07 - 虚拟机迁移
07 - 虚拟机迁移
掌握 QEMU 虚拟机的在线迁移、离线迁移、跨主机迁移,以及共享存储和压缩传输方案。
7.1 迁移概念
虚拟机迁移(Migration)是将运行中的虚拟机从一台宿主机移动到另一台宿主机的过程。
迁移类型
| 类型 | 说明 | 停机时间 | 使用场景 |
|---|---|---|---|
| 离线迁移 | 关机后移动磁盘和配置文件 | 长(分钟级) | 维护、硬件更换 |
| 在线迁移(冷迁移) | 运行中迁移,有短暂停顿 | 短(秒级) | 负载均衡 |
| 实时迁移(Live Migration) | 运行中迁移,几乎无感知 | 极短(毫秒级) | 高可用、维护 |
| 存储迁移 | 仅迁移磁盘数据 | 无/短 | 存储维护 |
迁移前提条件
在线迁移的前提:
├── 源主机和目标主机运行相同版本的 QEMU
├── CPU 兼容(同代或兼容模式)
├── 网络可达(QEMU monitor 端口)
├── 共享存储(NFS/iSCSI/Ceph)或存储迁移
└── 足够的带宽(建议 10Gbps+)
7.2 离线迁移
最简单的迁移方式,先关机再移动文件:
# 在源主机上导出虚拟机配置和磁盘
# 1. 关闭虚拟机
# 2. 复制配置和磁盘到目标主机
# 使用 rsync 增量同步磁盘文件
rsync -avz --progress \
/var/lib/qemu/vm1/disk.qcow2 \
target-host:/var/lib/qemu/vm1/disk.qcow2
# 使用 scp 直接复制
scp /var/lib/qemu/vm1/disk.qcow2 target-host:/var/lib/qemu/vm1/
# 在目标主机上启动
ssh target-host 'qemu-system-x86_64 -enable-kvm -cpu host -m 4G \
-drive file=/var/lib/qemu/vm1/disk.qcow2,format=qcow2 \
-nographic -daemonize'
离线迁移脚本
#!/bin/bash
# offline-migrate.sh - 离线迁移脚本
VM_NAME="$1"
SRC_HOST="$2"
DST_HOST="$3"
VM_DIR="/var/lib/qemu/${VM_NAME}"
echo "开始离线迁移: ${VM_NAME}"
echo " 源主机: ${SRC_HOST}"
echo " 目标主机: ${DST_HOST}"
# 1. 在源主机上关闭虚拟机
echo "关闭虚拟机..."
ssh ${SRC_HOST} "virsh shutdown ${VM_NAME}"
sleep 30
# 2. 同步磁盘文件
echo "同步磁盘文件..."
rsync -avz --progress \
${SRC_HOST}:${VM_DIR}/ \
${DST_HOST}:${VM_DIR}/
# 3. 在目标主机上启动
echo "在目标主机上启动..."
ssh ${DST_HOST} "cd ${VM_DIR} && qemu-system-x86_64 \
-enable-kvm -cpu host -m 4G \
-drive file=disk.qcow2,format=qcow2 \
-nographic -daemonize"
echo "迁移完成"
7.3 在线迁移(Live Migration)
使用 QEMU Monitor 迁移
在源主机的 QEMU Monitor 中执行:
# 启动 QEMU 并开启迁移端口
qemu-system-x86_64 \
-enable-kvm -cpu host -m 4G \
-drive file=disk.qcow2,format=qcow2 \
-incoming tcp:0:4444 \
-monitor stdio \
-daemonize
# 在 Monitor 中执行迁移
(qemu) migrate tcp://target-host:4444
# 查看迁移进度
(qemu) info migrate
# 使用压缩传输
(qemu) migrate_set_capability compress on
(qemu) migrate tcp://target-host:4444
# 使用多线程压缩
(qemu) migrate_set_capability compress-threads on
(qemu) migrate_set_parameter compress-threads 4
使用 libvirt 迁移
# 在线迁移(最简单的方式)
virsh migrate --live ubuntu-vm qemu+ssh://target-host/system
# 带压缩的迁移
virsh migrate --live --compressed ubuntu-vm qemu+ssh://target-host/system
# 指定迁移带宽限制
virsh migrate --live --bandwidth 1000 ubuntu-vm qemu+ssh://target-host/system
# 迁移后在目标主机自动启动
virsh migrate --live --persistent ubuntu-vm qemu+ssh://target-host/system
# 预复制迁移(默认)
virsh migrate --live --copy-storage-all ubuntu-vm qemu+ssh://target-host/system
在线迁移流程
实时迁移流程:
源主机 目标主机
│ │
│ 1. 连接目标主机 │
│ ────────────────────────────> │
│ │
│ 2. 传输内存页(预复制) │
│ ────────────────────────────> │
│ │
│ 3. 脏页跟踪,传输剩余页 │
│ ────────────────────────────> │
│ │
│ 4. 暂停源虚拟机 │
│ ────────────────────────────> │
│ │
│ 5. 传输最后状态(CPU+设备) │
│ ────────────────────────────> │
│ │
│ 6. 激活目标虚拟机 │
│ ────────────────────────────> │
│ │
│ 7. 源虚拟机停止 │
│ │
完成迁移
7.4 存储迁移
当源主机和目标主机没有共享存储时,需要同时迁移磁盘数据:
# 使用 libvirt 迁移存储
virsh migrate --live --copy-storage-all ubuntu-vm qemu+ssh://target-host/system
# 使用块迁移(Block Migration)
virsh migrate --live --copy-storage-inc ubuntu-vm qemu+ssh://target-host/system
# --copy-storage-inc: 增量复制(仅复制变化的部分)
使用 NBD 进行存储迁移
# 在目标主机上启动 NBD 服务器
qemu-nbd --listen --port=10809 disk.qcow2 &
# 在源主机上通过 NBD 访问目标磁盘
qemu-system-x86_64 \
-drive file=nbd:target-host:10809:exportname=drive0,format=raw
# 使用 QMP 执行块设备迁移
# (qemu) drive-mirror drive0 nbd:target-host:10809:exportname=drive0
7.5 共享存储配置
NFS 共享存储
# 在 NFS 服务器上配置
cat >> /etc/exports << 'EOF'
/var/lib/qemu 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)
EOF
sudo exportfs -ra
# 在源主机和目标主机上挂载
sudo apt install nfs-common
sudo mkdir -p /var/lib/qemu
sudo mount nfs-server:/var/lib/qemu /var/lib/qemu
# 验证
df -h /var/lib/qemu
iSCSI 共享存储
# 安装 iSCSI 工具
sudo apt install open-iscsi
# 发现 iSCSI 目标
sudo iscsiadm -m discovery -t sendtargets -p iscsi-server
# 登录到目标
sudo iscsiadm -m node -T iqn.2026-01.com.example:storage.vm -p iscsi-server -l
# 查看 iSCSI 块设备
lsblk
# 使用 iSCSI 设备启动虚拟机
qemu-system-x86_64 \
-enable-kvm -cpu host -m 4G \
-drive file=/dev/sdb,format=raw,if=virtio \
-nographic
Ceph RBD 共享存储
# 安装 Ceph 工具
sudo apt install ceph-common
# 创建 Ceph 存储池
ceph osd pool create vms 64
# 创建 RBD 镜像
rbd create vms/vm1-disk --size 40G
# 使用 RBD 镜像启动虚拟机
qemu-system-x86_64 \
-enable-kvm -cpu host -m 4G \
-drive file=rbd:vms/vm1-disk:conf=/etc/ceph/ceph.conf,format=raw,if=virtio \
-nographic
# 共享存储配置(在 libvirt 中)
cat > ceph-pool.xml << 'EOF'
<pool type='rbd'>
<name>ceph-vms</name>
<source>
<name>vms</name>
<host name='ceph-mon1'/>
<host name='ceph-mon2'/>
<host name='ceph-mon3'/>
</source>
</pool>
EOF
virsh pool-define ceph-pool.xml
virsh pool-start ceph-vms
virsh pool-autostart ceph-vms
7.6 迁移性能优化
压缩传输
# 在 Monitor 中启用压缩
(qemu) migrate_set_capability compress on
# 使用 zlib 压缩
(qemu) migrate_set_parameter compress-level 1
# 使用多线程
(qemu) migrate_set_capability compress-threads on
(qemu) migrate_set_parameter compress-threads 4
# 使用 xbzrle 压缩(增量压缩,适合内存变化小的场景)
(qemu) migrate_set_capability xbzrle on
(qemu) migrate_set_parameter xbzrle-cache-size 64M
带宽限制
# 限制迁移带宽(避免影响业务网络)
(qemu) migrate_set_parameter max-bandwidth 500M
# 使用 libvirt 限制
virsh migrate --live --bandwidth 500 ubuntu-vm qemu+ssh://target-host/system
迁移优化参数
| 参数 | 说明 | 推荐值 |
|---|---|---|
| max-bandwidth | 迁移带宽上限 | 500M-1G |
| max-postcopy-bandwidth | 后复制带宽 | 100M |
| downtime-limit | 最大停机时间 | 100ms |
| compress-level | 压缩级别 | 1-3 |
| compress-threads | 压缩线程数 | 4-8 |
| xbzrle-cache-size | XBZRLE 缓存大小 | 64M-256M |
| max-cpu-throttle | CPU 降速上限 | 99 |
后复制迁移(Postcopy Migration)
# 启用后复制迁移
(qemu) migrate_set_capability postcopy-ram on
# 开始迁移
(qemu) migrate tcp://target-host:4444
# 在传输一定量内存后切换到后复制模式
(qemu) migrate_start_postcopy
后复制迁移的优势:减少总迁移时间和停机时间。代价是如果目标主机故障,虚拟机将不可恢复。
7.7 迁移故障排查
常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 迁移超时 | 带宽不足或内存脏页过多 | 增加带宽、启用压缩 |
| CPU 不兼容 | 源/目标 CPU 差异大 | 使用 -cpu host,-vmx 模式 |
| 磁盘不可达 | 存储路径不同 | 使用共享存储或存储迁移 |
| 迁移后网络断 | MAC/IP 变化 | 使用桥接网络和固定 IP |
| 权限拒绝 | SSH 或文件权限问题 | 检查 SSH 密钥和文件权限 |
迁移诊断
# 查看迁移状态
(qemu) info migrate
# 输出示例:
# Migration status: active
# total time: 12345 ms
# downtime: 50 ms
# setup: 123 ms
# ram: 2048 MB
# transferred: 1800 MB
# remaining: 248 MB
# speed: 150 MB/s
# dirty pages rate: 10 MB/s
# 查看内存迁移详情
(qemu) info migrate_parameters
回滚迁移
# 如果迁移失败,可以在源主机上取消
(qemu) migrate_cancel
# 在 libvirt 中取消
virsh migrate-cancel ubuntu-vm
7.8 跨集群迁移
使用 Proxmox VE 迁移
# Proxmox VE 提供 GUI 和 CLI 迁移工具
qmigrate <vmid> <target-node>
# 或通过 API
curl -X POST https://pve-host:8006/api2/json/nodes/local/qemu/100/migrate \
-d target=target-node \
-d online=1
使用 OpenStack 迁移
# OpenStack 热迁移
openstack server migrate --live-migration --os-compute-api-version 2.25 \
<server-id> <target-host>
# 冷迁移
openstack server migrate <server-id>
要点回顾
| 要点 | 核心内容 |
|---|---|
| 离线迁移 | 关机 → 复制文件 → 启动,最简单 |
| 在线迁移 | 运行中迁移,短暂停机,使用 QMP/libvirt |
| 存储迁移 | NFS/iSCSI/Ceph 共享存储,或块迁移 |
| 压缩传输 | compress + xbzrle 减少网络带宽需求 |
| 后复制 | 减少停机时间,但风险更高 |
注意事项
CPU 兼容性: 迁移的源和目标主机 CPU 必须兼容。建议使用
-cpu host,-vmx或-cpu qemu64等通用 CPU 模型。
网络带宽: 在线迁移需要足够的带宽。1Gbps 网络迁移 4GB 内存的虚拟机大约需要 30-60 秒。
存储一致性: 使用共享存储时,确保存储挂载点在源和目标主机上一致。
测试迁移: 在生产环境中执行迁移前,务必在测试环境验证迁移流程。
扩展阅读
下一步
→ 08 - libvirt 集成:学习使用 libvirt/virsh/virt-manager 管理 QEMU 虚拟机。