本帖最后由 howtodown 于 2014-1-28 16:52 编辑
Nova是OpenStack云中的计算组织控制器。支持OpenStack云中实例(instances)生命周期的所有活动都由Nova处理。这样使得Nova成为一个负责管理计算资源、网络、认证、所需可扩展性的平台。但是,Nova自身并没有提供任何虚拟化能力,相反它使用libvirt API来与被支持的Hypervisors交互。Nova 通过一个与Amazon Web Services(AWS)EC2 API兼容的web services API来对外提供服务。
功能和特点:
实例生命周期管理
管理计算资源
网络和认证管理
REST风格的API
异步的一致性通信
Hypervisor透明:支持Xen,XenServer/XCP, KVM, UML, VMware vSphere and Hyper-V
OpenStack计算的组成:
Nova 云架构包括以下主要组件:
- API Server (nova-api)
- Message Queue (rabbit-mq server)
- Compute Workers (nova-compute)
- Network Controller (nova-network)
- Volume Worker (nova-volume)
- Scheduler (nova-scheduler)
- API Server(nova-api)
API Server
对外提供一个与云基础设施交互的接口,也是外部可用于管理基础设施的唯一组件。管理使用EC2 API通过web services调用实现。然后API Server通过消息队列(Message Queue)轮流与云基础设施的相关组件通信。作为EC2 API的另外一种选择,OpenStack也提供一个内部使用的“OpenStack API”。
Message Queue(Rabbit MQ Server)
OpenStack 节点之间通过消息队列使用AMQP(Advanced Message Queue Protocol)完成通信。Nova 通过异步调用请求响应,使用回调函数在收到响应时触发。因为使用了异步通信,不会有用户长时间卡在等待状态。这是有效的,因为许多API调用预期的行为都非常耗时,例如加载一个实例,或者上传一个镜像。
Compute Worker(nova-compute)
Compute Worker处理管理实例生命周期。他们通过Message Queue接收实例生命周期管理的请求,并承担操作工作。在一个典型生产环境的云部署中有一些compute workers。一个实例部署在哪个可用的compute worker上取决于调度算法。
Network Controller(nova-network)
Network Controller 处理主机地网络配置。它包括IP地址分配、为项目配置VLAN、实现安全组、配置计算节点网络。
Volume Workers(nova-volume)
Volume Workers用来管理基于LVM( Logical Volume Manager )的实例卷。Volume Workers有卷的相关功能,例如新建卷、删除卷、为实例附加卷,为实例分离卷。卷为实例提供一个持久化存储,因为根分区是非持久化的,当实例终止时对它所作的任何改变都会丢失。当一个卷从实例分离或者实例终止(这个卷附加在该终止的实例上)时,这个卷保留着存储在其上的数据。当把这个卷重附加载相同实例或者附加到不同实例上时,这些数据依旧能被访问。
一个实例的重要数据几乎总是要写在卷上,这样可以确保能在以后访问。这个对存储的典型应用需要数据库等服务的支持。
Scheduler(nova-scheduler)
调度器Scheduler把nova-API调用映射为OpenStack组件。调度器作为一个称为nova-schedule守护进程运行,通过恰当的调度算法从可用资源池获得一个计算服务。Scheduler会根据诸如负载、内存、可用域的物理距离、CPU构架等作出调度决定。nova scheduler实现了一个可插入式的结构。
当前nova-scheduler实现了一些基本的调度算法:
随机算法:计算主机在所有可用域内随机选择
可用域算法:跟随机算法相仿,但是计算主机在指定的可用域内随机选择。
简单算法:这种方法选择负载最小的主机运行实例。负载信息可通过负载均衡器获得。
---------------------------------------------------------------------------------------------------------------------------------------------------
对于Nova,我们先来看一张图:
总的来说,nova的各个组件是以数据库和队列为中心进行通信的,下面对其中的几个组件做一个简单的介绍:
Queue,也就是消息队列,它就像是网络上的一个hub,nova各个组件之间的通信几乎都是靠它进行的,当前的Queue是用RabbitMQ实现的,它和database一起为各个守护进程之间传递消息。
database存储云基础架构中的绝大多数状态。这包括了可用的实例类型,在用的实例,可用的网络和项目。当前广泛使用的数据库是sqlite3(仅适合测试和开发工作)、MySQL和PostgreSQL。
nova-compute负责决定创造虚拟机和撤销虚拟机,通过运行一系列系统命令(例如发起一个KVM实例,)并把这些状态更新到nova-database中去,其过程相当复杂,但是基本原理很简单。
nova-schedule负责从queue里取得虚拟机请求并决定把虚拟机分配到哪个服务器上去。schedule的算法可以自己定义,目前有Simple (最少加载主机),chancd(随机主机分配) ,zone(可用区域内的随机节点)等算法。
nova-volume负责记录每一个计算实例,相当于一个计算请求吧,并负责创建,分配或撤销持久层容器(Amazon的,iSCSI,AoE等等)给这些compute instances。
nova -netwok负责处理队列里的网络任务。
nova-api守护进程是OpenStack Compute的中心。它为所有API查询提供一个入口, 并且同时支持OpenStack API 和 Amazon EC2 API。
为了看看nova是如何工作的,我们可以以启动一个实例为例来进行说明,因为启动一个新的instance涉及到很多openstack nova里面的组件共同协作。
其中:
API :处理客户端的请求,并且转发到 Queue和Database中。
Scheduler:选择一个host去执行命令
nova-compute :启动和停止实例,附加和删除卷等操作
nova-network:管理网络资源,分配固定IP。
接下来就是真正的过程了,先从API开始:
API
例如我们输入一个命令:euca-run-instances -k test -t m1.tiny ami-tiny 它会执行以下操作:
查看这种类型的instance是否达到最大值
给scheduler发送一个消息(实际上是发送到Queue中)去运行这个实例。
Schedule
调度器接收到了消息队列Queue中API发来的消息,然后根据事先设定好的调度规则,选择好一个host,之后,这个instance会在这个host上创建。
Compute
真正去创建一个instance的操作是由Compute完成的,而这个过程中computer组件与Glance密不可分,如图所示:
---------------------------------------------------------------------------------------------------------------------------------------------------
想了解云计算可以做什么,就意味着你必须掌握虚拟化概念。通过虚拟化,你可以在虚拟机上而不是物理计算机上运行操作系统和应用程序。要使用虚拟机,你必须提供一个镜像文件,它包含了运行虚拟机所需的信息:包括要运行的操作系统、用户的登录名和密码、储存在系统上的文件等等。在 OpenStack 核心项目中,Nova 项目可谓是核心中的核心。正如 OpenStack 网站所介绍的,Nova 是 IaaS 系统的主要部分, 旨在为大规模的配置和管理虚拟机实例提供一个框架。与 Amazon 的EC2 服务的功能类似,它允许用户使用自己的镜像文件,通过可编程 API 创建、管理和销毁虚拟服务器。Nova 生产环境的配置模式
从功能上看, Nova 平台中有两类节点: 控制节点和计算节点,其角色由安装的服务决定,控制节点包括网络控制 Network、调度管理 Scheduler、api服务、存储卷管理、数据库管理、身份管理和镜像管理等,计算节点主要提供 nova-compute 服务。节点之间使用 AMQP 作为通讯总线,只要将 AMQP 消息被写入特定的消息队列中,相关的服务就可以获取该消息进行处理。由于使用了消息总线,因此服务之间是位置透明的,你可以将所有服务可以部署在同一台主机上,即 All-in-One(一般用于测试),也可以根据业务需要,将其分开部署在不同的主机上。用在生产环境 Nova 平台配置一般有三种类型:最简配置:需要至少两个节点,除了 nova-compute 外所有服务都部署在一台主机里,这台主机进行各种控制管理,即控制节点。
图1-1 OpenStack 双节点架构
标准配置:控制节点的服务可以分开在多个节点,标准的生产环境推荐使用至少 4 台主机来进一步细化职责。控制器、网络、卷和计算职责分别由一台主机担任。
图1-2 OpenStack 多节点架构
高级配置:很多情况下(比如为了高可用性),需要把各种管理服务分别部署在不同主机,(比如分别提供数据库集群服务、消息队列、镜像管理、网络控制等),形成更复杂的架构:
图1-3 OpenStack 高级架构
这种配置上的弹性得益于 Nova 选用 AMQP 作为消息传递技术,更准确地说,Nova 服务使用远程过程调用(RPC)彼此进行沟通。。AMQP 代理(可以是 RabbitMQ 或 Qpid)位于任两个 Nova 服务之间,使它们以松耦合的方式进行通信。因此不单 API 服务器可以和服务进行通讯,服务之间也可以相互通讯,如计算服务和网络服务、卷服务进行通讯以获得必要的资源。每一个 Nova 服务(Compute、scheduler 等等)在初始化时会创建两个消息队列:其路由选择关键字分别为“NODE-TYPE.NODE-ID”(如:Compute.)和“NODE-TYPE”(如 Compute)。后者则接收一般性消息,而前者则只接收发给特定节点的命令,例如执行 “euca-terminate instance”, 很明显,该命令只应发送给运行该实例的某个计算节点。无论是那一种生产配置模式,都允许用户根据需添加更多的计算节点,由 N 台服务器执行计算任务。
鸟瞰 OpenStack
在一个经典部署的 OpenStack 中,Nova、Swift 和 Glance 这三大组件需要协同交互,这里我们通过启动实例这样一个典型操作来看看它们之间的交互:- 1. 客户端利用 API 发出请求,要求启动一个实例。
- 2. 该请求通过一系列检查 (比如配额、权限等等)后,由 Nova API 服务器进行处理。
- 3. Nova API 服务器通过队列将启动实例的任务交给了 Nova 调度器。
- 4. 调度器根据调度规则决定在哪运行实例 — 即从 N 个计算节点中选取符合规则的节点
- 5. 调度器通过队列向指定的计算节点发出消息让其开始创建实例
- 6. 计算节点通知客户端实例开始创建,现在客户端可以继续其它任务
- 7. 在后台,计算节点利用 Glance API 在 Glance 注册表中查找所需的镜像文件
- 8-9. Glance API 向计算节点返回该镜像文件的物理位置和元数据
- 10. 得到了物理位置等信息,计算节点就可以 Swift Proxy 请求镜像文件
- 12-13. Swift Proxy 从 Swift 工作单元中获得映象,并将其传递给计算节点
获得了镜像文件之后,计算节点就可以利用 libvirt API 来与被支持的Hypervisors交互:- 计算节点会在数据库中更新实例的详细信息,并调用 hypervisor 开始配置实例的块设备
- 计算节点向网络节点的队列发出消息以便为实例配置网络
- 一旦收到返回的网络信息,计算节点就开始最后的配置调整,并启动实例
- 创建实例完成之后,无论成功与否,结算节点都会更新数据库,并在消息队列中发出通知
各组件间的交互如图 1-4 所示:
图1-4 在 OpenStack 中启动实例
接下来我们来看一下 Nova 各部件在执行启动实例时的通讯过程。
Nova 部件间的通讯
最核心的 Nova 几个服务包括:API,计算服务,调度器和网络。API 是 Nova 的 HTTP 界面,计算服务则运行在每一台主机上负责与 hypervisor 通讯(通常每台主机有一个计算服务)。网络服务管理 IP 地址池并且与交换机、路由器、防火墙等相关服务通讯。调度器则负责既有的池中选择最适合的计算节点来负责运行新的实例(同时它也负责获取卷)。Nova 本身是按分布式应用程序进行架构的,在上一篇文章中,我们已经介绍了各个部件的功能,这里我们简单回忆一下:- API 服务器(nova-api): 处理用户请求并将之路由给云控制器
- 云控制器(Cloud Controller):nova-api的一个类,负责处理计算节点、网络控制器、 API 服务器和调度器之间的通讯
- 调度器:选择某一主机来运行命令
- 计算工作单元:管理计算实例:启动或终止实例、挂载或卸载卷等等…
- 网络控制器:管理网络资源:分配固定 IP 地址、配置 VLAN …
注意:云控制器不是 Nova 7个部件之一,它只是 API 服务器的一个内部类而已。为了方便叙述通讯过程,这里我们单独把它抽离出来。在 Nova 内部,启动实例的流程是这样的:首先 API服务器接收到来自用户的 run_instances 命令。 API服务器将该消息转发到云控制器(1)。我们知道这里需要进行验证以确保用户具有所需的权限。云控制器将消息发送给调度器(2)。调度程序将消息转换为一个随机的主机,并询问他开始一个新的实例(3)。在主机上抓起的消息(4)的计算工作。计算工人需要一个固定的IP,所以将消息发送到网络控制器(5,6,7,8)推出一个新的实例。
----------------------------------------------------------------------------------------------------------------------------------------------------
OpenStack Nova Service启动分析
Nova project下面具有多个service,api,compute,sceduler等等,他们的启动过程都几乎类似,这一篇博客就详细记录nova-sceduler的启动过程。文章中贴出的源码都是从OpenStack Folsom版截取过来的。
下面就开始分析nova-sceduler的启动过程了,后面还有涉及到启动之后,做的一些周期性工作,这部分可能与sceduler无关,是在compute中的,一次帖上来。
首先是解析启动脚本的参数,包括配置文件,设置日志,utils.monkey_patch现在不明白(为了能够使用高效的eventlet模块, 需要打些补丁),然后创建服务,最后启动服务,等待请求。 Service.Service.create(binary=’nova-scheduler)过程如下:
过程为获取host name,topic即为用来与rabbit通信的标识,为scheduler,manager为scheduler_manager,在flags中搜 索其对应的类名,其值在nova.conf中指定,默认值为nova.scheduler.manager.SchedulerManager ,report_interval为节点将状态报告给数据库的时间间隔,默认为10秒。Periodic_interval,执行周期性任务的周期。再开 始初始化service。
其中关键的manager,其中self.manager_class_name 为nova.scheduler.manager.SchedulerManager,通过importutils.import_class动态的导入 该对象,故manager_class是这 么一个对象。(记住,在python中,一切都是对象,有类型对象,实例对象,譬如int为一个类型对象,5则为一个实例对象,其类型是int,而int 的类型则为type。)然后,调用SchedulerManager的__init__函数完成初始化,注意SchedulerManager的 __init__函数的参数列表,有args和kwargs,所以host=self.host就成了kwargs的一项。
创建完service类之后,开始启动service。
其中workers为none,执行else语句,lanuch_server如下:
使用eventlet.spawn启动一个green thread,run_server如下:
开始启动server,其中start的关键代码如下:
首先获取一个到rabbitmq server的连接,然后再注册一个rpc_dispatcher,该对象与回调函数相关,接收到rabbitmq的消息后,再由它来处理,接着创建多个 consumer来接收特定topic的消息队列的消息,并设置好消息监听。 这样一个服务就启动来了,在后面还有设置周期性的task。
在初始化service的过程中,会调用importutils动态导入具体的manager,对于nova-compute,导入的则是 ComputeManager,该类的继承关系 是,ComputeManager,Manager.SchedulerDependentManager,Manager,nova.db.Base. 其中Manager包含ManagerMeta元类。可以参考RabbitMQ(三)中 的manager类关系图。 对Manager与ManagerMeta的分析如下,这块代码涉及到一个资源刷新的问题。对于metaclass的分析可以参考后面的python高级 中的metaclass最后一个例子分析。Manager具有一个类属性_periodic_tasks,是一个列表类型的属性,元素是各个需要周期执行 的task。在manager类创建时,因为使用到了metaclass,会首先检查每个具有_periodic_task属性的函数,该属性由装饰器 periodic_task装饰上的。
这部分的代码就是启动周期性的task。
LoopingCall初始化最关键的参数是f,即传递进一个函数。430行,就将service的report_state函数传递进去,然后调用start函数,下面是start函数的实现。
可以知道,start函数内部有一个闭包函数,然后启动一个greenthread的来执行这个内部函数,内部函数根据传递的参数,决定是否要推迟启动,然后开始周期性的执行传递进来的函数,即self.report_state和self.periodic_task.
查看report_state的代码,关键的如下:
主要的作用是周期性的更新数据库中的nova库service表的report_count字段,目前不知道该字段有什么作用!
再查看periodic_task函数,service.periodic_tasks函数最后会调用 self.manager.periodic_tasks,该函数在nova.manager.py中,该函数会去调用被periodic_task装饰 的函数,在nova-compute服务中,被periodic_task装饰的有_publish_service_capabilities函 数,_report_driver_status函数等等,report_driver_status读取host的相关信息,然后更新 capabilities,最后通过scheduler_rpcapi发送到scheduler服务去
|