qemu-img 完全指南:虚拟机磁盘镜像创建、转换与扩容实战手册
2026/9/11 4:59:05 网站建设 项目流程

玩虚拟化的人迟早会撞上qemu-img这面墙。不管你是用 KVM、Proxmox VE 还是单纯想在本地跑个 QEMU 虚拟机,磁盘镜像的创建、转换、扩容、快照最终都会落到这个命令行工具上。它不像图形界面那么直观,但恰恰是这种“丑”和“硬”,让它在脚本化运维和批量处理时异常可靠。这篇文章不是照搬 man page,我把自己在实际操作中反复用到的命令、踩过的坑和几个完整的处理案例整理了一份手册,新老手都能在里面找到点东西。

1. 入手之前:qemu-img 到底解决什么问题

1.1 虚拟磁盘镜像是什么,什么时候需要 qemu-img

先说说最基础的概念。虚拟机里的硬盘不是一块真实的物理磁盘,而是一个文件,这个文件就是“磁盘镜像”。按照格式不同,它可能是厚厚的一块完整空间,也可能是一个只记录实际写入数据、随用随长的瘦文件。qemu-img就是用来操作这批文件的瑞士军刀:创建、转换格式、查看信息、检查一致性、扩容缩小、管理快照,全部由它包办。

什么时候你一定会用到它?举几个典型场景:刚装完一台 CentOS 虚拟机,想把 qcow2 转换成 raw 格式以便做物理机迁移;磁盘分区快满了,想在不破坏数据的前提下给虚拟机硬盘增加 20G 空间;拿同一块基础镜像批量克隆几台测试机;或者只是单纯想知道那块 qcow2 文件为什么比预想的大很多。这些操作如果不用qemu-img,就得借助商业虚拟化平台或者折腾 GUI 工具,效率低不少。

1.2 安装与基础准备

多数 Linux 发行版默认不自带qemu-img,但它通常会随 QEMU 组件一起安装。Debian/Ubuntu 上执行:

apt install qemu-utils -y

CentOS/RHEL 系则是:

yum install qemu-img -y

装完之后先验证一下版本,不同版本在某些参数行为上略有差异:

qemu-img --version

我建议你先建一个干净的实验目录,准备一块 1G 左右的测试镜像,后面所有命令都能在上面练手。用 root 或对目录有写权限的普通用户操作都可以,但要注意,后续如果要挂载或转换系统盘,通常需要 root 权限。

2. 镜像创建:从命令行到一块真实磁盘

2.1 三种主流镜像格式的特性对比

qemu-img支持很多格式:raw、qcow2、qed、vmdk、vhdx、vdi、luks 等。但日常用得最多、最值得深入理解的就是 raw 和 qcow2 两种,vmdk 则常见于 VMware 互操作场景。

raw 格式最直接,它就是把虚拟磁盘按字节展开成一个大文件,没有额外元数据。优点是性能好、无需转换即可被很多工具直接读取;缺点是占用空间大、不支持快照等高级特性。qcow2(QEMU Copy On Write version 2)是目前 KVM 环境的绝对主流,它支持写时复制、快照、压缩、AES 加密、backing file(差异镜像)等特性,文件体积通常远小于虚拟磁盘大小,但伴随而来的是略微的性能开销。

vmdk 是 VMware 的格式,qemu-img也能读写,常用于混合虚拟化环境迁移;vhdx 是 Hyper-V 格式,跨平台迁移时会接触到。如果你没有特殊迁移需求,我不建议在 QEMU/KVM 环境里用 vmdk 或 vhdx 作为主力格式,兼容性和高级特性支持终归不如 qcow2 来得完整。

2.2 创建镜像的完整命令与参数选择

创建一块 qcow2 格式、大小为 10G 的镜像:

qemu-img create -f qcow2 disk.qcow2 10G

这一句执行完,你得到的大小并不是 10G,而是一个可能只有 193K 的稀疏文件。qcow2 是按需分配的,只有虚拟机真正写入时才在宿主文件系统上占用块。你可以用ls -lh看表象大小,用du -h看实际占用,两者会存在明显差异。

如果想一开始就预留全部空间,防止后续写入时因宿主机磁盘不足导致 IO 错误,可以加 preallocation 参数:

qemu-img create -f qcow2 -o preallocation=full disk-full.qcow2 10G

full 预分配会立即占用 10G,适合对性能敏感的生产虚拟机;metadata 预分配只把 qcow2 的元数据预留出来,文件稍大但创建速度快,适合大批量创建实例时折中使用。raw 格式则不一样,它默认就是完整空间,除非你用truncate之类的命令创建稀疏文件。

创建 raw 格式:

qemu-img create -f raw disk.raw 10G

这块 raw 文件会立即显示为 10G,但如果底层文件系统支持稀疏文件,实际占用的可能也只是少量块,后续写入时才逐渐增大。这个特性有时候挺迷惑人,检查磁盘占用量时务必用du而不是ls

2.3 预分配模式的性能差异

经常有人问:qcow2 加了 full 预分配之后,性能和 raw 还有多大差距?我的实测感受是,裸设备或者 raw 格式在顺序读写上确实略微领先,但 qcow2 在引入了cache=noneiothread之类的优化后,差距已经缩小到很难感知的程度,尤其在磁盘本身是 SSD 的情况下。

从运维角度来说,我更看重的是完整预分配带来的空间确定性。生产环境最怕的不是慢,而是虚拟机在深夜突然写入大量数据时发现宿主机目录满了,那种 IO 错误会导致虚拟机文件系统切换到只读模式,比慢更致命。所以重要业务我通常创建 qcow2 并加上preallocation=metadata,既保留一定的按需分配灵活性,又趁早把元数据结构固定下来。

3. 镜像转换与格式迁移:qcow2 与 raw 的取舍

3.1 convert 命令的标准用法

格式转换是qemu-img最高频的场景之一。把 qcow2 转成 raw:

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

-f指定源格式,-O指定目标格式,-O大写,这是新手最容易踩的坑。小写-o是传给目标格式的选项参数,作用完全不同。如果省略-fqemu-img会尝试自动检测;如果省略-O,默认输出格式也是 raw。为了安全和明确,我习惯每次都把这两个参数显式写出来。

转换过程中,有一个细节值得注意:convert默认只拷贝实际有数据的块,目标 raw 文件会是一个稀疏文件。如果你希望转换后的 raw 文件完整占用所有空间,可以加-S 0参数,它表示所有扇区都视为“需要分配”,这样目标文件就不会有稀疏特性。

3.2 压缩与优化:让镜像瘦下来

qcow2 转 qcow2 的常见误区是直接拷贝文件,这样不仅没有优化,反而可能把碎片和冗余块一起拷贝过去。正确姿势是用 convert 做一次重写,同时加上压缩:

qemu-img convert -f qcow2 -O qcow2 -c old.qcow2 new.qcow2

-c参数开启压缩。压缩效果取决于镜像内部数据的特征,我的经验是,装完系统加常用软件后未做大量碎片写入的镜像,压缩率通常能到 20% 到 30%;如果是数据密集型(比如放满日志和数据库文件的镜像),压缩收益会更大。

需要说明的是,convert不会保留源镜像的快照和 backing file 链信息。如果你有一块带快照的 qcow2,执行 convert 时会得到一个平面化的镜像,也就是把所有快照差异合并进底层数据,这通常正是你想要的“摊平”操作。但如果你希望保留快照结构,就别用 convert,老老实实复制文件。

3.3 格式选型建议

我给自己定过一条选型原则:长期保留的基础镜像用 qcow2,需要直通或跨平台导出的镜像用 raw,涉及到要搬到公有云或物理机直接引导的场景才考虑 vmdk/vhdx。新项目一律 qcow2,因为你永远不知道后续会不会需要快照或者差异镜像。

转换过程本身一般很稳,但有两个前提:一是源镜像不能在转换过程中被正在运行的虚拟机写入,否则可能得到损坏的镜像;二是目标分区要有足够空间,虽然 convert 通常不占用完整目标大小,但如果目标格式是预分配的,峰值空间会非常大。我在一次 vmdk 转 raw 时,源文件只有 40G,转的目标 raw 文件却瞬间占了 40G,宿主机余量不够直接失败,教训深刻。

4. 镜像检修与信息核验:别让隐患积累

4.1 info 命令的实用参数解读

给虚拟机做体检,第一件事就是查镜像信息:

qemu-img info disk.qcow2

输出会显示 format(格式)、virtual size(虚拟大小)、disk size(实际占用)、cluster_size(簇大小)等。如果镜像有 backing file(差异镜像),输出里会多一行backing file,后面跟着父镜像的路径。批量查看信息可以加--output=json,方便脚本解析:

qemu-img info --output=json disk.qcow2

有一个容易被忽略的信息:disk size通常只统计当前文件实际占用,但对于稀疏文件,不同文件系统报告的数值可能不一致。我习惯同时用qemu-img infodu -h交叉验证,尤其在判断“镜像是否异常膨胀”时,这两个数字的差异能说明很多问题。

4.2 check 命令:检查与修复

镜像文件在宿主机异常断电或宿主机磁盘损坏时,可能出现内部元数据不一致。qcow2 有自检机制,跑一遍:

qemu-img check disk.qcow2

它会扫描镜像内所有表项、refcount(引用计数)和快照信息,输出错误数。如果发现有 leaked clusters(泄漏簇)或 corruptions(损坏项),可以尝试:

qemu-img check -r all disk.qcow2

-r all表示尝试修复所有可修复的问题。但我必须提醒一句:check -r修复的是“镜像文件自身的一致性”,不是虚拟机内部文件系统的完整性。万一镜像内部元数据修复后,虚拟机里看到的文件系统可能还是需要 fsck 的。我处理过一次 qcow2 因宿主断电而报“Cannot get block status”的问题,-r all跑完后镜像能重新挂载,但里面一个 ext4 分区还是需要进救援模式 fsck 才能正常启动。

check做成定期巡检任务是个好习惯。线上虚拟化环境我一般用 cron 每周跑一次脚本,记录所有 qcow2 的 check 输出,一旦出现非零错误就立刻介入。镜像是虚拟机的唯一持久化载体,小问题积累成不可修复的大问题时,代价远超巡检的那点开销。

4.3 实际案例:定位一块无法启动的虚拟机磁盘

有次一台测试虚拟机重启后起不来,virsh list --all显示为 running,但 QEMU 进程反复崩溃。我先执行:

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

发现 virtual size 正常,但 disk size 比之前明显小了很多,立刻意识到文件可能截断了。qemu-img check报了一堆 cluster 错误和 refcount 错误,用-r all修复后表面通过,但虚拟机仍然无法启动。最后检查宿主机物理磁盘时发现该目录所在分区已经满了,再查看 inode 和空间输出,通过清理日志与导出镜像才恢复正常。

这个案例给我的教训是:镜像问题往往不是镜像自己的问题,而是宿主环境的延伸体现。接到镜像损坏的信号,第一反应可以查工具,第二反应必须查宿主机磁盘空间和文件系统健康度。

5. 镜像扩容、快照与高级玩法

5.1 resize:给磁盘扩容

虚拟机磁盘不够用是最常见的需求。qcow2 扩容:

qemu-img resize disk.qcow2 +20G

执行完,镜像的 virtual size 变大了,但虚拟机内部的分区和文件系统并不知道这块新空间,还需要进系统处理。如果是 Linux 的 virtio 磁盘,通常用growpart扩展分区,再用resize2fs扩展文件系统。比如磁盘设备名是/dev/vda,分区 2 是根分区:

growpart /dev/vda 2 resize2fs /dev/vda2

这里有个顺序问题:先扩展镜像,再扩展分区,最后扩展文件系统。反过来操作没有任何意义。Windows 虚拟机则需要从磁盘管理里直接“扩展卷”。

扩容只能增大,不能缩小吗?qemu-img resize也支持缩小,但需要先缩小虚拟机内部文件系统和分区,再缩小镜像,中间一丁点差错都会造成数据损失。我强烈建议不要轻易缩小 qcow2,除非你做了完整快照且验证过可恢复。raw 镜像缩小则要记得先转换,否则需借助truncate,操作风险更高。

扩展之后确认一下新镜像尺寸,方法很简单,直接看info的 virtual size 字段即可。

5.2 快照管理:snapshot 命令实战

qcow2 内建快照是它最值钱的能力之一。创建快照:

qemu-img snapshot -c before-upgrade disk.qcow2

查看快照列表:

qemu-img snapshot -l disk.qcow2

回滚到某个快照:

qemu-img snapshot -a before-upgrade disk.qcow2

删除快照:

qemu-img snapshot -d before-upgrade disk.qcow2

快照的底层原理是写时复制:创建快照后,原镜像所有新写入的数据会记录到快照差异区域,原数据块则保留下来用于恢复。这意味着快照创建后,镜像的 disk size 会持续增长,尤其在高写入负载下。

快照使用有几个硬性经验:第一,快照不是备份,宿主文件系统损坏时快照同样跟着遭殃;第二,快照链越长,读写性能劣化越明显,我一般控制在三层以内,完成状态验证后的临时快照会及时删除;第三,不要在快照存在的情况下直接用qemu-img convert做迁移,会得到平面化结果,如果这不是你的目的,会有很大隐患。

5.3 rebase 与 bitmap:被低估的两个功能

rebase 是配合 backing file 使用的高级操作。差异镜像(overlay)依赖一个基础镜像,rebase 可以把差异镜像的底层基础替换成另一个,或者在基础镜像被更新后把差异合并到新的基础上:

qemu-img rebase -b new-base.qcow2 overlay.qcow2

不加-u时,rebase 会执行实际的数据重写,这是一个耗时操作。如果只需要修改 backing file 的路径记录而保持数据不动,可以加-u(unsafe)模式。但只有在确认新旧底座差异不影响数据时才建议这么做,否则很容易出现逻辑错位。

bitmap(位图)是 qemu 增量备份的关键机制。给镜像创建一个持久位图:

qemu-img bitmap --add disk.qcow2 backup-bitmap

之后用qemu-img map查看区块映射,就能知道哪些块被写过。这个功能配合 libvirt 的增量备份接口,可以做到有效的备份容灾。日常小环境不一定用得上,但了解存在总比临时抓瞎好。

6. 常见问题与排查技巧实录

6.1 镜像大小异常:qcow2 显示比想象中大得多

跑了一段虚拟机后,qcow2 文件从几 G 涨到几十 G,这是写入量大的正常情况,但如果清理了大量数据后文件仍不缩小,就有问题了。qcow2 的典型特点是“只增不减”,删除文件只释放内部虚拟块,不会自动把物理空间返还给宿主机。解决办法就是做一次流式转换:

qemu-img convert -f qcow2 -O qcow2 disk.qcow2 compacted.qcow2

如果同时有多个虚拟机,注意分批操作,转换期间磁盘 IO 会比较高。

6.2 权限错误与格式误判:最常见的低级错误

执行qemu-img命令时遇到Permission denied,多数情况下不是工具问题,而是镜像文件的所有者与当前执行用户不一致。虚拟机镜像通常属于 qemu 用户或者 root,用普通用户操作时需要 sudo,或者提前chown修改属主。还有一种情况是目录本身没有写权限,转换目标文件写不进去。

格式误判也很常见:你把一个 qcow2 文件重命名为 .raw,然后用-f raw去读,结果报错。qemu-img不会根据扩展名自动识别格式,必须显式指定正确的-f,不确定时先跑qemu-img info自动检测。

6.3 其他典型问题速查表

问题现象可能原因推荐处理方式
qemu-img: Could not open镜像路径错误或格式指定错误qemu-img info检测,确认-f参数
虚拟机启动卡在引导阶段镜像损坏或快照链断裂qemu-img check,必要时-r all
resize 后虚拟机看不到新空间只扩了镜像未扩分区和文件系统进系统用growpartresize2fs或 Windows 磁盘管理扩展卷
转换中报No space left目标分区空间不足清理宿主机空间,或换到更大的目标目录
镜像 check 提示 leaked clusters上次异常退出未完全清理先备份,再check -r all
snapshot 后镜像文件膨胀迅速快照写时复制机制导致及时删除无用快照,避免长期保活

排查顺序我基本固定为:先info确认识别信息,再check确认健康度,再考虑转换或修复。不要一上来就-r all,修复动作本身是有副作用的,备份过再修更稳妥。

另外提一个细节:qemu-img操作大镜像时,如果宿主文件系统是 btrfs,建议先确认是否开启了 CoW。btrfs 默认对文件做写时复制,镜像本身又是高频写文件,叠加 CoW 会造成大量空间碎片和性能损耗。用chattr +C关闭镜像文件所在的目录或文件的 CoW 特性,是 btrfs 上跑 KVM 的一个重要优化点。

最后再分享一个我最近常干的事:用qemu-img convert结合 systemd timer 做每周一次的镜像“压缩保洁”。因为测试环境有大量临时虚拟机,删除后基础镜像不回收空间,每周自动转换一次,把没有实际数据的空洞全部清掉,宿主机磁盘空间稳定多了。qemu-img就是这样,命令本身不难,难的是你得知道在什么时机、用什么组合拳去处理镜像的真实状态。工具是死的,用法是活的,多在你的环境里跑几轮,它就能从“一个命令行工具”变成“你管理虚拟化环境最靠谱的右手”。

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

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

立即咨询