强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

QEMU 虚拟化完全指南 / 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-sizeXBZRLE 缓存大小64M-256M
max-cpu-throttleCPU 降速上限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 虚拟机。