我们正在使用带有 qcow2-images 的 kvm/qemu 作为虚拟机。
qcow2 有一个很好的功能,即图像文件仅分配虚拟机实际需要的空间。但是,如果虚拟机的分配空间变小,我该如何缩小图像文件?
例子:
1.) 我创建了一个 qcow2 格式的新图像,大小为 100GB
2.) 我使用此映像来安装 ubuntu。安装需要大约 10 GB,映像文件最大增大到大约 10GB。到目前为止没有什么意外。
3.) 我在图像中填充了大约 40 GB 的额外数据。图像文件大小增加到了 50GB。我对此没意见 :-)
4.) 奇怪的地方就在这里:我删除了图像上的所有 40GB 数据,但图像大小仍然占用了 50GB。
问题:我如何释放 40GB 的数据并将图像缩小到仅需要的 10 GB?
提前致谢,伯尼
答案1
virt-sparsify 可以完成所有这些工作,减少您的麻烦: http://libguestfs.org/virt-sparsify.1.html
答案2
图像不会自动缩小,因为删除文件时实际上并没有删除数据(这就是取消删除功能起作用的原因)。Qemu 有一个功能可以将 qcow2 图像缩小,但该实用程序实际上所做的是从磁盘中删除重复的零,而其他所有信息保持不变。因此,这个想法是:
- 将驱动器填零(
dd if=/dev/zero of=/some/file
直到空间不足) - 删除/一些/文件
- 关闭虚拟机
- cd 到虚拟机镜像保存的位置并运行
qemu-img convert -O qcow2 original_image.qcow2 deduplicated_image.qcow2
- 更改虚拟机设置以使用新的 deduplicated_image.qcow2,测试虚拟机是否正常工作,然后删除旧映像
据我所知,这只适用于 qcow2 图像,我还没有测试其他格式。
答案3
除了可接受的答案(描述了缩小 qcow2 文件的更常见、更通用的方法)之外,libvirt/qemu/qcow2 堆栈的现代版本(即:RHEL7+)提供了virtio-scsi
支持该discard='unmap'
选项的驱动程序。
如果虚拟机使用virtio-scsi
并且 libvirt 定义包含discard='unmap'
,则客户机文件系统上的简单操作fstrim
将释放主机上已分配但未使用的可用空间。这可以du -hs <guestdisk>
在主机端使用进行检查(注意:ls -al <guestdisk>
将不是显示实际分配的大小,仅是逻辑分配的大小)。
注意:qemu 4.x 也添加了discard
对的支持virtio-blk
,因此不再需要virtio-scsi
trim 才能工作。
在较新的 libvirt/qemu 实例(即 RHEL8+)上,使用时,virtio-scsi
即使客户机操作系统不支持 trim,也可以减少客户机文件大小:通过启用两个都 discard='unmap'
并且discard_zeroes='unmap'
在客户机端写入连续的零流(即通过dd if=/dev/zero of=/zero.img bs=1M count=1024
)将触发受影响的 LBA 范围的主机大小修剪。但是,请注意,这可能会占用大量 CPU(主机必须“解析”任何客户机写入以搜索重复的零),因此应仅在特定情况下启用它。
这两种方法都会减少身体的分配的大小(du -hs
显示的内容)。为了减少逻辑大小(简单ls -al
给出的内容),您需要使用virt-spasify
或qemu-img
(如其他答案中所述)。
答案4
virt-sparsify --compress fileA fileB
会减小图像的大小,但是它会将 qcow2 图像创建为另一个文件,因此您必须重命名和移动其中的内容。您不能同时使用--compress
和。请参阅以下链接以了解更多信息。--in-place
http://libguestfs.org/virt-sparsify.1.html