postcopy
postcopy对我来说一直是一个神秘的东西,这次终于有时间仔细研究一下。
所谓postcopy直接来说就是在虚拟机启动后再迁移
正常情况下我们是先把虚拟机的信息拷贝到目的端,包括内存、设备,然后在目的端启动虚拟机。而postcopy引入了一个非常有意思的想法,就是先把虚拟机启动起来,然后再来迁移需要的信息。当然这里最重要的就是内存了。
本小节也是以内存为主线,其余支持postcopy的部分暂且不表。(主要是因为没看)
从用法开始
在探讨细节前,我们先看看是怎么使用postcopy的。总体过程和普通迁移类似,有一点有意思的区别是在启动迁移后,再启动postcopy。
以在monitor中执行迁移为例,需要执行的命令是:
migrate_set_capability postcopy-ram on # both source and destination
migrate_set_capability postcopy-blocktime on # both source and destination
migrate -d tcp:0:4444
migrate_start_postcopy # after first round of sync其中第一二条命令需要在目的和源端都执行。然后需要在启动迁移后,再开启postcopy。其中建议在运行了一轮迁移后执行。
启动postcopy
执行migrate_start_postcopy命令,作用是将某个变量置为true。
hmp_migrate_start_postcopy
qmp_migrate_start_postcopy
atomic_set(&s->start_postcopy, true);而这个变量设置后,就会在migration_iteration_run判断。当达到条件则会开启postcopy。听着真是一点也不神奇。
postcopy中的交互
神奇的事情这个时候才开始发生 -- postcopy_start()函数隐藏了大部分的秘密。
先来一个简化的代码流程:
貌似还是有点长,稍微总结一下:
进入后虚拟机停掉了
通知目的地那些内从空间是要丢弃的
发送命令LISTNE/RUN给目的地
上面的流程看着已经有点麻烦了,但是这还只是迁移过程中的源端。目的端是如何和源端进行交互的呢?下面用一个小小的流程图解释一下。
目的和源端的交互是通过几个命令来实现的。
DISCARD : 通知目的端需要放弃的内存空间
LISTEN : 开启一个新的监听线程
PACKAGED : 这个命令有点意思,它将一坨东西打包发送
RUN : 告诉目的端可以运行了
当目的端收到RUN命令,主线程就会拉起虚拟机执行了。而在LISTEN命令下开启的postcopy_ram_listen_thread就会肩负其接收后续内存的责任。
好玩的是在目的端还用了一个超级简化的状态机来记录postcopy过程的状态变化:incoming_postcopy_state(PostcopyState)
这个状态迁移实在太简单了,变化如下:
userfaultfd
重点在上面都描述完了,这里只提一下这里利用到的一个内核特性userfaultfd。
也即是我们需要通过这个接口来:
告诉虚拟机哪个内存被丢弃
当新内存来到后,填入指定位置
好了,基本讲完了,以后想到新的再来补充。
Last updated
Was this helpful?