参考:http://blog.ucloud.cn/archives/2375
在迁移过程中我们需要解决以下几个问题:
宿主机的选择;
磁盘镜像处理;
网络切换设置;
内存磁盘压力的处理等。
普通迁移优化
准备阶段
在迁移准备阶段,需要选择相同业务类型的宿主机,以便方便创建相同配置的虚拟机。该机型除了具有足够空闲内存和磁盘的物理机外,还需要考虑目标物理机的配置是否合适。特别是需要考虑CPU的型号和内核的版本号。
另外,考虑到迁移过程网络带宽有限,如果带宽被其他任务占用,就会使得迁移速度下降,甚至影响最终迁移的成功率。为此,除非物理机之间的网络带宽足够大,原则上并不允许在相同两台物理机之间进行多个并行的迁移任务,以便尽量确保在线迁移的成功率。
迁移阶段
在线迁移过程中需要迁移虚拟机的所有磁盘和内存数据,而且虚拟机在迁移过程中并不停机,这使得需要迁移更多的增量数据。如果能够减少数据的迁移量,就能够减少迁移时间,从而更快的实现云平台的资源动态调整和故障处理。
磁盘在物理机上是以文件方式存在的,这个文件是sparse文件,假设虚拟机的磁盘是100G,但实际使用了10G,那么这个磁盘文件在物理机上只占用了10G空间。如图 2�-1所示,但是原生的Qemu在迁移磁盘时并没有保持sparse特性,所以这个100G的磁盘迁移到目标物理机上后就实际占用了100G空间。这个对物理机的磁盘空间来说是非常浪费的,而且还严重影响迁移的完成时间。
如图2-2所示,在源端读到全0的块,就不发送到目标端,这样目标端就是跳着块来写一个文件,这样就保持了磁盘文件的sparse特性。同时,考虑到线上往往存在多种Qemu版本,还要考虑到原生的Qemu和打了这个patch的Qemu之间迁移机器如何保持sparse。为此,可以通过在Qemu中接收磁盘数据过程判断一个块是否全部为0,如果是就不实际写磁盘,即可解决。所有的零块数据都被跳过,不进行传输。
通过上述方法就可以忽略磁盘迁移过程中的零数据,大大减少传输的数据量。最终,通过Qemu的这些patch,还可以明显减少在线迁移的数据传输量和镜像文件的空间占用量。
存储盘优化。直接进行挂载卸载操作。不需要创建新盘进行数据copy。直接将盘转移过去。
迁移结束优化
如果用户产生的脏内存数据过多,就会使得迁移的增量数据传输时间一直大于最大停机时间,使得增量传输阶段不断进行循环迭代,导致整个迁移过程无法完成
由于用户产生脏内存数据的速度与虚拟机的vCPU被提交运行的时间有关,因此能够减少用户虚拟机vCPU执行时间可以阻止用户产生过多的内存脏数据,从而让迁移数据传输得以在内存脏数据产生之前的完成。
对Qemu的auto-converge功能进行优化,首先,提高Qemu的throttling迁移速度,避免迁移速度限制迁移的完成时间。其次,修改auto-converge的触发条件。在增量迁移数据时,如果产生脏数据的量大于上次产生传输数据量的50%,并重复发生多次,则自动触发自动auto-converge功能。该功能默认情况下,将削减20%的虚拟机vCPU执行时间,也就减低用户虚机vCPU的执行速度,并减少新增的脏数据。
在每次内存迭代开始时,它会根据之前的削减情况,决定后续削减粒度。如果新增脏数据仍然过多,它将重复削减10%的许可vCPU的运行时间,直至削减CPU直至99%,从而触发最后阶段的停机迁移,以完成迁移过程。
虽然这种优化会使得虚拟机的停机时间稍长,但是根据长期实践结果,整个迁移的停机时间仍然非常小(小于100ms),因此这项优化对提高迁移的成功率有重要意义。
压缩迁移优化
虽然Qemu的auto-converge功能可以在一定程度上解决用户内存负载对迁移的影响,提高迁移成功率,但如果用户产生的脏数据对vCPU的执行速度依赖不大,则会使迁移的增量数据传输时间一直大于最大停机时间,使整个迁移过程无法完成。考虑到内存负载高的用户,往往会反复修改某一内存页,这些内存页面很容易被压缩。为此,可以考虑在迁移内存数据前进行压缩。
如图 2-4所示,当前Qemu支持的XBZRLE压缩算法会将之前发送的内存页面维护在其内存缓存区内。在迁移内存页面时,会先查找该页面是否在其XBZRLE缓存内,如果在缓存内,则进行异或编码,只传输被压缩后的增量数据;如果没有,则直接传输内存页面。通过这个过程可以大大减少发送内存页面数据量,并提高内存迁移速度。
实际使用表明通过这种压缩方法可以提高高内存负载虚拟机的迁移成功率、并缩短迁移时间,同时CPU使用率提高也在合理范围内;对于普通内存负载虚拟机的迁移,几乎没有额外的CPU使用率消耗。后续还会结合底层硬件加速卡,并适时的开启多线程内存压缩迁移优化。
切换阶段
1. 源端paused优化
迁移的过程是由Qemu来具体执行,但是对于整个迁移过程的控制则是来自更上层的Libvirt。当Qemu在执行最后一步机器数据迁移切换时,两边的虚拟机都是处于paused状态。后续Libvirt将关闭源端SourceHost上的被迁移虚拟机,并拉起目标端DestHost上的对应虚拟机。
在线迁移的最大优点在于不能因为迁移失败而导致虚拟机关机,不管成功或者失败,都要保障虚拟机实例的存活(源端或目标端)。
2. OVS切换优化
此外,我们在迁移过程中观察到,在迁移即将完成时存在数秒网络中断的情况,这会导致用户业务出现短暂中断,使得后台的迁移过程对用户不透明。而且为减少对用户业务造成不利影响,往往需要事先和用户协调沟通迁移事项,限制了在线迁移的应用。
为此,通过大量的测试迁移实验发现最后一轮的虚拟机的迁移关机时间downtime基本在70ms左右,并不是长时间网络中断的主要原因,而且虚拟机内部压力和迁移速度的变化对迁移downtime并无明显影响。虚拟机网络是采用openswitch来定义组建的,经过大量实验确认迁移过程中的网络中断时间和openswtich设置目标端虚拟机新flow规则的延时时间存在正相关关系。
在虚拟机迁移后到目标端DestHost后,及时为虚拟机下发的新flow规则。通过优化openswtich的网络配置机制,目前已经将迁移过程中的网络中断时间控制在几百毫秒左右,基本做到用户无感知,不会因为在线迁移造成用户业务的中断。
如果用户虚拟机正在运行高IO负载业务,会导致磁盘迁移过程迟迟无法结束,最终导致迁移失败。
如图 3-1所示,首先就需要打通目标端DestHost和源端SourceHost之间的存储系统,即共享两个Host上虚拟机镜像的磁盘数据;同时,在此基础上进行共享存储的跨机迁移,从而实现先进行虚拟机内存和CPU等数据的迁移,以便在目标端DestHost快速拉起虚拟机,缓解源端SourceHost的内存和CPU压力。之后,再将虚拟机的大磁盘数据从源端SourceHost拉取到目标端DestHost。最后,删除源DestHost和目标SourceHost直接的共享存储。
具体快速在线迁移的具体实现步骤如下:
通过快速迁移优化,整个完整的迁移过程所需的时间,和传统的迁移方法所需的时间相当。但是迁移过程中,共享存储迁移的过程非常短暂,可以快速的在目标端DestHost上拉起虚拟机VM,迅速降低源端SourceHost的负载,改善用户VM之间的资源竞争,改善用户VM的性能,特别对于具有大数据盘的VM用户具有重要意义。
,在进行这种特殊跨存储迁移时,需要通过Libvirt的特殊配置,先在目标端建立一个不同存储类型的虚拟机(其他配置完全一样),然后再进行后续数据迁移。
如下图 3�-2所示,通过这种特殊配置之后,源端Qemu将通过qcow2驱动从qcow2磁盘文件中读取客户磁盘数据,再通过网络发送到目标端,目标端Qemu在接收到数据之后,通过raw驱动将数据写入到lvm块设备中。
通过多次的反复迭代最终完成整个磁盘的迁移,并最终将源端普通云主机上的用户虚拟机迁移切换到目标端SSD机型的云主机上。整个迁移过程对用户是透明的,不会对用户业务造成不利影响,即便目标端虚拟机迁移失败也不会影响源端用户虚拟机的正常运行。
由于Libvirt位于虚拟化组件的最上层,它的升级不会影响正在运行的虚拟机,而且直接可生效,无需停机和迁移就可完成。而Qemu升级以往常需要通过在线迁移才能保证无感知的升级。考虑到磁盘迁移占迁移时间的大部分,如果能够避免磁盘的迁移就可以大大节省软件升级的时间。
如图 3-3所示,在进行本地热升级的时候,需要在本地安装新版的Qemu_new,而原有已经运行的虚拟机VM_old仍然为旧版Qemu_old,然后将创建一台相同配置的新虚拟机VM_new,此时新建的虚拟机VM_new的Qemu版本为Qemu_new,并且新虚拟机VM_new此时处于paused状态。
新虚拟机VM_new和旧虚拟机VM_old之间通过socket文件进行内存数据迁移,这个迁移过程和普通在线迁移过程一致,也是先进行一次全量的内存迁移,然后再进行多次迭代的增量内存迁移,并最终短暂停机完成最后一次的内存和虚拟机机器信息等迁移。