资讯动态

qemu-img 实战指南:虚拟磁盘镜像管理全解析

发布时间:2026/9/11 13:06:25 来源:尧图企业网站定制
qemu-img 这个命令搞虚拟化、搞云计算运维的基本都绕不开。做镜像创建、格式转换、磁盘扩容、快照管理凡是跟虚拟机磁盘镜像打交道它都是最趁手的那把工具刀。这篇东西我打算不写“教科书”就按我日常维护集群和做镜像模板时真正会碰到的场景来拆从命令行的每个参数怎么用到后端镜像的关系、扩容时分区表的联动、快照链怎么避免踩坑配合实际能跑通的案例串一遍。不管你是刚接手公司虚拟化平台的运维新手还是自己折腾 QEMU/KVM 做实验的同学照着步骤过一遍基本都能直接用起来。认识 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 属于“高级功能”功能强大但坑也多需要用的时候务必先理解原理。镜像创建从零开始做出能用的虚拟磁盘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 preallocationmetadata,compat1.1 /data/vm/test.qcow2 20Gcompat1.1 会使用较新的 qcow2 特性老版本 QEMU 可能不认识preallocationmetadata 会在创建时预分配元数据空间好处是首次写入时不用再临时分配元数据随机写性能会稳定一点。如果你的宿主机内核和 qemu 版本都比较新建议显式写成 compat1.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、fullraw 格式也支持 falloc 和 full但 raw 本身在稀疏模式下就已经天然“延迟分配”所以重点还是看 qcow2。off 就是完全不预分配创建时文件最小metadata 会预分配元数据区文件大小会明显比 off 大一点但写入时不需要再临时申请元数据full 会把整块虚拟磁盘空间全部真正分配出来创建大型镜像的过程会比较慢文件大小直接等于虚拟磁盘大小。我实际测试下来如果虚拟机要跑的是数据库这类随机写密集型业务用 preallocationmetadata 配合稍大的 cluster_size比如 64K在创建索引或批量导入数据时会有肉眼可见的性能提升。如果只是普通 Web 服务或者做桌面测试用默认的 off 就好没必要多占空间。至于 full在本地 NFS 或普通磁盘场景我基本不用它唯一优势是避免“写时分配延时”但现代存储都有缓存和分层这个优势远不如空间浪费来得痛。镜像转换与迁移格式互通才是真本事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 转到 qcow2qemu-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.rawls 显示的是逻辑大小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。这个命令尤其适合在自动化流程里加一个前置校验空间不够就直接中断免得跑到一半磁盘写满。日常维护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/vda1growpart 用来扩展分区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。先看 commitqemu-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这样即使出问题还能回滚。一致性检查与常见坑实录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_growfsWindows 用磁盘管理扩展卷 启动虚拟机报告“空间不足”但宿主机空间充足 | 差分盘写满或快照过多 | 检查 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 21 | 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确认无误后再动手这个习惯能帮你挡掉绝大多数低级事故。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价