我花了很多时间在网上搜索如何缩小 KVM 虚拟磁盘映像,尤其是对于 Windows 来宾,但没有运气。
我所发现的只是将 VM 可用空间归零,对虚拟磁盘进行碎片整理(来自 Windows),然后运行qemu-img convert -c ...
(-c
标志压缩)。
我有一个 Windows 7 VM,虚拟驱动器大小为 100 GB。最初,这个 VDD 在主机存储上花费了 40 GB。归零后,VDD 会在主机上占用 100 GB 的空间。并qemu-img -c ...
创建了 91 GB,这完全不是我的预期。
在modernie 网站上,我们可以下载小于10 GB 的W7 VM,这怎么可能?有没有办法“真正”压缩 VM 映像?
感谢@dyasny,我用virt-sparsity
. 我清理了 W7 VM 磁盘,禁用休眠,所以 VDD 只消耗 20 GB。再次降级磁盘,然后再次运行sdelete -z
。virt-sparsity
使用该标志运行--compress
会提供 80 GB 的虚拟驱动器。远非我所希望的。
EDIT-2016-02-16:“刷新”这个问题,因为这里讨论的缩小 VM 的方法非常有效,但有一个主要缺点:它会删除所有 VM 快照。如果有人知道如何在保留快照的同时缩小 VM,请随时分享!
要缩小 Windows 来宾操作系统,您必须缩小来宾内部的分区、关闭 VM、创建所需大小的新磁盘、将数据从旧磁盘复制到新的更小的磁盘、交换磁盘名称并重新启动虚拟机。
这很简单,但如果操作不当可能会导致数据丢失和头发丢失。
以下是带有 100 GB 的 Windows Server 2012 来宾的 KVM 的步骤,我们希望使用 QCOW2 格式缩小到 35 GB。
重要提示:此方法不涉及修改虚拟机定义。相反,它只需要磁盘映像操作。
客人的假设:
主机假设:
第 1 步:准备 Windows 来宾,收缩主 C: 分区
在这一步中,我们将直接从 Windows 中减少我们的 Windows 分区。此步骤结束时生成的磁盘映像将是引导分区、C: 驱动器(减少)和我们将删除的剩余未使用空间(通过不将其复制到新磁盘)的总和。
一旦出现“收缩 C:”对话框窗口,在“要收缩的空间量”中输入空间量,使“收缩后的总大小(以 MB 为单位)”值接近所需的 35 GB。然后点击“收缩”。
注意:如果新空间太小,您可能会收到错误消息,在这种情况下,您应该将“要收缩的空间量”逐渐减少 1GB,直到错误消失并发生收缩。在实践中,我们希望保留 10 GB 的可用空间。
假设您能够将 C: 分区缩小到 34 GB。
完成后,通过打开命令提示符并键入以下内容来关闭 VM:
shutdown /s /t 0
第 2 步:缩小 VM 主机上的磁盘
该过程并不是真正的收缩,而是我们将创建一个新磁盘(最终大小),我们将从原始磁盘复制两个分区,并跳过未使用的空间。
目标是创建一个总大小 = 引导分区 + C: 分区的磁盘。我们还会得到一些微小的剩余空间(除非你的数学是完美的),不用担心,因为我们将在最后一步处理。
sudo su
cd /var/lib/libvirt/images
ls -l
我们做一个备份:
(去喝杯咖啡,因为这需要一段时间才能获得大磁盘)
安装您可能缺少的 guestfs 软件包:
好的,让我们通过浏览 windows 映像来仔细检查我们的 windows 磁盘
virt-filesystems
:输出这个:
请注意,我们有
/dev/sda1
350 MB 的 Windows 启动分区,/dev/sda2
这是我们现在 34 GB 的 C: 分区,总磁盘映像/dev/sda/
为 100 G,留给我们一堆空间需要修剪。所以这是重要的一步:算一算:34 G + 350M 适合 35 G,因此我们将创建一个 35 GB 的图像。我们最终会不可避免地得到一些剩余空间——除非你的数学是完美的——但别担心,我们将在下面处理它。
newdisk.qcow2
让我们创建一个总大小为 35 GB的新虚拟 QCOW2 磁盘:输出:
让我们通过将旧磁盘复制到新分配的磁盘来调整磁盘大小。这是绝对令人敬畏的一点。大多数其他指南显示了一些非常复杂的东西。这可以通过这个命令简单地完成,之后你应该去喝更多的咖啡——这可能需要一段时间:
输出这个:
请注意该工具发现了多余的空间...回忆一下关于数学的评论...所以您可以取消它并重新创建磁盘,或者像我们在此处所做的那样继续前进并像
sda2
在步骤 3 中所做的那样扩展分区。一旦完成。检查生成的图像:
输出这个:
注意
/dev/sda3
剩余空间的类型是 linux 类型。剩余的空间是可以的,除非你的数学完全正确。我们将在下面进一步处理来自 Windows 来宾的这个额外分区。现在,忽略它。交换磁盘映像:
启动你的虚拟机。
第 3 步:在 Window Guest 上完成磁盘操作
在这一步中,我们确认 Windows 启动正常,我们将把 C 分区扩展到额外的空间。
登录到 Windows 来宾
打开“计算机管理”实用程序,使用开始菜单搜索功能找到它。
在左侧,单击“存储->磁盘管理”
您应该看到 3 个分区:引导、C: 和一个 439 MB 的小分区(最右边)。显示 3 个分区的计算机管理屏幕截图
通过右键单击->删除卷删除linux分区。(对任何提示单击是)
右键单击 C: 分区并单击“扩展”,然后在对话框中单击“下一步”和“确定”。它应该只提供最后一个分区的扩展量。完成后,您已经调整了 C: 的大小,并且只剩下两个分区。
而已。您的 Windows 来宾现在仅使用 35 GB 左右。请记住,由于所有开销等原因,实际磁盘映像可能更大(可能接近 38 GB)。
检查一切是否正常并删除您的映像备份或将它们离线移动到存储中。
我终于设法真正缩小了 VM 空间。一开始,W7 VM 占用了 107 GB 的主机存储空间。虚拟 HDD 大小为 100 GB,目前,VM 仅占用 18 GB 的虚拟存储空间。
这是我所做的:
sdelete -c c:
sdelete -z c:
qemu-img convert -c -f qcow2 w7-64.qcow2 -O qcow2 w7-64-compressed.qcow2
这样,qcow2 文件就从 107 GB 缩小到了...7 GB!
运行时
qemu-img -c
,会压缩图像,虽然可以减少一些空间,但确实会损害性能。如果要对磁盘上的零进行重复数据删除,则需要运行qemu-img convert
,基本上就好像您正在尝试将图像从一种格式转换为另一种格式(即使 src 和 dst 格式相同)。这个过程将写入一个新的转换后的图像,没有零,有效地删除驱动器上的零空间。
当然,另一种选择是简单地使用
virt-sparsify
。适用于 KVM 上的 Windows VM 的方法如下。
在 Windows 客户机上:
sdelete -z c:
(sdelete -z
适用于虚拟机。它不会增加磁盘上的实际 QCOW2 映像大小并将空白空间清零。sdelete -c
另一方面,它不是必需的,它会增加磁盘上的 QCOW2 映像大小)在 Linux 主机上:
qemu-img convert -O qcow2 -c inputVM.img outputVM.img
(请注意,这不会保留快照并将采用当前状态)在 Xenial 和 Bionic 中,
virt-sparsify
软件包libguestfs-tools中的实用程序应该可以工作。注意:sdelete
事先在来宾内部运行工具(但不会受到伤害)--in-place
标志来释放空间而不复制文件(如果磁盘映像已经大于驱动器上的剩余可用空间,则很有用!)您只需要“打孔”或“稀疏”空白空间。为此,您需要仅包含 0 和孔的空间。文件系统的“空白空间”只是未分配,但可能包含旧的垃圾数据,而不是 0。所以第一步是将它归零。有一些工具可以做到这一点,但这里有一个简单的最小方法......
在每个文件系统上创建一个只有 0 的文件,然后将其删除。在这里,我假设 /tmp 是您可写的,并且位于 rootfs 上。(在 Windows 中,您可以在 cygwin 中执行相同的命令,或使用其他工具。)
现在空白空间只是0。而且,这个磁盘现在是磁盘上的完整大小......与你最终想要的相反。因此,如果您之前空间不足,这将不起作用。
停止虚拟机。
打孔。有几种方法可以做到这一点……这是一种快速的方法,使用 python 脚本。首先停止 vm,然后在磁盘文件上运行脚本。如果它是 qcow2 文件或其他格式,它应该工作相同,但可能有一些我忘记了,或者只是一个更简单的方法。
并且要注意没有分配一个洞,所以文件不是都在一个地方;文件系统可能会变得碎片化,从而影响性能。这在典型的 Linux/UNIX 文件系统上不应该以任何方式引起注意,除非您在写入文件时空间非常低,但请注意这种可能性。建议至少保留 10% 的可用空间以避免碎片。
此外,还有一些工具也可以做其他事情......比如仅将非零空白空间归零(因此它们在打孔之前不会增长),也将交换归零,在线执行(可能需要虚拟机管理程序支持),等等。我尝试了这些方法,发现它们都非常不可靠,有时几乎没有像手动归零那样缩小 5%,所以我什至不会费心列出这些工具;其他人可以列出他们的最爱。
您可能想要禁用系统还原或删除 VM 磁盘中的任何现有卷影副本。仅此一项就可能占用大量空间,并且对文件系统来说似乎是隐藏的。然后在 vm 重新启动后运行 sdelete 并将可用空间清零。