QEMU 快照和虚拟机迁移

FreeGuideOnline 最新 2026-07-13

bash qemu-img create -f qcow2 test-vm.qcow2 10G

然后安装一个操作系统,或直接以 Live CD 启动。确保虚拟机处于**关闭**状态再进行磁盘快照,以获得最干净的状态。

### 磁盘快照基础操作(使用 qemu-img)

`qemu-img` 是管理 qcow2 镜像的命令行工具,可用于创建、列出、应用、删除快照。

#### 创建快照
```bash
qemu-img snapshot -c snapshot_name test-vm.qcow2

-c 表示创建(create),后面跟随自定义的快照名称。该命令会在镜像内部元数据中记录当前全部磁盘内容。

列出所有快照

qemu-img snapshot -l test-vm.qcow2

输出示例:

Snapshot list:
ID        TAG                 VM SIZE                DATE       VM CLOCK
1         before_apt_upgrade   2.5G 2025-03-01 10:20:30   00:05:12.300
2         clean_install        1.8G 2025-03-01 09:15:00   00:03:00.000

回滚至某个快照

警告:所有在快照之后写入的数据将会丢失。

qemu-img snapshot -a snapshot_name test-vm.qcow2

-a 表示应用(apply)。完成后磁盘状态恢复为快照时刻的状态。

删除快照

qemu-img snapshot -d snapshot_name test-vm.qcow2

删除无用的快照可以释放镜像文件内部占用的空间(qcow2 文件不会自动收缩,你可能需要后续执行 qemu-img check -r allqemu-img convert 来回收空间)。

在线快照:保存内存状态(hibernate)

若希望保存虚拟机的完整运行状态(内存、CPU、设备),需要在 QEMU 监视器(Monitor)中操作。这适用于虚拟机正在运行时。

  1. 启动虚拟机时添加监视器支持,通常使用 -monitor stdio-qmp(QEMU 管理协议)。最简单的是通过 stdio 在控制台直接交互:
    qemu-system-x86_64 -hda test-vm.qcow2 -m 2G -monitor stdio
    
  2. 进入 QEMU 命令行(出现 (qemu) 提示符)。
  3. 创建完整状态快照(磁盘+内存):
    savevm my_running_snapshot
    
  4. 稍后恢复运行状态:
    loadvm my_running_snapshot
    
  5. 查看所有内存快照:
    info snapshots
    

savevm 会将磁盘快照和内存状态一起保存到 qcow2 镜像文件中。注意:内部内存快照不能与外部快照同时使用;且镜像必须是 qcow2 格式。

外部快照:更安全的生产级方案

内部快照所有数据堆在一个文件里,容易造成文件肥大且不够灵活。外部快照则通过“写时复制”层链来实现:原始基础镜像变为只读,一个新 qcow2 文件作为覆盖层记录所有更改。

创建外部快照

qemu-img create -f qcow2 -b test-vm.qcow2 -F qcow2 snapshot_overlay.qcow2
  • -b 指向后备基础镜像(backing file)
  • -F 指定基础镜像的格式

此时 snapshot_overlay.qcow2 只包含与基础镜像的差异,可以单独使用。启动虚拟机时直接指定该覆盖文件:

qemu-system-x86_64 -hda snapshot_overlay.qcow2

基础镜像 test-vm.qcow2 一定要保持原样不变动,因为覆盖层依赖于它。

回滚外部快照

回滚只需要删除覆盖文件并重新创建一个基于同一基础镜像的新覆盖层即可。或者,你可以先将覆盖层合并回基础镜像:

qemu-img commit snapshot_overlay.qcow2

这会将覆盖层中的更改合并到其后备基础镜像中,然后可以删除覆盖文件。

查看外部快照链信息

qemu-img info snapshot_overlay.qcow2

会显示 backing file 路径及格式。

虚拟机迁移:手动 QEMU 迁移

QEMU 支持在线迁移(live migration),可将运行中的虚拟机从一台主机迁移到另一台,几乎无停机。这要求两台主机能直接网络通信,且具有共享存储(或至少相同的磁盘内容)。

在线迁移基本步骤(非共享存储)

对于没有共享存储的环境,通常采用 基于 UNIX 套接字的迁移TCP 迁移,并结合磁盘复制的思路。这里以 TCP 迁移并手动同步磁盘状态为例(假设基础镜像已复制到目标主机)。

  1. 源主机 启动虚拟机并准备迁移:

    qemu-system-x86_64 -hda /path/to/disk.qcow2 -m 2G -monitor tcp:0.0.0.0:4444,server,nowait
    

    使用 TCP 监视器以便远程控制。

  2. 目标主机 预先准备好相同的 qcow2 镜像(可通过 scp 或提前复制)。启动一个“接收”模式的 QEMU 实例,监听迁移:

    qemu-system-x86_64 -hda /path/to/disk.qcow2 -m 2G -incoming tcp:0:4445
    

    这里 -incoming 参数指定接收来自此地址的迁移流。

  3. 源主机 通过监视器发起迁移: 连接到源主机监视器(例如使用 telnet source_host 4444 或通过之前 -monitor stdio 方式),执行:

    migrate -d tcp:target_host:4445
    

    -d 表示后台执行,也可使用 migrate_set_speed 限制带宽。

  4. 查看迁移状态

    info migrate
    

    等待状态显示为 completed

  5. 迁移完成后,源虚拟机自动暂停(或你可选择手动关闭),目标虚拟机继续运行。

无共享存储的块迁移

若目标主机没有基础镜像,QEMU 支持在迁移过程中一同传输磁盘内容(块迁移)。只需在源监视器中加入 -b 选项:

migrate -d -b tcp:target_host:4445

这会在后台同步磁盘数据,但会显著增加迁移时间和网络负担,不适合大磁盘。

使用 Virsh(libvirt)简化迁移

如果你使用 libvirt 管理虚拟机,迁移只需一条命令:

virsh migrate --live <vm_name> qemu+ssh://target_host/system