随着存储技术的不断发展,云计算中的存储后端种类越来越多。而在不同存储后端之间进行存储热迁移则是和普遍的需求。在 OpenStack 中,云硬盘(volume)支持在不同后端之间进行数据移。具体的可分为两类,一种是云硬盘未挂载的,另一种是已经挂载的。前一种比较简单,后面一种就是存储热迁移了。下面对这两种方式在 OpenStack 中具体实现简单介绍,此外还介绍如何实现把虚拟机从本地启动的方式热迁移到云硬盘中。
未挂载云硬盘的迁移
detached volume 指未挂载到虚拟机上的 volume,状态为available。对 detached volume 进行迁移的流程比较简单,直接将数据从原来的 volume 拷贝到新的 volume 就可以了。在迁移的过程中需要注意 volume 状态的变化、对异常的处理,保证 volume 状态的一致性。整个流程如图1所示。
图1 detach volume迁移流程图
下面简单介绍 Cinder(即 OpenStack 中 volume 的管理组件)的实现细节。
- cinder-api 接收 migrate 请求
cinder-api 收到 client 发来的 migrate 请求后,经过 paste.deploy 和 route 的映射,交给 cinder.api.contrib.admin_actions.API 类中的 migrate_volume 方法。该方法首先会检查迁移的目的 host 上的 cinder volume 服务是否正常,然后将目标 volume 的 migration_status 设为migrating。当这些预处理全部完成后,cinder api 通过 rpc 将请求转到 cinder-scheduler。 - cinder-scheduler 对目的 host 进行检查
cinder-scheduler 收到 cinder-api 发过来的请求后,会对迁移的目的 host 进行检查,根据配置文件对 host 进行容量等检查,以判断该 host 能否创建新的 volume。 - cinder-volume 处理 migrate
当 source host 的 cinder-volume 服务收到处理请求后,会执行以下三个操作:
通过 rpc 调用目的 host 上的 cinder-volume 服务新建一个 volume;
当新的 volume 创建完毕后,使用 dd 命令进行复制;
复制完成后,对 volume 的状态进行修改并删除旧的 volume。
已挂载的云硬盘的热迁移
attached volume 指已经挂载到虚拟机,状态是 in-use 的 volume,对 attached volume 进行热迁移需要在不中断虚拟机业务的同时进行 volume 的复制和切换。OpenStack 中使用 libvirt 的 rebase方法来实现 volume 的热迁移。OpenStack API 流程处理如图2所示。
图2 attach volume热迁移整体流程
如图2所示,attached volume 需要 cinder 和 nova 两个组件共同协作才能完成迁移。下面简单介绍 API 处理流程。
- cinder 向 nova 发起 swap volume 请求
cinder-volume 服务收到 volume migration 请求后,如果发现 volume 状态为 attached,则通过 novaclient 向 nova 发起 swap volume 请求。 - nova api 对请求进行预处理
nova-api 收到该请求后,通过 paste.deploy 和 route 的引导和映射,请求进入 VolumeAttachmentController 的 update方法。该方法先会进行例行检查,如对新旧 volume 的状态进行判断,确保能够执行 detach 和 attach 操作;对虚拟机的 Block Device Mapping 进行检查;中间还会调用 cinderclient 来更新新旧 volume 的状态。这部分的代码逻辑主要是对资源在数据库中的状态进行判断。然后,nova-api 通过 rpc 将请求提交到虚拟机所在主机的nova-compute 服务中,这时候就开始执行 volume 的热迁移了。 - nova-compute 调用 libvirt 执行具体的热迁移操作
nova.compute.manager. ComputeManager 类中的 swap_volume 方法是真正执行的入口,主要流程如图3所示。图3 swap volume操作流程图
- cinder-volume 处理 volume 热迁移后的一些状态更新
经过 nova 的 swap volume 步骤后,新旧 volume 之间的数据已经复制并同步,并且虚拟机已经使用新的 volume 了。接下来 cinder 需要处理一些数据库相关的信息更新。cinder 会交换新旧 volume 在数据库中的元信息,具体交换的内容为 provider-location 和volume-type 这两个字段,该交换过程如图4所示图4 volume信息交换示意图
现在需要将旧的 volume 的状态改回 attached 并添加新的 attachment 记录,然后把新的 volume 的记录删除。
Ceph RBD 支持
OpenStack 社区目前对 volume 的迁移主要考虑了 LVM 等 iSCSI 协议的后端。对 Ceph RBD 后端的支持比较有限,目前还不支持从 LVM 迁移到 RBD,这时需要进行进一步开发。目前我们进行了相关的测试,使得可以热迁移到 Ceph RBD。
虚拟机系统盘热迁移
虚拟机如果一开始就是从云硬盘启动的,那么我们可以方便地将虚拟机在各个存储后端直接迁移。然而虚拟机如果是从本地镜像启动的,我们想要迁移就比较麻烦了。一种简单的方式是迁移整个虚拟机到其他存储后端的 nova 计算节点上。这里我们介绍另一种方法,直接将虚拟机的本地启动镜像迁移到云硬盘中,同时这个云硬盘还能使用上述的热迁移的方法,进一步迁移到其他存储上。
Libvirt 的 rebase 功能
在讲如何实现迁移到云硬盘功能之前,我们来回顾下 volume 热迁移时提到的 libvirt rebase 方法。Libvirt rebase 主要是用到了 QEMU live block copy 的功能,这个具体在 libvirt 中如何实现我们暂且不讨论。我们来看下 nova 在 swap volume 时如何调用 libvirt rebase 的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
注意到 _swap_volume 函数并没有指定旧的磁盘是否必须是 cinder 提供的 volume,如果被迁移的磁盘是本地的系统盘呢?其实也是可以的。
实现迁移系统盘到云硬盘中
考虑到 _swap_volume 函数也能支持将本地的系统盘迁移到 volume 上,我们可以实现新的 nova API 来调用此函数。
基本步骤如下:
- 调用 cinder 创建新的 volume
- 调用 libvirt driver 来进行热迁移
- 对 nova 中虚拟机的信息进行更新,将虚拟机的状态改为从云硬盘启动
转载自:http://blog.umcloud.com/openstack-block-live-migrate/