原文: http://www.hengtianyun.com/download-show-id-79.html
OpenStack的Resize(升级)功能,我们可以改变虚拟机的CPU核数、内存及磁盘大小,当然虚拟机只能向上升级,不允许向下降级。通过分析源代码,我们发现Resize的过程其实就是冷迁移的过程,Resize多传进去了一个flavor参数。下面将分析OpenStack升级虚拟机和冷迁移的功能。
一、 前端入口
(一) Resize
/usr/share/openstack-dashboard/openstack_dashboard/dashboards/project/instances/workflows/resize_instance.py
从上面的代码可知,传了两个相关参数进去,第一个为虚拟机id(instance_id),第二个为升级的flavor。继续深入api.nova.server_resize
/usr/share/openstack-dashboard/openstack_dashboard/api/nova.py
从代码可知,利用novaclient客户端,向后端发出升级请求
(二) 冷迁移
/usr/share/openstack-dashboard/openstack_dashboard/dashboards/admin/instances/tables.py
前段通过api.nova.server_migrate发起迁移请求,其中参数obj_id就是虚拟机的id,深入api.nova.server_migrate
/usr/share/openstack-dashboard/openstack_dashboard/api/nova.py
从代码可知,利用novaclient客户端,向后端发出迁移请求
二、 后端响应
当novaclient发出请求时,一般由nova-api组件作出响应。我们将分别分析nova-api如何对resize和冷迁移进行响应。
(一) Resize
对Resize请求进行响应的函数位于文件
/usr/lib/python2.7/dist-packages/nova/api/openstack/compute/servers.py
继续深入self._resize()函数
从上述代码可知,最后通过compute_api.resize进行调用,它传了instance和flavor_id两个参数进去
(二) 冷迁移
/usr/lib/python2.7/dist-packages/nova/api/openstack/compute/contrib/admin_actions.py
从代码可知,冷迁移也调用了compute_api.resize(),相比Resize功能,它只传了instance一个参数进去
(三) Resize 和冷迁移的共同过程
下面将从compute_api.resize()开始分析,这段代码位于文件
/usr/lib/python2.7/dist-packages/nova/compute/api.py
/usr/lib/python2.7/dist-packages/nova/conductor/api.py
Nova-conductor组件响应请求
/usr/lib/python2.7/dist-packages/nova/conductor/manager.py
函数 _cold_migrate()
通过上述代码我们发现,首先是通过rpc调用nova-scheduler组件调度最优节点。调度算法分为两个阶段,即filter和weight。首先是过滤(filter),从所有的主机中找到符合实例运行条件的主机,然后从过滤出来的主机中,找到最合适的一个主机。
过滤阶段系统默认调用的filter主要包括RetryFilter、AvailabilityZoneFilter、RamFilter、ComputeFilter、ComputeCapabilitiesFilter、ImagePropertiesFilter,其中比较重要的filter包括AvailabilityZoneFilter和RamFilter,AvailabilityZoneFiter保证了调度发生在同一个zone,RamFilter确保了内存是否足够,默认情况下,ram的扩大系数为1.5,也就是假如物理内存为100G,内存被虚拟为150G,通过nova.conf配置文件,我们可以改变扩大系数。此外,通过配置文件,我们还可以改变调用的过滤器,除了上述过滤器外,我们还可以使用CoreFilter、DiskFilter、IoOpsFilter等。这些都是系统自带的过滤器,我们也可以根据需求,自己构造过滤器。
Weight阶段,从它做的工作来看,就是从符合条件的主机中选择“最合适”的主机,这个选择的过程是通过“评分”来实现的。现阶段的weight很简单,主要通过RAMWeigher进行权衡,剩余内存越大,权值越大。
当上述工作完成后,若未挑选出合适的节点,Resize过程结束,系统报错,若挑选出了合适节点,开始Resize流程,首先,rpc调用目的节点的nova-compute,即self.compute_rpcapi.prep_resize。
目的节点nova-compute开始响应
/usr/lib/python2.7/dist-packages/nova/compute/manager.py(2885)_prep_resize()
在prep_resize阶段,主要保存了虚拟机Resize前后的状态,最后通过rpc调用源节点的nova-compute,即self.compute_rpcapi.resize_instance
/usr/lib/python2.7/dist-packages/nova/compute/manager.py(3020)resize_instance()
上述代码,一个比较重要的过程就是迁移磁盘文件,该功能通过self.driver.migrate_disk_and_power_off这个函数实现,我们可以具体看一下这个函数
/usr/lib/python2.7/dist-packages/nova/virt/libvirt/driver.py(4487)migrate_disk_and_power_off()
通过上述步骤,成功把虚拟机的磁盘文件复制到了目的节点上,开始迁移的最后一步,创建虚拟机这一步通过rpc调用目的节点的nova-compute实现,即self.compute_rpcapi.finish_resize,其具体代码如下。
/usr/share/pyshared/nova/compute/manager.py:3153
/usr/lib/python2.7/dist-packages/nova/compute/manager.py(3073)_finish_resize()
/usr/lib/python2.7/dist-packages/nova/virt/libvirt/driver.py
通过self._create_domain_and_network就成功创建了虚拟机。
一、 不足与改进
通过对Resize的分析,我们发现有以下几个缺陷
1) AvailabilityZoneFilter
迁移过程中,会出现跨域的resize,availabilityZoneFilter好像并没有起到过滤错误,这是由于我们创建虚拟机时,虚拟机的域选择为ramdom,因此AvailabilityZoneFilter过滤器会对所有域的主机都放行,导致虚拟机升级到别的域域上去。
2) 镜像复制过程
迁移过程中,先会在源节点将增量镜像和base镜像进行合并,然后在复制到目的节点上,合并的过程比较耗时,我们可以直接将增量镜像复制到目的节点,然后下载base镜像,最后做一次rebase即可。