1. 传输方式
传输方式 | 跳转函数 |
TCP | tcp_start_outgoing_migration |
RDMA | rdma_start_outgoing_migration |
EXEC | exec_start_outgoing_migration |
UNIX | unix_start_outgoing_migration |
FD | fd_start_outgoing_migration |
通常libvirt控制的虚机迁移都使用fd迁移,这是一种方便管理的迁移方式,由上层应用程序(libvirt)打开文件描述符,qemu只负责往描述符里面发送数据,这样可以把迁移的控制层和实现层完全分开。
2. 迁移方式
2.1. Pre-copy 预拷贝内存
预拷贝内存(Pre-copy)通过一个循环,将内存数据发送至目的主机VM,循环第一轮发送所有内存数据,接下来每一轮发送上一轮预拷贝过程中的脏页。最后一轮是停机拷贝阶段,源主机被挂起,停止内存更新,将脏页整体拷贝到目的主机vm上。
对于更新速度非常快的内存部分,每次循环过程都会变脏,需要重复 pre-copy,同时也导致循环次数非常多,迁移的时间变长。针对这种情况,KVM 虚拟机建立了三个原则:集中原则,一个循环内的 dirty pages 小于等于 50;不扩散原则, 一个循环内传输的 dirty pages 少于新产生的;有限循环原则,循环次数必须少于 30。在实现上,就是采取了以下措施:
- 有限循环:循环次数和效果受到控制,对每轮 pre-copy 的效果进行计算,若 pre-copy 对于减少不一致内存数量的效果不显著,或者循环次数超过了上限,循环将中止,进入停机拷贝阶段。
- 在被迁移 VM 的内核设置一个内存访问的监控模块。在内存 pre-copy 过程中,VM 的一个进程在一个被调度运行的期间,被限制最多执行 40 次内存写操作。这个措施直接限制了 pre-copy 过程中内存变脏的速度,其代价是对 VM 上的进程运行进行了一定的限制。
KVM 的预拷贝在线迁移过程详解:
(1) 源服务器和目标服务器简图
当虚拟机还在源服务器上运转时,第一个循环内将全部内存镜像复制到目标服务器上。在这个过程中,KVM 依然会监视内存的任何变化。(2) 内存镜像复制示意图
以后的循环中,检查上一个循环中内存是否发生了变化。 假如发生了变化,那么 VMM 会将发生变化的内存页即 dirty pages 重新复制到目标服务器中,并覆盖掉先前的内存页。在这个阶段,VMM 依然会继续监视内存的变化情况。(3) 进行有变化的内存复制
VMM 会持续这样的内存复制循环。随着循环次数的增加,所需要复制的 dirty pages 就会明显减少,而复制所耗费的时间就会逐渐变短,那么内存就有可能没有足够的时间发生变化。最后,当源服务器与目标服务器之间的差异达到一定标准时,内存复制操作才会结束,同时暂停源系统。
(4) 所需复制的数据在减少
在源系统和目标系统都停机的情况下,将最后一个循环的 dirty-pages 和源系统设备的工作状态复制到目标服务器。
(5) 状态信息的复制
然后,将存储从源系统上解锁,并锁定在目标系统上。启动目标服务器,并与存储资源和网络资源相连接。(6) 停止源服务器,启动目标服务器
2.2. Post-copy内存后拷贝
先把虚拟机现有的CPU state, registers and, optionally, non-pageable memory(内存中不会进行交换或者移动的内存)等信息传输到目的服务器,不管dirty page,并迅速把虚拟机在目的服务器启动起来。同时,源服务器也会动态的把剩余的memory推送到目的服务器上。但是当虚拟机运行调用到还没传输过来的memory时,会触发page-fault.
postcopy基于userfault机制,可以在用户空间中通过文件描述符fd获得page fault信息。当虚拟机在目的服务器上调用到这些还未传输完成的内存时,userfaultfd可以到源服务器上把这些内存信息取出,并传输到目的服务器上,让虚拟机继续运行。
使用postcopy不会受虚机对内存io的压力影响,但迁移完成后如果内存io压力大,会频繁调用userfault,这就会对服务器带宽带来压力,造成虚机性能下降。
2.3. hybrid-copy混合拷贝
同时迁移存储数据和内存数据,融合了pre-copy和post-copy两者的优势,降低了网络流量传输,减少了访问源端内存次数。
缺点式依然存在post-copy阶段中的稳健性问题
三种模式的比较: