KVM虚拟机快照频繁导致磁盘膨胀,快照清理最佳实践
KVM 虚拟机快照频繁生成后,qcow2 磁盘文件会持续膨胀,不仅占用宿主机空间,还会拖慢虚拟机读写性能。
清理快照的关键不是直接删除快照文件,而是把快照数据合并回磁盘并解除快照链。
本文会从快照查看、合并清理、休眠处理、验证方式四个角度讲清楚,零基础用户也可以照着命令直接操作。
为什么频繁快照会让磁盘膨胀
qcow2 磁盘采用写时复制机制,快照生成后新数据写入独立快照层,底层镜像不变。
快照越多,磁盘链越长,每次写入都要向上层查找数据,IO 开销和文件体积同步增长。
频繁创建又不清理,宿主机的可用空间会被快速蚕食,虚拟机还可能因为磁盘占满而出现 IO 错误。
清理前先看清快照链
先用 virsh list --all 查看虚拟机列表,再用 virsh snapshot-list <虚拟机名称> 查看该机器的全部快照,注意观察 Creation Time 和 State。
State 为 running 的只是创建快照时虚拟机处于运行态,不代表快照正在被使用。
virsh list --all
virsh snapshot-list centos7-test
如果快照很多,建议先写个带日期的记录文件,避免清理时误删或分不清对应关系。
快照清理的正确操作顺序
清理快照不能直接删除 .qcow2 文件或调用 virsh snapshot-delete 硬删,这样可能让当前磁盘链断裂,虚拟机无法启动。
推荐用 virsh blockcommit 将顶层快照数据逐步合并回底层镜像,然后删除无用快照对象。
方式一:在线合并,虚拟机不关机
前提是虚拟机处于运行状态,且宿主机有足够空间容纳临时数据。
执行以下命令,把当前活动层数据提交到基础镜像:
virsh blockcommit centos7-test vda --active --wait --verbose
这里的 vda 是虚拟磁盘目标名,可用 virsh domblklist centos7-test 查询。--active 表示提交活动层,--wait 等合并完成,--verbose 输出进度。
完成后磁盘链会简化,但还需要清理对应的快照记录:
virsh snapshot-list centos7-test
virsh snapshot-delete centos7-test <快照名称> --metadata
方式二:离线合并,虚拟机休眠后进行
如果虚拟机当前 IO 压力大,或者块合并一直报错,建议先休眠再处理。
对运行中的虚拟机执行:
virsh suspend centos7-test
挂起后磁盘状态相对稳定,再用 virsh blockcommit 合并。
合并完成后再执行 virsh resume centos7-test 恢复运行。
如果你的虚拟机已经关机,直接用以下方式最稳妥:
virsh snapshot-list centos7-test
virsh blockcommit centos7-test vda --base vda snapshot-two --top snapshot-one
实际操作中 --base 和 --top 参数容易写反,新手建议用最简单的 --active --wait,让 libvirt 自动处理整个链。
避坑清单:这几点最容易出问题
- 宿主机空间不足时不要执行块合并。先
df -h确认磁盘剩余空间大于虚拟机磁盘实际占用,否则合并过程中空间耗尽会直接导致磁盘损坏。 - 删除快照元数据不要加
--children以外的手动范围。如果确实只想保留某几个快照,先画清快照树:virsh snapshot-list --tree。 - virsh blockcommit 失败时检查磁盘目标名。很多报错来自
vda写成了sda,用virsh domblklist确认即可。 - 不要同时清理多个虚拟机的快照。并行合并会成倍增加宿主机 IO 负载,可能引发并发写入冲突。
- 快照清理完成后,记得用
virsh snapshot-list确认不再有悬挂快照。如果只剩当前指向,说明链已经收敛。
清理后如何确认磁盘真的瘦身了
查看虚拟机关机状态下的磁盘文件大小:
ls -lh /var/lib/libvirt/images/centos7-test.qcow2
注意文件大小不一定立刻变小,因为 qcow2 不会自动释放已占用的簇。
要真正缩减文件体积,建议做一次磁盘碎片整理和空白区回收。
对 Linux 客户机,在虚拟机上执行:
fstrim -av
然后在宿主机运行:
alpine qemu-img convert -O qcow2 centos7-test.qcow2 centos7-test-compact.qcow2
mv centos7-test-compact.qcow2 centos7-test.qcow2
如果宿主机是 Debian/Ubuntu,alpine 替换为 qemu-img 即可。
转换完成后启动虚拟机,确认系统正常,再把原文件备份删除。
另外,建议每隔一段时间用 virsh snapshot-list 做一次快照年龄检查,清理 7 天前不再需要的快照。
快照不是保护数据的主要手段,定期同步数据到外部存储才是更可靠的方式。
遇到快照清理后虚拟机无法启动,先不要删除任何磁盘文件。
用 virsh start <虚拟机名称> 看报错提示,再结合本文的合并方式重新整理快照链。
多数情况下,只要不强行删底层镜像,数据都可以找回。
如果你正在处理 KVM 虚拟机快照频繁导致磁盘膨胀的问题,建议先按本文步骤完整执行,再根据自己的环境做微调;
遇到异常时优先回看避坑和高频问题部分。