Postcopy


先把虚拟机现有的CPU state, registers and, optionally, non-pageable memory(内存中不会进行交换或者移动的内存)等信息传输到目的服务器,不管dirty page,并迅速把虚拟机在目的服务器启动起来。同时,源服务器也会动态的把剩余的memory推送到目的服务器上。但是当虚拟机运行调用到还没传输过来的memory时,会触发page-fault.

postcopy基于userfault机制,可以在用户空间中通过文件描述符fd获得page fault信息。当虚拟机在目的服务器上调用到这些还未传输完成的内存时,userfaultfd可以到源服务器上把这些内存信息取出,并传输到目的服务器上,让虚拟机继续运行。

spacer.gif图片.png

使用postcopy不会受虚机对内存io的压力影响,但迁移完成后如果内存io压力大,会频繁调用userfault,这就会对服务器带宽带来压力,造成虚机性能下降。


x-multifd


x-multifd就是使用多个fd来传输文件

x-multifd-channels:在迁移时,使用多少个channels进行并行传输,也是用于迁移的sockets的数量,默认为2.

x-multifd-page-count:会将多少张pages一并发给一个thread,默认值为16.


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. 源服务器和目标服务器简图

spacer.gif图片.png

当虚拟机还在源服务器上运转时,第一个循环内将全部内存镜像复制到目标服务器上。在这个过程中,KVM 依然会监视内存的任何变化。

2. 内存镜像复制示意图

spacer.gif图片.png

以后的循环中,检查上一个循环中内存是否发生了变化。 假如发生了变化,那么 VMM 会将发生变化的内存页即 dirty pages 重新复制到目标服务器中,并覆盖掉先前的内存页。在这个阶段,VMM 依然会继续监视内存的变化情况。

3. 进行有变化的内存复制

spacer.gif图片.png

VMM 会持续这样的内存复制循环。随着循环次数的增加,所需要复制的 dirty pages 就会明显减少,而复制所耗费的时间就会逐渐变短,那么内存就有可能没有足够的时间发生变化。最后,当源服务器与目标服务器之间的差异达到一定标准时,内存复制操作才会结束,同时暂停源系统。

 4. 所需复制的数据在减少

spacer.gif图片.png

在源系统和目标系统都停机的情况下,将最后一个循环的 dirty-pages 和源系统设备的工作状态复制到目标服务器。

 5. 状态信息的复制

spacer.gif图片.png

然后,将存储从源系统上解锁,并锁定在目标系统上。启动目标服务器,并与存储资源和网络资源相连接。

 6. 停止源服务器,启动目标服务器

spacer.gif图片.png