热迁移:内存复制、状态交接与业务恢复
一、热迁移的状态范围与连续性要求
热迁移把客户机的执行从源端交给目的端,用于宿主维护与资源调度。目标是保持内存、CPU 和设备状态对应同一个执行点,并把业务不可服务的时间控制在可接受范围。迁移耗时、客户机停机时间和恢复后的业务延迟需要分别衡量。
其基础是保存与恢复:暂停源端,把客户机可见的内存内容、寄存器和设备状态交给目的端,让目的端在兼容的虚拟硬件上继续执行。若全部复制都发生在暂停之后,大容量内存会直接拉长停机。预拷贝把大部分内存复制提前到客户机运行期间,再处理期间产生的变化。
源端和目的端各有一个 QEMU 进程,分别持有本机的 RAM 映射与设备对象。源端 KVM 记录客户机执行产生的脏页,源 QEMU 读取和发送状态,目的 QEMU 将其装载到自己的对象中;Libvirt 则在两台宿主机上协调准备、接管和清理。迁移数据跨主机传输,本地对象和进程地址各自保留。
本文从普通预拷贝流程入手:两端采用兼容的机器、CPU 和设备配置,磁盘内容通过共享存储或另行复制保持一致,网络也需要在目的端具备接管条件。状态传输和这些外部资源的准备共同组成完整迁移。
源码版本:QEMU 10.2.0。
二、内存、CPU 与设备的一致性
客户机的一条写盘操作可能已经把请求放入内存中的队列,但设备尚未返回完成。如果只复制 RAM 就在目的端启动,设备不知道哪些请求正在处理;如果只恢复 CPU 寄存器,下一条指令读到的内存又可能来自另一个时刻。迁移需要重建一份可以继续执行的机器状态。
| 状态 | 迁移所需信息 | 交接时要满足的条件 |
|---|---|---|
| RAM | 页面内容及客户机物理地址布局 | 最后一批修改已到达,不能用过期页面覆盖新状态 |
| CPU | 指令位置、寄存器、控制及中断状态 | 与停机时的内存和设备状态一致 |
| 设备 | 寄存器、队列位置、定时器和可迁移的内部状态 | 在途操作得到收尾或被设备协议正确保存 |
| 外部资源 | 可访问的磁盘内容、网络和后端连接 | 目的端可接管,源端不能继续修改同一份业务状态 |
最直接的办法是先停机,再复制这些状态。8 GiB RAM 在有效带宽 1 GiB/s 下,仅内存复制就至少需要约 8 秒。预拷贝把首轮和多轮重传安排在客户机运行期间,只把最后一部分工作放入停机窗口,因此需要脏页跟踪来找出复制后发生的修改。
三、准备、运行中复制与停机交接
Mermaid 源码
flowchart TB
accTitle: 预拷贝迁移与外部资源切换
accDescr: 目的端准备兼容机器,源端运行时复制内存并重传脏页,源端停机后传递剩余内存及 CPU 和设备状态。目的端加载状态,并在存储和网络接管具备条件后恢复客户机。
A["目的端:兼容机器与接收通道就绪"] --> B["源端运行:首轮 RAM 复制"]
B --> C["源端运行:脏页迭代重传"]
C -->|切换条件满足| D["源端停止:剩余 RAM、CPU 与设备状态"]
D --> E["目的端:加载完整执行状态"]
E --> F["目的端恢复客户机<br/>源端保持停止"]
R["管理层:存储可用、访问权与网络接管"] -.-> A
R -.-> F
classDef source fill:#eaf0f6,stroke:#8198ac,color:#263c4c;
classDef destination fill:#e4f1ec,stroke:#438575,color:#173e34;
classDef coordination fill:#fff4db,stroke:#b89a55,color:#59491e;
class B,C,D source;
class A,E,F destination;
class R coordination;
1. 运行中复制 RAM
目的端准备好机器并等待状态。源端先传内存,客户机继续运行;脏页跟踪记录复制期间再次修改的页,使其进入后续轮次。迁移流同时标识状态处理器、版本与分段,使接收端把状态交给对应 RAM 或设备处理逻辑。
2. 停止源端并恢复目的端
剩余量满足切换条件后,源端暂停 vCPU,协调设备停止,发送最后的 RAM、CPU 寄存器和设备状态。目的端加载完成并具备存储访问、网络接管条件后恢复执行。管理层必须避免两端同时运行同一台客户机。
这里的暂停还要覆盖能够修改客户机内存的设备和后端。只停止 vCPU,不能保证 DMA 或异步 I/O 已停止写入。各状态处理器通过迁移回调保存自己的内容,目的端再按相同协议恢复;迁移流中的 RAM 分段、设备状态与结束标记负责组织这次交接。
四、一次磁盘请求在迁移前后的衔接
以共享存储上的 virtio-blk 磁盘为例,客户机把写请求放入 RAM 中的队列,源端设备开始处理。预拷贝可能已经复制过这段队列内存,但请求随后完成,又会改变完成记录和中断状态。最终交接必须让这些状态一起反映停机时的进度:
| 阶段 | 源端 | 目的端 |
|---|---|---|
| 运行中复制 | 继续处理请求,记录 RAM 修改 | 接收页面,尚不执行客户机或重复处理队列 |
| 停机收尾 | 停止客户机与相关 I/O 活动,完成最后脏页同步和设备状态保存 | 更新 RAM,装载队列处理位置、寄存器和中断状态 |
| 恢复执行 | 保持停止,等待管理层确认与清理 | 在原有磁盘内容上继续处理;驱动依据恢复的队列状态推进 |
共享存储解决两端访问同一份磁盘内容的问题;设备迁移解决队列、完成状态和后端活动的衔接。具体设备需要按自己的协议收尾或保存在途工作。网络同样需要目的端接管原来的连接环境,不能仅凭 RAM 复制成功判断业务已经恢复。
内存迭代的轮次、位图与带宽计算集中在预拷贝专篇;这里的完整性检查包括四项:最终 RAM、CPU 状态、设备状态和外部资源接管。
五、收敛、并行传输与后拷贝的取舍
| 遇到的限制 | 方案与作用 | 新增成本 |
|---|---|---|
| 停机复制全部内存耗时过长 | 预拷贝:提前复制,大部分时间维持客户机运行 | 持续跟踪修改,部分页面反复发送 |
| 单条传输路径无法利用可用带宽 | MultiFD:并行处理和传输 RAM 批次 | 更多线程、缓冲与跨通道同步 |
| 写脏过快,剩余量长期不下降 | 限制写脏,或切换后拷贝结束源端修改 | 前者影响业务执行;后者引入远程缺页和双端故障依赖 |
这些方案针对不同瓶颈。传输线程不足时增加并行度可能有效;链路已经饱和时,更多线程未必提高吞吐。写脏率过高则需要降低写脏、提高带宽,或改变切换方式。普通预拷贝在目的端接管前通常还保留可继续运行的源端;后拷贝开始后,不能简单让源端恢复执行来回退。
六、把迁移时间、停机和业务影响分开评价
迁移总时间包含运行中的复制阶段。客户机实际停顿指源端停止执行到目的端恢复执行的间隔;QMP 的 downtime 则由迁移实现计时,本例在源端记录,结束边界还受返回通道等因素影响,并非直接测量目的端恢复执行的时刻。业务不可用时间还可能包含网络收敛、客户端超时和服务恢复。这三种口径应分别记录,具体计时位置见停机时间与统计边界。
首先看剩余内存是否下降,再检查停机阶段的设备保存、传输和加载耗时,最后观察客户机恢复后的尾延迟。预拷贝的关键收益是把大规模复制移出停机窗口;它的主要代价是重复传输和迁移期间的资源竞争。带宽、MultiFD、压缩和后拷贝分别影响传输能力、CPU 消耗与切换方式,应依据实际瓶颈选择。
七、按迁移阶段继续阅读
- 预拷贝内存迭代与停机控制:用交互模型观察带宽、写脏与收敛。
- 迁移流格式与状态恢复:流头、RAM 分段和 CPU、设备状态。
- VFIO 设备热迁移:设备状态与 DMA 交接:具备迁移能力的直通设备在源端停止、传输状态和目的端恢复的过程。
- MultiFD 任务分发与同步:提高内存传输并行度。
- 后拷贝缺页与页面传输:目的端先执行之后如何取得页面。
- 虚拟 CPU 模型与迁移兼容性:迁移之前如何检查共同能力与状态约定。
- Libvirt 热迁移的阶段协调与失败恢复:准备、接管与清理,以及断连后的判断。