-第二步:磁盘
对于磁盘来说,通常对于这种块设备的迁移有两种方法。
一种是基于共享存储(EBS)的,支持在多点同时打开同一块盘。于是在B的虚拟机空壳上我们也会挂载上原先的这块磁盘,并且由QEMU自身保证。如果存在写入,则先在A上写,直到迁移完成的瞬间才开始在B上写。单点写入能够保证数据的一致性。
另一种方案是针对本地存储的。美团云的默认磁盘使用的是本地存储,为了避免迁移的时候需要拷贝大磁盘,我们使用了一个用户态的文件系统工具 fuse,它既可以像NFS一样方便地使用mount远程挂载磁盘,同时以用户态程序规避了内核难以调试的问题,并且和http整合到一起,形成了一个服务。在B端的空壳QEMU上新准备的磁盘也是空的,使用 fuse mount 挂载A上的远程磁盘文件,并将其设置成空壳QEMU的 backing_file,凭借QEMU的 copy_on_write 技术,A上的磁盘对于B的虚拟机来说变成本地可用。当内存迁移完成,新QEMU在B上运行后,我们还需要往B的QEMU monitor上发送 block_stream 命令,以一个较小的速度(30MB/s)从A上同步磁盘,这个同步动作和用户在虚拟机内部的IO访问是不冲突的,用户这段时间做出的磁盘修改都会被记录在B本地,直到最终同步完成,才会去 merge 这些差异的数据。
因此这两种方案都能保证迁移的过程中磁盘的数据同步过程中,原来的数据盘A都是可用的,从而保证原有的业务不会中断。
- 第三部:内存
最后一步是迁移内存。假设某个时刻网络和磁盘都在B上就绪了,虚拟机的整个系统仍然在A上运行着,为了保证业务不中断,我们一边从A往B拷贝着内存,填充空壳,另一方面仍然不能暂停A上QEMU的运行。但是只要在运行,内存就会有变化,可能拷贝了几十秒后(由网速决定)达到终点,但此时原先拷贝过的区域内一部分内存又变化了,因此,QEMU自身会在拷贝过程中记录下那些发生变化的脏页,针对它们再进行一次拷贝,如此循环。由于拷贝速度比内存变化速度快,所以在某个时刻,A与B上的QEMU内存会达到完全一致,A主动终止执行下一条CPU指令,B随即按照程序栈接替A执行,这样便完成了虚拟机系统从A到B的无缝切换。
下面就是整个迁移过程的框架:
美团云”零感知“迁移技术最大的技术难点是什么?
在同步内存这块,迁移速度的选择是一个技术难点。速度太大,过度占用网卡带宽,宿主机负载很重,容易影响其他用户体验;速度太小,脏页一直增长,来不及同步,导致一直迁移中无法结束。
脏页的问题,曾经遇到过这样一个场景。某个网站用户要求做迁移,迁移的时间段内。网站的访问量也很大,内存同步速度赶不上网站内存的变化速度。因此,美团云将迁移速度作为重要的备选参数,使得管理员能够针对不同的用户需求动态调整。从而在各种情况下,提高迁移成功率,做到真正的“零感知”解决方案。
我们还在做什么?
在最新的QEMU 2.5版本中,我们注意到,一个被称作为自动收敛(autoconverge)的功能被集成到了迁移代码里,它通过适当降低虚拟CPU执行速度的方法,间接降低了内存变化速度,从而提升迁移成功率。
此外,还有一个新特性叫 post-copy,它跟原先这种同步内存的方式(pre-copy)比起来,能够在第一时间就去B端将QEMU空壳启动起来,然后通过 page fault 的方式按需去A端读内存,这样一来,虽然同步的过程比较长,但能够避免集中拷贝大段内存,从而提高迁移成功率。
美团云正在不断迭代,试图在更严峻的环境下,为用户提供真正“零感知”的在线迁移解决方案,从而大幅度提高云服务的可靠性,并降低运维的依赖性。这样靠谱的云,你值得拥有!