KVM 热迁移是在虚拟机持续运行、业务几乎无感知的前提下,将其从源宿主机完整迁移到目标宿主机的技术,核心是内存状态 + 设备状态 + CPU 状态的在线同步,仅最后阶段短暂停机(毫秒级)。
KVM 热迁移的本质,就是在虚拟机持续运行时,通过迭代同步内存脏页,在极短停机时间内完成虚拟机全部运行状态的网络传输与远程恢复,实现宿主机之间无缝切换。
迁移 “运行时状态”,不是迁移 “文件”
虚拟机 = 两部分
- 静态镜像(硬盘文件)
- 动态状态(内存 + CPU 寄存器 + 设备状态)
普通迁移 = 关机 → 拷贝文件 → 开机
热迁移 =不关机,只迁移动态状态
所以本质是:只迁移 “此刻正在运行的状态”,磁盘数据不动(或后台同步)。
必备前提条件
源宿主机 + 目标宿主机:
- 同 CPU 架构(x86_64),指令集尽量一致;可通过 libvirt CPU 模式(如
match='exact'、custom)兼容差异。 - KVM、QEMU、libvirt 版本尽量一致
- 网络互通,最好万兆迁移专用网
- 同 CPU 架构(x86_64),指令集尽量一致;可通过 libvirt CPU 模式(如
- 虚拟机磁盘:
- 放在共享存储(NFS/iSCSI/ceph),两台主机都能访问同一路径
- 禁用本地磁盘缓存(cache=none)。磁盘
cache=none或cache=writethrough
- 虚拟机不能有:
- PCI 设备直通(GPU、网卡直通等)
- 本地挂载的物理磁盘
- 防火墙放行:
- SSH 22 端口
- libvirt 迁移端口(16509 等)
- 源 / 目标网络互通;专用高速迁移网络(万兆优先);开放端口 16509(QEMU 默认)、SSH 端口;防火墙放行。
- 软件:源 / 目标 KVM、QEMU、libvirt 版本一致;虚拟机配置(vCPU、内存、网卡、磁盘)完全一致;无 PCIe 直通(除 KAE 等特殊设备)。
核心原理
1. 迁移类型
- 共享存储热迁移(主流):虚拟机磁盘存于 NFS/iSCSI/FC/GlusterFS 等共享存储,源 / 目标均可访问,仅迁移内存与状态,速度最快。
- 非共享存储热迁移:本地磁盘随虚拟机一起在线拷贝迁移,速度慢、带宽占用大。
2. 核心流程(共享存储)
- 预拷贝阶段:源 VM 持续运行,QEMU/KVM 将全部内存页发送到目标;同时记录被修改的 “脏页”,循环同步脏页,直到脏页量足够小。
- 停机同步阶段:短暂暂停源 VM,传输最后一批脏页与设备 / CPU 状态,目标完成状态加载。
- 恢复运行:目标 VM 启动,源 VM 销毁,业务恢复。
3. 关键机制
- 脏页跟踪:KVM 通过页表标记修改页,减少重复传输。
- 自动收敛(Auto-Converge):脏页生成过快时,适度限流 VM CPU,确保迁移能完成。
- 最大停机时间(Max Downtime):控制最后停机时长(默认 300ms,可设)。
- 带宽限速:避免迁移占用过多业务带宽。
- 压缩(zlib/zstd)、多通道(MultiFD):加速传输、降低带宽。
脏页迭代预拷贝(Dirty Page Pre-copy)
在虚拟机持续运行时,通过多轮迭代,只同步被修改过的内存页(脏页),不断缩小需要传输的数据量,直到脏页足够少,再短暂停机完成最终同步,实现几乎无感知迁移。
脏页迭代预拷贝原理 = 硬件跟踪脏页 + 运行时多轮只传变化页 + 最后毫秒级停机同步最小状态,实现虚拟机内存从一台物理机无缝搬到另一台。
这是 KVM/QEMU 热迁移真正的核心原理。
第一轮:全量内存拷贝,源主机把 VM 全部内存发给目标主机。VM 还在跑,业务不中断。
第二轮:只拷贝 “脏页”,KVM 会标记哪些内存页被修改过 → 只发这些脏页。循环反复,脏页越来越少。
最后一刻:停机毫秒级,同步最终状态,脏页足够少 → 暂停 VM 极短时间发送最后一点脏页 + CPU 寄存器 + 设备状态
目标机恢复执行,目标机从收到的状态继续跑,IP 不变、连接不断。
本质:利用 “脏页收敛” 实现近乎无感知切换。
完整流程原理
1. 开启脏页跟踪(Dirty Logging)
源宿主机的 KVM 内核模块会:
- 给虚拟机的所有内存页打上可跟踪标记
- 一旦 VM 往某页内存写数据,该页立刻被标记为脏页(Dirty Page)
这是整个技术的基础:知道哪些页变了。
2. 第一轮:全量内存预拷贝
- 源 QEMU 把虚拟机全部内存页发给目标主机
- 虚拟机全程不暂停,业务正常跑
- 同时,KVM 持续记录新产生的脏页
结果:目标机拿到了一份 “旧但完整” 的内存镜像。
3. 多轮迭代:只同步脏页(核心)
这就是 “迭代” 的含义:循环执行:
- 把本轮所有脏页发送到目标机
- 清空本轮脏页标记
- 继续跟踪新产生的脏页
特点:
- 每一轮只传变化的少量数据
- 正常业务下,脏页会越来越少,逐步收敛
- VM 始终不停止
4. 停机同步(Stop-and-Copy)
当脏页已经非常少(达到阈值):
- 短暂暂停虚拟机(毫秒级)
- 发送最后一批脏页
- 发送 CPU 寄存器、设备状态
- 目标机加载完整状态,启动运行
- 源机销毁虚拟机
切换完成。
关键机制原理
1. 脏页跟踪怎么实现?
底层依赖:
- Intel EPT / AMD NPT(硬件辅助虚拟化页表)
- KVM 将页表权限设为只读
- 一旦 VM 写入,触发EPT 违反异常
- KVM 捕获后标记该页为脏页,恢复可写权限
这是硬件级高效跟踪,几乎无性能损耗。
2. 为什么要 “迭代”?
因为 VM 一边迁移一边改内存。只传一轮会导致目标机内存永远落后。
多轮迭代 → 脏页递减 → 最终可收敛。
3. 为什么停机时间极短?
因为停机时只传:
- 最后一小批脏页
- 寄存器 + 设备状态(KB 级)
所以停机通常< 300ms,TCP 不断、业务无感。
用最简单的比喻理解
你要抄写一本正在被不断修改的书:
- 先抄完整本(第一轮全量)
- 作者边写你边改,只改被涂改的页面(迭代传脏页)
- 等作者修改越来越少
- 让作者停笔 0.1 秒,你抄完最后几页
- 你手里的书和原书完全一致
这就是脏页迭代预拷贝。
核心优势
1.业务几乎无感知,停机时间极短
- 绝大多数内存是在VM 正常运行时后台同步的
- 只在最后脏页极少时,才短暂暂停 VM
- 停机时间通常几十毫秒~几百毫秒
- 应用、TCP 连接基本不会断
这是它能实现真正热迁移的根本原因。
2.避免一次性全量停机拷贝
如果不做迭代,而是一次性停 VM、传全部内存:
- 内存越大,停机越久
- 32G 内存可能要停几秒甚至更久,业务直接雪崩
迭代预拷贝把停机时间从 “秒级” 压到 “毫秒级”。
3.网络压力更平滑,不会瞬间打满带宽
- 不是一次性爆发传输
- 多轮迭代、渐进式同步
- 对物理网络冲击小,不会影响同宿主机其他 VM
4.自动适应业务压力,能 “追得上” 脏页
VM 一边跑、一边改内存,会不断产生脏页。预拷贝会:
- 第一轮传全部内存
- 之后只传变化的脏页
- 每一轮脏页通常越来越少,最终能收敛完成
这保证了迁移一定能结束,而不是永远追不上。
5.内存越大,优势越明显
- 8G、16G、64G、128G 内存的 VM 都能平滑迁移
- 不需要为迁移预留额外巨大内存缓冲
- 对宿主机资源占用可控
6.成熟稳定,兼容性极强
- 从老版本 KVM 到最新版本都支持
- 不需要特殊硬件
- 不依赖存储架构(共享 / 非共享都能用)
是工业界标准热迁移方案。
架构本质:QEMU 状态序列化 + 网络传输
KVM 热迁移不是硬件级迁移,而是QEMU 把虚拟机状态序列化,通过网络传给另一个 QEMU。
- 源 QEMU:导出状态
- 网络:传输状态数据
- 目标 QEMU:导入状态、恢复执行
本质:两个 QEMU 进程之间的状态转移。
为什么能做到 “热”?
因为:
- 虚拟机的执行环境是完全虚拟化的
- 所有状态都在内存和 QEMU 控制下
- 没有绑定物理 CPU / 物理硬件
- 内存可以被追踪、复制、传输
本质:虚拟化层把硬件抽象掉了,状态可迁移。
最简单的热迁移命令(virsh)
1. 基础共享存储热迁移
virsh migrate --live <虚拟机名> qemu+ssh://目标IP/system示例:
virsh migrate --live vm101 qemu+ssh://192.168.1.100/system2. 更稳定的参数(推荐)
virsh migrate --live \ --auto-converge \ # 自动收敛,防止脏页追不上 --unsafe \ # 忽略部分兼容性检查 --migrateuri tcp://目标IP \ <虚拟机名> qemu+ssh://目标IP/system3. 限制带宽
virsh migrate-setspeed <虚拟机名> --bandwidth 500单位:Mbps
4. 设置最大停机时间(业务无感)
virsh migrate-setmaxdowntime <虚拟机名> 300单位:毫秒
5. 查看迁移状态
virsh domjobinfo <虚拟机名>看到:
Job type: Unbounded正在迁移Job completed successfully成功
常见失败原因
- CPU 型号 / 指令集不一致,解决:虚拟机 XML 里加
<cpu mode='custom' match='exact' check='none'> <model fallback='allow'>Skylake-Client-noTSX-IBRS</model> </cpu> - 脏页产生太快,迁移无法收敛,解决:加
--auto-converge,会自动轻微压制虚拟机 CPU - 网络不通、防火墙拦截,关闭防火墙或放行业务与迁移端口
- 磁盘路径不一致、权限不对,两台主机挂载共享存储路径必须完全一样