我花了很多时间在网上搜索如何缩小 KVM 虚拟磁盘映像,特别是针对 Windows 客户机,但没有任何收获。
我发现只需将虚拟机可用空间归零,对虚拟磁盘进行碎片整理(从 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:“刷新”这个问题,因为这里讨论的缩小虚拟机的方法非常有效,但有一个主要缺点:它会删除所有虚拟机快照。如果有人知道如何在保留快照的同时缩小虚拟机,请随时分享!
答案1
要缩小 Windows 客户操作系统,您必须缩小客户机内的分区,关闭虚拟机,创建所需大小的新较小磁盘,将数据从旧磁盘复制到新的较小磁盘,交换磁盘名称并重新启动虚拟机。
这很简单,但如果操作不当可能会导致数据丢失和头发丢失。
下面是针对 Windows Server 2012 客户机的 KVM 步骤,其中,我们想要使用 QCOW2 格式将 100 GB 的 Windows Server 2012 客户机缩小到 35 GB。
重要的:此方法涉及无需修改虚拟机定义。相反,它只需要磁盘映像操作。
对客人的假设:
- Guest 是 Windows Server 2012
- 100 GB 的 QCOW2 格式磁盘映像
- 两个分区:
- 350 MB 的启动空间
- C 盘 99.6 GB,已用空间 20 GB
- 我们希望将 C: 从 99.6 GB 缩小到 34 GB
对主持人的假设:
- Ubuntu 16 LTS 服务器
- KVM(libvirt)
- 250 GB 驱动器
- 虚拟映像位于 /var/lib/libvirt/images
步骤 1:准备 Windows 客户机,缩小主 C:分区
在此步骤中,我们将直接从 Windows 中缩小 Windows 分区。此步骤结束时生成的磁盘映像将是启动分区、C: 驱动器(缩小)和我们将删除的剩余未使用空间(通过不将其复制到新磁盘)的总和。
- 登录 Windows 客户机
- 打开“计算机管理”实用程序,通过使用开始菜单的搜索功能来找到它。
- 在左侧点击“存储->磁盘管理”存储磁盘管理截图
- 在新屏幕上,右键单击 C: 分区,单击“压缩卷…”,这可能需要一点时间才会出现对话框。请耐心等待。
出现“压缩 C:”对话框后,在“要压缩的空间量”中输入空间量,使“压缩后的总大小(以 MB 为单位)”值接近所需的 35 GB。然后单击“压缩”。
笔记:如果新空间太小,您可能会收到错误消息,在这种情况下,您应该逐步减少“要缩小的空间量”1GB,直到错误消失并且缩小开始。实际上,我们希望保留 10 GB 的可用空间。
我们假设您能够将 C: 分区缩小到 34 GB。
完成后,打开命令提示符并输入以下内容关闭虚拟机:
shutdown /s /t 0
- 您的 Windows 客户机已准备就绪。
步骤 2:缩小虚拟机主机上的磁盘空间
该过程实际上并不是缩小,而是我们将创建一个新磁盘(最终大小),我们将从原始磁盘复制两个分区,并跳过转移未使用的空间。
目标是创建一个总大小 = 启动分区 + C: 分区的磁盘。我们最终还会剩下一些微小的空间(除非您的数学计算非常完美),不用担心,因为我们会在最后一步处理。
- 登录linux主机
- 切换到超级用户:
sudo su
- 前往存储虚拟图像的位置:
cd /var/lib/libvirt/images
- 列出文件:
ls -l
- 找到您的客户机映像(其他地方有很多关于此内容的教程)。假设我们的 Windows 客户机映像名为“windows.qcow2”
我们进行备份:
mkdir backup cp windows.qcow2 backup/windows.qcow2.bak
(去喝咖啡,因为处理大磁盘需要一段时间)
安装您可能缺少的 guestfs 软件包:
apt-get install libguestfs-tools
好吧,让我们通过以下方法探索 Windows 映像来仔细检查我们的 Windows 磁盘
virt-filesystems
:virt-filesystems --long --parts --blkdevs -h -a windows.qcow2
输出如下内容:
Name Type MBR Size Parent /dev/sda1 partition 07 350M /dev/sda /dev/sda2 partition 07 34G /dev/sda /dev/sda device - 100G -
请注意,我们有
/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 磁盘:qemu-img create -f qcow2 -o preallocation=metadata newdisk.qcow2 35G
输出:
Formatting 'newdisk.qcow2', fmt=qcow2 size=37580963840 encryption=off cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16`
让我们通过将旧磁盘复制到新分配的磁盘来调整磁盘大小。这是绝对棒极了的部分。大多数其他指南都展示了一些非常复杂的东西。这可以通过以下命令轻松完成,之后您应该去喝杯咖啡——这可能需要一段时间:
virt-resize windows.qcow2 newdisk.qcow2`
输出如下内容:
[ 0.0] Examining windows.qcow2 100% ?¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦? --:-- ********** Summary of changes: /dev/sda1: This partition will be left alone. /dev/sda2: This partition will be left alone. There is a surplus of 439.8M. An extra partition will be created for the surplus. ********** [ 8.8] Setting up initial partition table on newdisk.qcow2 [ 9.9] Copying /dev/sda1 100% ?¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦? 00:00 [ 15.1] Copying /dev/sda2 100% ?¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦? 00:00 Resize operation completed with no errors. Before deleting the old disk, carefully check that the resized disk boots and works correctly.
注意,该工具发现了剩余的空间...回想一下关于数学的评论...所以你可以取消它并重新创建磁盘,或者像我们在这里所做的那样继续前进,并
sda2
按照步骤 3 中所做的那样扩展分区。完成后,检查生成的图像:
virt-filesystems --long --parts --blkdevs -h -a newdisk.qcow2
输出如下内容:
Name Type MBR Size Parent /dev/sda1 partition 07 350M /dev/sda /dev/sda2 partition 07 34G /dev/sda /dev/sda3 partition 83 439.8M /dev/sda /dev/sda device - 35G -
请注意,剩余空间的类型
/dev/sda3
为 linux。剩余空间是可以的,除非您的计算完全正确。我们将在下面处理来自 Windows 客户机的这个额外分区。现在,请忽略它。交换磁盘映像:
mv windows.qcow2 backup/ mv newdisk.qcow2 windows.qcow2
启动您的虚拟机。
步骤 3:在 Windows 客户机上完成磁盘操作
在此步骤中,我们确认 Windows 启动正常,并且我们将把 C 分区扩展到额外的空间。
登录到 Windows 客户机
打开“计算机管理”实用程序,通过使用开始菜单的搜索功能来找到它。
在左侧点击“存储->磁盘管理”
您应该看到 3 个分区:启动分区、C: 分区和一个 439 MB 的小分区(最右边)。显示 3 个分区的计算机管理屏幕截图
通过右键单击->删除卷来删除 Linux 分区。(对于任何提示单击“是”)
右键单击 C: 分区,然后单击“扩展”,然后在对话框中单击下一步和确定。它应该只提供最后一个分区的扩展量。完成后,您已调整 C: 的大小,并且只剩下两个分区。
就是这样。您的 Windows 客户机现在仅使用 35 GB 左右。请记住,由于所有开销等原因,实际磁盘映像可能更大(可能更接近 38 GB)。
检查一切是否正常,然后删除您的图像备份或将其离线移至存储。
答案2
我终于设法真正缩小了虚拟机空间。一开始,W7 VM 在主机存储上占用了 107 GB。虚拟硬盘大小为 100 GB,目前,虚拟机仅占用了 18 GB 的虚拟存储。
这是我所做的:
- 清理虚拟驱动器(删除临时文件等)
- 使用“全面优化”的开源 UltraDefrag 软件进行碎片整理
- 跑步
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!
答案3
运行 时qemu-img -c
,会压缩图像,虽然可以减少一些空间,但实际上会损害性能。如果要对磁盘上的零进行重复数据删除,则需要运行qemu-img convert
,基本上就像尝试将图像从一种格式转换为另一种格式一样(即使 src 和 dst 格式相同)。
此过程将写入一个新的转换图像(不带零),从而有效地对驱动器上的零空间进行重复数据删除。
另一个选择是简单地使用virt-sparsify
课程。
答案4
virt-sparsify
在 Xenial 和 Bionic 中,包中的实用程序libguestfs 工具应该可以工作。请注意:
- 您不必事先
sdelete
在客户机内部运行类似工具(但这不会造成任何损害) - 您可以使用该
--in-place
标志来释放空间而不复制文件(如果磁盘映像已经大于驱动器上剩余的可用空间,则很有用!) - 该工具支持qcow2和raw格式的图片