KVM迁移虚拟机在线热迁移,同架构不同宿主机迁移踩坑
KVM 在线热迁移(Live Migration)可以让虚拟机在不关机的情况下从一台宿主机搬到另一台宿主机。
很多新手容易忽略一个前提:迁移双方必须是同 CPU 架构,且磁盘需要放在共享存储上。
如果这两个条件不满足,迁移要么直接失败,要么虚拟机迁移后出现 CPU 不识别、性能骤降等诡异问题。
本文按实际操作顺序,把同架构不同宿主机间的热迁移完整走一遍,并列出我踩过的坑。
迁移前先确认这三件事
开始之前,最好在源宿主机和目标宿主机上逐项检查,避免做无用功。
1. CPU 架构和型号要兼容
查看两台宿主机的 CPU 信息:
lscpu | grep 'Model name'
建议两台的 CPU 型号完全一致,如果不一致,至少也要同代同系列。
否则迁移虽然可能成功,但虚拟机内部可能会报 CPU 不支持或触发内核 panic。
2. 虚拟机磁盘必须放在共享存储里
在线热迁移只传输内存和 CPU 状态,磁盘数据不会跟着走。
所以虚拟机的磁盘镜像必须放在两台宿主机都能访问的存储上,比如 NFS、iSCSI、GlusterFS。
如果磁盘在本地,迁移过程中目标宿主机根本找不到磁盘文件,迁移会直接报错。
3. 网络和防火墙要放行
迁移默认走 TCP 端口 49152 到 49215 这段范围,同时也要保证 libvirt 的 TLS 端口(默认 16514)或 SSH 通道可达。
最简单的做法是临时关闭防火墙测试,或者放行对应端口:
firewall-cmd --permanent --add-port=49152-49215/tcp
firewall-cmd --reload
配置 NFS 共享存储并挂载到两台宿主机
这里以 NFS 为例。
先在一台存储服务器上导出磁盘目录,编辑 /etc/exports:
/data/kvm_images 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)
然后重启 NFS 服务:
systemctl restart nfs-server
在两台 KVM 宿主机上分别挂载:
mkdir -p /data/kvm_images
mount -t nfs 192.168.1.10:/data/kvm_images /data/kvm_images
把挂载信息写进 /etc/fstab,防止重启后丢失:
echo '192.168.1.10:/data/kvm_images /data/kvm_images nfs defaults 0 0' >> /etc/fstab
如果虚拟机原来用的是本地磁盘,先用 qemu-img convert 把磁盘迁移到共享目录,再修改虚拟机 XML 中的磁盘路径。
转换前先关闭虚拟机:
qemu-img convert -O qcow2 /var/lib/libvirt/images/old.qcow2 /data/kvm_images/vm-disk.qcow2
用 virsh migrate 执行热迁移
确认共享存储挂载正常后,在源宿主机上执行迁移命令。
推荐先测试不加密的 TCP 隧道方式:
virsh migrate --live --unsafe --verbose vm-name qemu+ssh://root@目标宿主机IP/system
如果已经配置好免密 SSH,这个命令会直接开始迁移。--live 表示在线迁移,--unsafe 用于跳过安全检查(适合测试环境),--verbose 显示进度。
迁移过程中不要中断命令,也不要去重启 libvirtd。
一个常见错误是迁移慢到像卡住,这通常是因为内存脏页速率太高,网络带宽或磁盘 IO 跟不上。
可以改用更保守的参数,增加最大内存带宽限制:
virsh migrate --live --verbose --bandwidth 100 vm-name qemu+ssh://root@目标宿主机IP/system
--bandwidth 单位是 MiB/s,可以根据实际网络调整。
怎么判断迁移真的成功了
迁移成功的标志不是源宿主机上没有这个虚拟机,而是目标宿主机上已经接管了虚拟机,并且网络、业务都正常。
在目标宿主机上执行:
virsh list --all
看到虚拟机状态为 running 后,还要检查以下几点:
virsh dumpxml vm-name | grep '
如果目标宿主机上的虚拟机是 paused 状态,说明迁移没有完全成功,需要查看 virsh domjobinfo vm-name 里的状态信息。
另外,迁移完成后源宿主机上可能会残留一个不完整的定义文件。
用 virsh undefine vm-name 清理一下即可,不要删除共享磁盘文件。
最容易踩的几个坑
没有共享存储就跑热迁移。
这是最常见的失败原因。
迁移进程会报 file not found 或 storage migration failed,其实不是命令错了,而是目标宿主机看不到磁盘路径。
两台宿主机 CPU 型号不一致。
我遇到过迁移成功,但虚拟机起来后 dmesg 全是 CPU 相关报错,服务频繁崩溃。
建议迁移前先在虚拟机里跑 lscpu 做对比,如果真不一致,可以用 virsh edit vm-name 把 CPU 模式改为 host-model,让目标宿主机自动适配。
忽略了防火墙端口。virsh migrate 卡在 0% 迟迟不动,先检查源宿主机到目标宿主机的 TCP 端口是否通:
telnet 目标宿主机IP 16514
迁移后网络不通。
很多虚拟机使用 libvirt 默认 NAT 网络,迁移到另一台宿主机后,如果目标宿主机的网桥配置和源机不同,虚拟机的 IP 会变。
建议生产环境使用 bridge 模式,并且保证两台宿主机在同一个二层网络。
如果你正在处理 KVM 虚拟机在线热迁移,建议先把共享存储和 CPU 兼容性这两关过了,再执行迁移命令。
迁移过程中遇到异常,优先查看 libvirtd 日志:
tail -f /var/log/libvirt/libvirtd.log
热迁移本身并不复杂,复杂的是前置环境。
把准备工作做扎实,后续的迁移流程基本可以控制在几分钟内完成。