qemu-img 实战指南:虚拟磁盘镜像管理全解析
2026/9/11 13:06:25 网站建设 项目流程

qemu-img 这个命令,搞虚拟化、搞云计算运维的基本都绕不开。做镜像创建、格式转换、磁盘扩容、快照管理,凡是跟虚拟机磁盘镜像打交道,它都是最趁手的那把工具刀。这篇东西我打算不写“教科书”,就按我日常维护集群和做镜像模板时真正会碰到的场景来拆,从命令行的每个参数怎么用,到后端镜像的关系、扩容时分区表的联动、快照链怎么避免踩坑,配合实际能跑通的案例串一遍。不管你是刚接手公司虚拟化平台的运维新手,还是自己折腾 QEMU/KVM 做实验的同学,照着步骤过一遍基本都能直接用起来。

  1. 认识 qemu-img:先搞清楚它是干什么的

1.1 一句话定位与整体命令观

qemu-img 是 QEMU 项目自带的磁盘镜像管理工具,装好 qemu-kvm 或者 qemu-utils 之后就能直接用,不需要额外装独立程序。它的核心职责是:创建指定大小和格式的虚拟磁盘镜像文件,在不同镜像格式之间做转换,查看镜像的详细信息,检查镜像是否有损坏,对镜像扩容缩容,以及管理镜像内部的快照。

在真实的业务里,它最常见的两个场景:一个是做云平台底层的镜像模板,需要把原始格式的虚拟磁盘统一转成 qcow2 并做压缩;另一个是日常排障,比如虚拟机数据盘满了要扩容,或者怀疑镜像文件异常变大、启动异常,都需要先用 qemu-img 去摸底。它走的是纯命令行交互,没有图形界面,但正因为不带任何花活,在脚本化、批量处理的场景里反而是最可靠的。

刚上手的人容易犯的一个毛病是:把 qemu-img 和 qemu-system-x86_64 混在一起理解。其实前者只处理“静态”的镜像文件,不会去启动虚拟机;后者才负责真正把镜像作为磁盘启动起来。也就是说,你在虚拟机运行状态下去动它的镜像文件,大概率会出问题,后面我会专门讲这个边界。

1.2 镜像格式怎么选:raw、qcow2 与其它

qemu-img 支持的格式非常多,兄弟们日常用到的基本就是 raw、qcow2,迁移和对接外部平台时会碰到 vmdk、vhdx、vpc。选格式这件事,本质上是在“性能”“功能”“空间占用”三者之间做取舍。

raw 格式是最原始的磁盘映像,数据怎么落盘就怎么存,没有快照、没有压缩、没有后端镜像这些概念。它的优势是性能损耗几乎为零,读写最直接;劣势是创建一个 100G 的 raw 文件,如果采用预分配方式,就会立即占用 100G 空间,即便里面全是空数据也一点不含糊。不过在本地单机做高 IO 场景,或者需要挂载回环设备直接使用的时候,raw 依然很有价值。

qcow2 是 QEMU 自己的写时复制格式,也是生产环境用得最多的。它支持按需分配空间、内部快照、压缩、AES 加密、后端镜像几个核心特性。一个声明 100G 的 qcow2 文件,如果只写入了 2G 数据,实际文件往往只有几 G,非常省空间。这个特性带来的代价是写入路径上多了一层元数据处理,跨页写入时有一定额外开销,但在绝大多数业务场景下影响可以忽略。

vmdk 是 VMware 的格式,vhd/vhdx 是 hypervisor 常用格式。qemu-img 都能读能写,做跨平台迁移时只需要一条 convert 命令。还有一个 vpc 格式严格说属于老掉牙的产物,我平时很少碰,只有在接手某些古董虚拟机的时候才会用 qemu-img 去识别一下。

我做镜像选型时的判断标准是这样:如果是给生产虚拟机做系统盘,无脑上 qcow2,快照和数据盘扩容都方便;如果是要做裸设备映射,或者放在本地高性能存储上跑数据库,raw 更省心;如果是给外部平台准备的交付镜像,先确认目标平台的格式要求,再转换。

格式 | 分配方式 | 快照 | 压缩 | 典型场景 raw | 全量或稀疏 | 不支持 | 不支持 | 高性能本地盘、回环挂载 qcow2 | 按需分配 | 支持 | 支持 | KVM 虚拟机系统盘、模板镜像 vmdk | 按需分配 | 支持(依赖平台) | 支持 | VMware 迁移/兼容 vhdx | 按需分配 | 支持 | 支持 | Hyper-V 迁移/兼容 vpc | 全量 | 基本不用 | 不支持 | 老式虚拟化平台

1.3 常用子命令速查

qemu-img 的子命令看起来很多,但常用的就那么几个,先列一张速查表,后文会逐个展开。

子命令 | 功能说明 create | 创建新的镜像文件 info | 查看镜像信息 convert | 转换镜像格式 resize | 调整镜像大小 snapshot | 管理内部快照 rebase | 调整后端镜像关联 commit | 把差异数据合并回后端镜像 check | 检查镜像一致性 measure | 预估转换输出大小 dd | 像 dd 一样转换镜像文件部分数据

我日常写脚本时用最多的组合是 qemu-img info + qemu-img convert + qemu-img resize,这三个能解决 80% 的镜像管理需求。剩下 snapshot 和 rebase 属于“高级功能”,功能强大但坑也多,需要用的时候务必先理解原理。

  1. 镜像创建:从零开始做出能用的虚拟磁盘

2.1 create 命令的完整姿势

创建镜像是接触 qemu-img 的第一步,也是最不该出错的步骤。一条最基本的创建命令长这样:

qemu-img create -f qcow2 /data/vm/ubuntu-20.04.qcow2 50G

-f 指定格式,后面是镜像文件路径,再后面是磁盘大小。这个“50G”指的是虚拟磁盘容量,也就是虚拟机内部看到的硬盘大小,并不代表文件马上占 50G。全部参数可以用 qemu-img create --help 查看,或者直接 man 一下。

创建 qcow2 时除了 -f 和大小,有几个可选参数值得注意。-o 参数可以指定很多属性,比如:

qemu-img create -f qcow2 -o preallocation=metadata,compat=1.1 /data/vm/test.qcow2 20G

compat=1.1 会使用较新的 qcow2 特性,老版本 QEMU 可能不认识;preallocation=metadata 会在创建时预分配元数据空间,好处是首次写入时不用再临时分配元数据,随机写性能会稳定一点。如果你的宿主机内核和 qemu 版本都比较新,建议显式写成 compat=1.1,否则某些老工具链可能无法识别。

还有个贴士:如果你在一个空间紧张的分区上创建大镜像,又不想让它立即占满磁盘,qcow2 的“延迟分配”就是救星。但如果你的存储本身就是一个支持精简配置的分布式存储,比如 Ceph RBD,那其实更推荐直接用存储层的块设备,而不是在文件系统里再套一层 qcow2,性能差很多。

2.2 后端镜像与 Copy-on-Write:一个镜像拉起一批虚拟机

backend file,也就是后端镜像,是 qcow2 最核心也最容易用错的功能。用一句话解释写时复制:底层镜像作为只读模板,上层镜像记录所有差异数据。多个上层镜像共享同一个底层镜像,看起来每个虚拟机都有自己的完整磁盘,实际上公共部分只在底层镜像存了一份,省下的空间非常可观。

创建差分镜像的命令是:

qemu-img create -f qcow2 -b /data/templates/ubuntu-base.qcow2 -F qcow2 /data/vm/node1.qcow2

-b 指定后端镜像路径,-F 指定后端镜像的格式。这条命令跑完后,node1.qcow2 的实际文件会非常小,只有几 M(甚至几百 K),但它对外声称的大小和底层镜像一致。虚拟机启动后,读命中底层镜像,写操作全部落到上层。

这里有几个必须注意的点。第一,-F 参数千万不要省,尤其是在后端格式不是 qcow2 的时候,明确指定能让后续的检查少走很多弯路。第二,后端镜像在差分盘的使用周期内,绝对不能被修改或删除,否则上层镜像直接失效。第三,如果虚拟机只是做临时测试,用完就删,差分盘很香;但如果这个虚拟机要长期运行,并且会产生大量写入,差分盘会一直在“文件系统层”上增加数据块,文件会慢慢膨胀,后续备份和迁移都会变重。

实际项目里我很少在“生产虚拟机”上用差分盘,更多是用它来做批量克隆的交付方式。先做一个小而全的基础模板,再用脚本快速生成几十个差分盘,配合 cloud-init 完成 IP 和主机名初始化,一次性拉起一批测试环境,体验非常酸爽。

2.3 预分配策略:空间与性能的取舍

qcow2 的预分配参数有三个可选值:off、metadata、full,raw 格式也支持 falloc 和 full,但 raw 本身在稀疏模式下就已经天然“延迟分配”,所以重点还是看 qcow2。

off 就是完全不预分配,创建时文件最小;metadata 会预分配元数据区,文件大小会明显比 off 大一点,但写入时不需要再临时申请元数据;full 会把整块虚拟磁盘空间全部真正分配出来,创建大型镜像的过程会比较慢,文件大小直接等于虚拟磁盘大小。

我实际测试下来,如果虚拟机要跑的是数据库这类随机写密集型业务,用 preallocation=metadata 配合稍大的 cluster_size(比如 64K),在创建索引或批量导入数据时会有肉眼可见的性能提升。如果只是普通 Web 服务或者做桌面测试,用默认的 off 就好,没必要多占空间。至于 full,在本地 NFS 或普通磁盘场景我基本不用,它唯一优势是避免“写时分配延时”,但现代存储都有缓存和分层,这个优势远不如空间浪费来得痛。

  1. 镜像转换与迁移:格式互通才是真本事

3.1 convert 命令的完整流程

格式转换是 qemu-img 高频使用场景。最常见的动作是 raw 转 qcow2,或者反过来做镜像导出。一条典型的转换命令:

qemu-img convert -f raw -O qcow2 /data/raw/disk.raw /data/qcow2/disk.qcow2

-f 表示源格式,-O(大写 O)表示目标格式,后面跟源文件路径和目标文件路径。注意 -f 有时可以不写,qemu-img 会自动探测,但自动探测偶尔会把某些“无特征文件”识别错,所以能明确就尽量明确。转 vmdk 喂给某 v 字头平台时,多加一句:

qemu-img convert -f qcow2 -O vmdk -o compat6 /data/qcow2/disk.qcow2 /data/vmdk/disk.vmdk

这里 -o compat6 是为了兼容老版本 vmdk 格式,如果对方平台太老,用默认的 vmdk 描述符可能起不来。反过来从 vmdk 转到 qcow2:

qemu-img convert -f vmdk -O qcow2 /data/vmdk/disk.vmdk /data/qcow2/disk.qcow2

这条几乎用来做“从友商平台迁移到 KVM”的必经步骤。转换期间源文件必须处于一致状态,最好是虚拟机已关机状态下操作,否则转出来的镜像在下次启动时可能报文件系统错误。如果要迁移的是正在运行的虚拟机,建议先做快照或者用文件系统快照工具,再基于快照转,而不是直接对着活着的镜像硬转。

3.2 压缩与稀疏:空间管理两把刀

qcow2 支持压缩,可以在 convert 时加上 -c 参数,将写入目标镜像的数据进行压缩:

qemu-img convert -f qcow2 -O qcow2 -c /data/old/disk.qcow2 /data/new/disk-compressed.qcow2

这个命令一般用于“镜像瘦身”。一个跑了一段时间的虚拟机,如果内部删了大量文件,qcow2 文件并不会自动把空间还给宿主机,它只会越来越大。这时候 convert 到一个新文件,配合 -c 压缩,往往能大幅度减小体积。我在真实环境里见过一个 20G 的镜像文件,内部实际数据只有 5G,用这条命令压缩后直接变成 3G,效果立竿见影。

不过 -c 压缩也有代价:压缩过程非常吃 CPU,压缩时间和镜像大小成正比;压缩后的镜像在虚拟机后续写入时,每次都要对新写入的数据块做压缩,性能会有额外损耗。因此压缩适合做“归档模板”和“交付镜像”,不建议在长期运行的虚拟机系统盘上用。如果是临时救治一个占空间的镜像,转完压缩后,再正常转一遍不带 -c 的副本给虚拟机用,也是一个思路。

稀疏文件和压缩是两个概念。raw 格式也支持稀疏,也就是文件中存在大量“空洞”,这些空洞不会真实占用磁盘。判断一个文件是否稀疏,可以用 du 和 ls 对比:

ls -lh disk.raw du -h disk.raw

ls 显示的是逻辑大小,du 显示的是实际占用块大小。如果两个值差很远,说明这个文件是稀疏的。convert 在默认情况下会尽量保留稀疏特性,如果你想转出一个“完全填实”的 raw 文件,可以用 -S 参数控制稀疏阈值。比如:

qemu-img convert -f qcow2 -O raw -S 4k disk.qcow2 disk.raw

-S 4k 表示小于 4K 的连续零块会被视为空洞,从而保持稀疏;设成 0 表示禁止稀疏,转为全量文件。需要把镜像放到不支持稀疏的文件系统上时,才需要显式关闭稀疏。

convert 是不可逆操作,虽然目标文件出问题时还能用源文件重来,但一定要注意目标文件路径不能和源文件路径相同,否则大概率把源文件写坏。建议先转换到临时目录,再 mv 回来。

3.3 用 measure 预估输出大小

转换之前先知道结果到底多大,能避免磁盘空间炸掉。qemu-img measure 就是干这个的:

qemu-img measure -f qcow2 -O qcow2 /data/old/disk.qcow2

输出会告诉你 required 和 fully allocated 两个数值。required 是转换后最小可能占用的空间,fully allocated 是假设所有块都被分配后最大可能占用的空间。如果你要转换的源镜像正在被虚拟机使用,那么实际结果会更接近 fully allocated。这个命令尤其适合在自动化流程里加一个前置校验,空间不够就直接中断,免得跑到一半磁盘写满。

  1. 日常维护:resize、快照、rebase 与 commit 的实战

4.1 resize 扩容与缩容,分区表联动才是关键

虚拟机磁盘不够用,是运维群里出现频率最高的问题。qemu-img resize 可以调整镜像大小,但注意它只调整“虚拟磁盘”的大小,不会自动修改虚拟机内部的分区和文件系统,这一步必须由你手动补齐。

扩容命令很简单,可以带单位,也可以直接写绝对值或者相对值:

qemu-img resize /data/vm/disk.qcow2 100G qemu-img resize /data/vm/disk.qcow2 +20G

只加一个“+”,表示在原有基础上增加 20G;不加单位默认是字节,建议都用 G 或 T 显式写。执行完成后,进入虚拟机内部,先让内核重新识别磁盘大小,再用分区工具把空闲空间利用起来。以 Linux 为例,如果是整块盘直接做文件系统,可以:

growpart /dev/vda 1 resize2fs /dev/vda1

growpart 用来扩展分区,resize2fs 用来扩展 ext4 文件系统;如果是 xfs,用 xfs_growfs / 而不是 resize2fs。如果虚拟机里装的是 Windows,要在磁盘管理里右键分区选择“扩展卷”。

resize 缩容就麻烦很多,qemu-img 本身虽然也能 shrink,但 qcow2 shrink 目前只能缩小到某个固定值,且必须保证内部文件系统数据已经腾出足够空间。强烈建议不要在 qemu-img 去做缩容,而是先做文件系统缩容,再用 qemu-img convert 到一个小尺寸的新镜像,否则分分钟数据损坏。

关键提示:容量扩了但分区不扩,等于白扩。很多人做完 qemu-img resize 后,虚拟机里 df -h 看了一模一样,其实就是少了分区扩展这一步。另外,如果磁盘是 LVM 管理的,还要记得在 LVM 层面把 PV 扩一下再扩 LV。

4.2 snapshot 快照链:内部快照的正确玩法

qcow2 支持内部快照,也就是说在同一个镜像文件里保存多个时间点的状态。创建快照:

qemu-img snapshot -c before-update /data/vm/disk.qcow2

列出快照:

qemu-img snapshot -l /data/vm/disk.qcow2

回滚到某个快照:

qemu-img snapshot -a before-update /data/vm/disk.qcow2

删除某个快照:

qemu-img snapshot -d before-update /data/vm/disk.qcow2

看着很舒服,但实际用起来有几条“家规”。第一,创建快照必须保证镜像当前处于一致状态,最好虚拟机已关机或者通过 fsfreeze 冻结了文件系统,否则回滚回去可能碰到文件系统不一致。第二,内部快照和“基于后端镜像的差分盘”是两码事,内部快照是把快照点之后的差异增量存到同一个文件里,快照数量多了会显著增大镜像文件尺寸,同时读写性能也可能下降。第三,快照链不要建太深,一般在生产上我只保留最近 2-3 个快照,时间久了就赶紧 commit 掉。

如果业务上需要更强大的快照体系,比如瞬时快照和定时快照,更推荐用存储层方案,比如 LVM 快照、Ceph RBD 快照或者 ZFS 快照,这些是块级别的,不会把虚拟磁盘文件搞成“千层饼”。

4.3 rebase 与 commit:把差异合并回底层

当差分盘用了一段时间,底层镜像内容变了,或者你想把几个差分盘的数据合并到模板镜像上重新分发,就需要 rebase 和 commit。

先看 commit:

qemu-img commit -f qcow2 /data/vm/node1.qcow2

这条命令会把 node1.qcow2 里的所有差异数据写回它的后端镜像。成功后,node1.qcow2 就没什么用了。执行 commit 的硬性条件:所有基于这个后端镜像的差分盘都必须处于关机状态,且后端镜像不能被其他虚拟机占用。如果后端镜像还被其他人开着,commit 上去的数据可能会污染别人的视图。

再看 rebase,它的作用是改变一个差分镜像的后端镜像关联。最常见用法是:底层模板更新了,你想让差分盘基于新模板继续跑,而不是继续挂在旧模板上:

qemu-img rebase -b /data/templates/ubuntu-base-v2.qcow2 -F qcow2 /data/vm/node1.qcow2

不加任何额外参数时,rebase 会默认执行一次“可能比较耗时”的数据同步,把旧后端里被上层引用、新后端里又不存在的数据块复制到上层差分盘里。这样切换后端后,数据依然完整一致。如果明确新旧后端差异不大,可以加 -u 参数做“无同步”的快速 rebase,只改关联不拷贝数据,但前提是你自己确认数据不需要同步,这个参数用错就可能丢数据。

我的建议是:rebase 这种操作不要手贱去乱跑,除非你很明确整条快照链的来龙去脉。日常最安全的操作是先打快照,再执行 rebase,这样即使出问题还能回滚。

  1. 一致性检查与常见坑实录

5.1 check 命令与修复机制

qemu-img check 是镜像的“体检”入口:

qemu-img check /data/vm/disk.qcow2

它会遍历镜像的元数据和数据引用,找出 refcount 不匹配、泄漏的簇、损坏的 L1/L2 表等问题。正常输出会提示 “No errors were found”。如果检测到错误,可以尝试加 -r all 参数修复:

qemu-img check -r all /data/vm/disk.qcow2

但有一点必须清醒:check 修复的是“镜像元数据层面”的完整性,不等于恢复你删掉的文件。如果错误出在有数据内容的簇上,-r all 可能会让对应数据块指向错误位置,导致访问题文件变化。因此我建议任何修复动作之前,先把原镜像拷一份再动手,修复后的镜像要在测试虚拟机里启动验证。

日常巡检中,我习惯在批量维护窗口里对所有关机状态的虚拟机执行一次 check,统计是否有 leaked 或 corrupt 项。只是 leaked 可以等下次 convert 时自动消除,不必太紧张;真正需要关注的 error 是 corrupt 和 wrong refcount。

5.2 高频踩坑记录

这张表里全是实战中遇到的高频问题,每一个我都付费踩过。

现象 | 原因 | 解法 镜像文件越来越大,无法自动回收 | qcow2 不会自动 shrink | 使用 qemu-img convert 重新转换为新文件 resize 后虚拟机内部容量没变化 | 只扩了磁盘,没扩分区和文件系统 | 在虚拟机内执行 growpart + resize2fs / xfs_growfs,Windows 用磁盘管理扩展卷 启动虚拟机报告“空间不足”但宿主机空间充足 | 差分盘写满或快照过多 | 检查 qemu-img info 的 disk size,清理旧快照或 commit 差分盘 镜像被误删/后端镜像丢失 | 差分盘依赖后端模板 | 用 qemu-img rebase 指定新后端,条件是新后端内容与旧后端一致 转换 vmdk 到 qcow2 后引导失败 | 某些 vmdk 描述符带加密或 streamOptimized 特性 | 先用 vmware-vdiskmanager 或 vmx 转成 monolithicSparse 再转 qcow2 虚拟机运行中执行 qemu-img 命令导致锁异常 | QEMU 对镜像文件有锁机制,裸调命令可能绕过检查 | 不要在虚拟机运行时直接改镜像;扩容等操作先关机 快照回滚后文件读取异常 | 创建快照时文件系统未冻结,状态不一致 | 创建内部快照前必须冻结文件系统或关机

5.3 自动化脚本里的实用技巧

qemu-img 命令非常适合嵌入运维脚本,分享几个我实际使用的套路。

批量查看镜像信息:

for img in /data/vm/*.qcow2; do echo "==>>> $img"; qemu-img info "$img" | grep -E "virtual size|disk size|cluster_size"; done

批量为所有关闭状态的虚拟机做一致性检查,并把异常输出到文件:

for img in $(find /data/vm -name "*.qcow2" -type f); do result=$(qemu-img check "$img" 2>&1 | tail -1) echo "$img : $result" echo "$img : $result" >> /var/log/qemu-img-check.log done

用这个脚本每周跑一次,能提前发现很多隐患。

convert 时保留进度条:

qemu-img convert -p -f qcow2 -O qcow2 -c disk.qcow2 disk-compressed.qcow2

-p 参数会显示完整进度,批量转换大量镜像时心里有底。如果机器 CPU 核数多,还可以用 qemu-img 自带的“并行压缩”能力,不过这里更推荐直接串行配合后台任务,避免 CPU 被吃满影响线上虚拟机。

到了这步,qemu-img 的主要功能基本都覆盖到了。我个人在实际操作中的体会是:这个工具的命令参数并不难,真正决定成败的往往是你对镜像格式和快照链路的理解深度。多花点时间把后端镜像、快照、commit 这几个概念在测试环境里反复玩几遍,比死记命令要管用得多。最后再分享一个小技巧:给模板镜像做任何结构性操作之前,先跑一条 qemu-img info 和 qemu-img check,确认无误后再动手,这个习惯能帮你挡掉绝大多数低级事故。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询