qcow2文件不会自动变小,必须在客户机内填零并用qemu-img convert重写镜像才能释放物理空间;因其稀疏特性仅跳过从未写入的块,而已删除但残留非零数据的块需先清零,convert时才能识别并省略全零块。

直接结论:qcow2 文件不会自动变小,必须在客户机内填零 + 宿主机上 qemu-img convert 重写镜像,才能真正释放物理空间。
为什么 qemu-img convert 能压缩 qcow2 实际占用?
qcow2 的稀疏特性只对「从未写入过的块」有效;已写入又删除的块仍保留旧数据(非零),qemu-img convert 默认跳过全零数据块,但不会跳过残留的随机字节。所以必须先让客户机把空闲空间填成真正的 0x00,转换时才能识别并省略这些块。
-
-O qcow2是必须的,它重建镜像结构,丢弃未被引用的零块 -
-c(compress)参数仅压缩元数据,对实际空间节省几乎无用,且显著拖慢速度,不推荐 - 目标镜像必须是新文件名,
qemu-img convert不支持原地覆盖 - 转换后需手动替换虚拟机磁盘路径或 XML 配置,否则仍加载旧镜像
Linux 客户机内填零的实操要点
填零不是越快越好,关键是覆盖所有可访问的空闲空间,包括 swap、LVM 逻辑卷、独立挂载点等。
- 先禁用 swap:
swapoff -a,再用dd if=/dev/zero of=/swapfile bs=1M count=1024清零 swap 文件(若使用文件型 swap) - 对每个挂载点分别填零,例如
/home单独挂载时,需在该目录下执行dd if=/dev/zero of=junk - 填零完成后必须
sync,再rm junk,否则部分零块可能未刷盘 - 如果客户机启用了
fstrim(如 ext4 + discard 挂载选项),可在关机前运行fstrim -av,但效果不如填零稳定
宿主机执行 convert 前必须检查的三件事
临时空间不足、权限错误、镜像被锁定,是 qemu-img convert 失败最常见的三个原因。
- 临时目录剩余空间至少是原镜像大小的 1.5 倍——
qemu-img convert会边读边写,中间状态可能瞬时占用双倍空间 - 确保宿主机有读取客户机镜像的权限,特别是使用 libvirt 管理时,镜像常属
root:libvirt,普通用户需加sudo或改组 - 确认虚拟机已完全关机(
virsh list --all中状态为shut off),而非暂停(paused)或崩溃(crashed),否则镜像文件被 qemu 进程锁住
最易被忽略的是:填零操作必须在客户机「关机前最后一刻」完成,且不能依赖 systemd 的 shutdown 服务自动清理——很多发行版会在关机流程中提前 umount 分区,导致 junk 文件无法写满或 sync 失效。手动执行、亲眼确认 dd 报出 No space left on device,才是可靠信号。











