分类: 云计算
2019-02-13 14:48:04
创建虚拟机是OpenStack最基本的功能,也是较为核心的功能。整个流程以Nova组件为中心,期间会涉及到与其他组件的交互,如Keystone、Glance、Neutron、Cinder。下面就详细介绍一下虚拟机的整个创建流程(OpenStack Ocata版本)。
可以将整个过程大致分为三个阶段,第一个阶段为从novaclient到nova-api,第二个阶段为从nova-api到nova-compute,第三个阶段为从nova-compute到底层的Hypervisor。
1. 从novaclient到nova-api
创建虚拟机一般是从界面或命令行发出请求开始的,两种方式都会借助novaclient向nova-api发出HTTP请求。nova-api暴露了一组RESTful的API,以接受novaclient发出的各种请求。创建虚拟机时需要向{your_compute_service_url}/servers发送POST请求。在使用命令行创建时可使用“--debug”选项来跟踪这些HTTP请求,如使用nova --debug boot。
为了保证对OpenStack各个服务的安全访问,在请求创建虚拟机之前,novaclient会先向Keystone发送用户的用户名、密码、域名信息来申请一个有效的token,之后向nova-api发送请求的头部就会带有token信息。nova-api收到请求后会向Keystone验证token的有效性,token验证通过后,nova-api会向数据库写入虚拟机的初始数据。Keystone在验证token时,会先去缓存数据库memcached中查找,若缓存未命中再去数据库中的token表查找对应记录。由于OpenStack各个组件之间都需要token验证,并且token存在有效期,过期的token不会自动清理,所以随着时间的增长token表的记录会越来越多,那么在查询token表时就可能存在慢查询。除了使用memcached做缓存之外,我们还可以使用keystone-manage token_flush对token表做定期清理,避免数据库慢查询。
2. 从nova-api到nova-compute
nova-api工作结束后会向nova-conductor发起RPC请求,请求创建虚拟机。nova-conductor是nova-compute和数据库之间的桥梁,它可以防止nova-compute直接访问数据库,从而提高对数据库访问的安全性。随着nova-conductor功能的完善,它也接管了nova-compute中一些耗时较长的任务,如build_instances、resize_instance、live_migrate_instance等。
nova-conductor收到请求后首先以rpc.call的方式请求nova-scheduler完成虚拟机创建的调度工作。nova-scheduler使用过滤和权重计算的方法来选定创建虚拟机的主机,过滤器和权重计算方法可以在nova.conf中配置。nova-scheduler自己会维护一份计算节点数据,并根数据库中对比。调度完成后将选定的host返回给nova-conductor,由nova-conductor向nova-compute发起rpc.cast的创建请求。
一般来说,OpenStack各个组件之间会通过RESTful API进行通信,而组件内部的各个服务进程之间则是通过基于AMPQ的RPC方式进行通信。RPC方式又分为两种,rpc.cast和rpc.call,rpc.call为request/response方式,多用于同步场景;而使用rpc.cast方式发出请求后则无需一直等待响应,但之后需要定期查询执行结果,一般用于异步场景。实现RPC通信还需借助消息队列,OpenStack将其使用的通信方式都封装在公有库oslo_messaging中,目前支持的消息队列包括Rabbitmq、Zeromq、Kafka等。
以nova-api和nova-conductor之间的通信为例。nova-conductor服务在启动时会注册一个RPC server等待处理请求,nova-api发送创建虚拟机的rpc请求时会先创建一个topic publisher用于话题发布,发布的topic为conductor,method为build_instance,然后publisher将消息发送给话题交换器,话题交换器再根据routing_key转发给绑定的消息队列,最后由topic consumer接收并调用nova-conductor manager中的build_instance方法处理。
创建虚拟机过程中的所有HTTP请求和RPC请求均会占用服务器的TCP连接数。一般来说,作为客户端的TCP连接数最大为65535个,但也会受到内存、文件描述符等因素的影响,所以为保证正常创建虚拟机,可以使用监控工具来监控服务器的资源或进行TCP连接的调优。
3. 从nova-compute到Hypervisor
nova-compute收到请求后再分别调用glanceclient、neutronclient和cinderclient向glance、neutron、cinder获取创建虚拟机的镜像、网络、存储信息,认证过程与nova-api类似。
此时虚拟机的vm_state为Building,虚拟机还只存在于数据库中,完成最后的创建还要交给Hypervisor。OpenStack支持的Hypervisor包括Libvirt、hyperv、xen、vmware等,其中对libvirt管理的KVM的支持性最好,这也是OpenStack默认的hypervisor。当libvirt收到创建请求时,会拉取镜像创建根存储、根据请求中的虚拟机信息生成xml文件,再根据xml文件创建网络(如ovs上创建端口)、define domain、start domain等,直到libvirt检测到虚拟机状态为running则创建成功。
当OpenStack使用Ceph共享存储时,镜像无需下载到本地再上传到后端,而是直接使用clone,配合Ceph支持的COW技术几乎可以完成虚拟机的秒级启动。前提是使用raw格式的镜像,因为Ceph不支持从qcow2的镜像引导,若使用qcow2镜像创建虚拟机,则需要将镜像下载到本地转换成raw格式再上传,不仅增加启动时间,而且还可能因为空间不足无法完成镜像的格式转换从而造成虚拟机启动失败,所以建议直接使用raw格式的镜像创建虚拟机。
为避免创建过程中服务的单点故障,建议使用keepalived+haproxy或者pacemaker+haproxy的方式实现OpenStack各个服务的高可用。
补充: