前篇讲了hypervisor概述及其管理,但是nova创建一个虚机都要给哪些模块交互呢?
在OpenStack中创建实例的大致流程为:
[1,2]用户通过Dashboard界面或命令行发起实例创建请求,Keystone从请求中获取用户相关信息并进行身份验证;
[3] 验证通过后,用户获得认证Token,实例创建请求进入Nova-api;
[4,5] 在向Keystone验证用户Token有效后,Nova-api([6,7]将信息存入Nova DB,[8]然后将请求放入Queue消息队列)[9]将请求转入Nova-scheduler;
Nova-scheduler([10,11]从Nova DB获取虚机信息)进行实例创建目的主机的调度选择,目标主机选取完成后,([12]将请求放入Queue消息队列)[13]请求转入Nova-compute;
Nova-compute([14]将请求再次放入Queue消息队列)与Nova-conductor[15]([16,17]从Nova DB获取虚机信息)交互以获取创建实例的信息,在成功获取实例信息后,Nova-compute[18,14]分别与Glance[19,21](glance-api)、Neutron[24,22](neutron server)和Cinder[25,27](Cinder-api)交互以获取镜像资源、网络资源和云存储资源;
一切资源准备就绪后,Nova-compute便通过Libvirt API与具体的Hypervisor交互[28]并创建虚拟机。
[20,23,26]分别为Glance(glance-api)、Neutron(neutron server)和Cinder(Cinder-api)收到nova-compute请求,将其token带到keystone进行验证,验证通过后再处理流程。
从nova创建虚机的流程看出来涉及到模块包括Keystone,nova的nova-api/nova-scheduler/nova-conductor/nova-compute/glance/neutron/cinder。下面从每个模块的角色来讲述各自的实现,见1、2、3、4、5。创建虚机过程中的状态变更见6。
1.Keystone工作流程
任何终端用户在与OpenStack的服务项目交互时,第一步便是进行身份认证与授权,而Keystone负责OpenStack全部项目的认证与授权任务。Nova-api/glance-api/neutron-server/glance-api都是首先和keystone交互,获取token或验证token成功后再继续业务逻辑处理。
Nova客户端通过Keystone的身份验证(用户名、密码和项目project,可能还有https的证书),则Keystone为其生成授权Token,并将此Token存储到后端数据库中。Keystone的后端数据库可以是SQL数据库,也可以是如Memcache这样的缓存系统。为了快速响应后续OpenStack服务组件发起的Token核实过程,建议尽量使用基于内存的缓存系统作为Keystone的后端存储数据库。Keystone的身份验证过程可以在本地进行,也可以通过LDAP服务器进行身份验证,以nova客户端为例,原理图如下
2.Nova-api工作流程
Nova-api向Keystone验证Token的有效性成功后,Nova-api开始判断实例创建请求所携带的参数是否有效合法:
1) 检查虚拟机名字是否符合命名规范;
2) 使用的虚拟机模板flavor_id在数据库中是否存在;
3) 使用的镜像image_uuid是否是有效的uuid格式;
4) 检查instance、vCPU、RAM的数量是否超出了配置文件中的限制,通常每个Project拥有的资源都是有限的;
5) 检查相关metadata的长度是否超过限制,inject_files的数目是否超过限制,一般情况下这些参数都为空;
6) 检查请求中的network是否存在且可用;
7) image和flavor是否存在且可用,同时还会检测请求中flavor的磁盘是否满足image需求等;
当所有资源检查都通过后,Nova-api便在nova数据库中初始化虚拟机相关的记录(intial entry),主要包括instance、block_device_mapping和quota等记录,并将instance记录中的vm_states字段设为building,task_state字段设为scheduling。
然后Nova-api调用Nova-conductor并将请求传递到消息队列(MQ)中。由于Nova-api将请求以RPC cast的方式发送给Nova-conductor,而cast()方法发送的请求并不会返回消息,因此Nova客户端此时只会接收到请求已被接受的返回,但是具体的虚拟创建过程还在后台继续执行,而Nova客户端可以查到的虚拟机vmstate为building,task_state为scheduling(估计是从数据库中查到的,其他信息没有返回就查不到)。
3.Nova-conductor工作流程
在Nova各个组件中,除Nova-api需要接受外部请求外,其他组件仅进行彼此之间的交互调用,并且组件之间的交互以RPC调用的方式通过消息队列来实现。
由于Nova-conductor提供了build_instances()这个RPC方法,因此一直处于消息队列监听状态,一旦监听的队列有消息进入,Nova-conductor便开始执行build_instances()方法。
Nova-conductor向Nova-schduler发出RPC call调用,并要求其返回计算节点调度结果,在收到Nova-scheduler的调度结果后,Nova-conductor的build_instances()方法将请求传递到Nova-compute的消息队列中。
4.Nova-scheduler工作流程
Nova-scheduler的功能是负责监听消息队列,并在获取消息队列之后进行计算节点的调度选取,同时将调度结果传递给消息队列。
为了获取创建实例的目标主机,Nova-conductor会向Nova-scheduler发起RPC call调用,并调用Nova-scheduler的select_destin-ations()方法;Nova-scheduler在消息队列中接收到调用消息后,根据nova.conf配置文件中关于Filters和Weight的配置参数对计算节点主机列表进行过滤和加权调度,在这个过程中,Nova-scheduler需要访问数据库以获取节点相关的信息;在获取信息后,Nova-scheduler便开始进行节点调度,默认使用的调度驱动为FilterScheduler,调度完成之后,将节点调度结果传递到消息队列,以完成Nova-conductor的RPC call调用过程。
5.Nova-compute工作流程
Nova-compute是Nova服务项目中最复杂和最关键的组件,运行Nova-compute的节点称为计算节点,通常Nova-compute部署在独立的计算节点上,并与Nova项目的其他组件分开部署。在实例创建过程中,Nova-compute随时监听topic:compute-computeN(computeN为计算节点名称)消息队列,在监听到Nova-conductor传递的实例创建请求后,Nova-compute开始启动内部工作流程以响应实例创建请求。在Nova-api的工作流程中,请求中创建实例所需的镜像、网络和存储等资源已经做过有效性和可用性的检查,因此Nova-compute将直接与Glance交互以获取镜像资源,与Cinder交互获取块存储资源。如果配置了Ceph块存储或对象存储服务,Nova-compute还会与Ceph RADOS进行交互以访问Ceph存储集群。Nova-compute与Glance、Cidner和Ceph的交互访问流程如图所示
在获取镜像和存储资源后,Nova-compute还需与OpenStack的网络服务项目Neutron进行交互访问以获取网络资源。由于网络资源的有效性和可用性已经在Nova-api工作流程中完成,这里主要是获取虚拟机的Fixed IP等网络资源。Nova-compute与Neutron的交互过程如图。
在准备好常见实例所需的一切资源后,Nova-compute将通过Libvirt与对应的Hyper-visor API进行交互,并通过Libvirt API接口进行虚拟机的创建工作。Nova-compute与Libvirt交互创建实例的过程如图。
6. Nova实例状态变更
在虚拟机实例的创建和运行维护过程中,Nova使用三个变量来描述虚拟机当前的状态,分别为vm_state、power_state和task_state。其中,power_state代表虚拟机电源状态,其本质上反应的是Hypervisor的状态,其状态值遵循“由下至上(bottom-up)”的变更过程,即先是底层计算节点上Hypervisor状态变更,然后上层数据库对应值变更;vm_state反应的是基于API调用的一种稳定状态,其状态变更比较符合用户的逻辑思维,是一种由上至下(top-down)的API实现过程;task_state代表的是API调用过程中的过渡状态,反映了不同阶段所调用API对实例进行的操作。
1).power_State
power_state是Nova程序调用特定虚拟机上的虚拟驱动所获取的状态。数据库中关于特定实例的power_state值仅是虚拟机最近一段时间的快照值,并不能真正反映当前虚拟机的实际power_state,虚拟机当前power_state的实际值位于Hypervisor中。
计算节点首先报告虚拟机power_state已经更新,然后再刷新数据库中的power_state字段值。power_state状态值衍生自Libvirt(其中BLOCKED状态值也被丢弃),其本质上代表的是RUNNING状态,SHUTOFF被映射为SHUTDOWN状态,FAILED被映射为NOSTATE状态,因此power_state目前有RUNNING、SHUTDOWN和NOSTATE三种状态。
2).vm_State
vm_state状态值是对虚拟机当前稳定状态的描述,而不是过渡状态。也就是说,如果针对特定虚拟机已经没有API继续调用,则应该用vm_state来描述此时虚拟机的稳定状态。
vm_state状态值更新的前提是针对此虚拟机有任务发生,并且任务成功完成,同时task_state被置为NOSTATE。如果没有API调用发生,则vm_state状态值绝对不会改变;如果对虚拟机的操作任务失败,但是成功回滚(rollback),则vm_state状态值也不会改变;如果不能回滚成功,则vm_state被置为ERROR状态。
3).task_state
task_state代表的是过渡状态,并且与调用的API函数密切相关,其状态值描述了虚拟机当前正在执行的任务。只有对虚拟机发起了操作任务时,才会有task_state状态值出现,而当vm_state处于稳定值时,task_state通常为NOSTATE。task_state有5种状态包括Scheduling、None、Networking、Block_Device_Mapping和Spawning。
其他服务说明
如果要使用虚拟网络控制台VNC与实例交互,则Nova-consoleauth和Nova-novncproxy是必须的;
如果使用AWS风格API,则Nova-cert和Nova-objectstore是必须的。
笔记整理来自山金孝的《OpenStack高可用集群(上册):原理与架构》8.6章节,如有侵权请通知删除