I've spent many hours searching the web about how to shrink KVM virtual disk images, especially for Windows guests, with no luck.
All I've found is to zeroize the VM free space, defrag the virtual disk (from Windows), and then run qemu-img convert -c ...
(-c
flag to compress).
I've a Windows 7 VM, with a 100 GB virtual drive size. Initially, this VDD spent 40 GB on the host storage. Once it's zeroized, the VDD eats for real 100 GB on the host. And qemu-img -c ...
creates a 91 GB, which is not at all what I expected.
On the modernie web site, we can download W7 VMs which are less than 10 GB, how is this possible? Is there a way to "really" compress the VM images?
Thanks to @dyasny, I made a small test with virt-sparsity
. I cleaned up the W7 VM disk, disable hibernation, so the VDD only consumes 20 GB. Degraded the disk again, and ran again sdelete -z
. Running virt-sparsity
with the --compress
flag gives a 80 GB virtual drive. Far from what I would have hoped.
EDIT-2016-02-16:
"Refreshing" this question because the method to shrink a VM discussed here is very efficient but has a major drawback: it deletes all VM snapshots. If someone knows how to shrink a VM while preserving snapshots, feel free to share!
Best Answer
To shrink a Windows Guest OS, you have to shrink the partition inside the guest, shutdown the VM, create a new smaller disk of the desired size, copy the data from the old disk to the new smaller disk, swap the disk names and reboot the VM.
It’s straightforward, yet if done improperly could lead to loss of data – and hair.
Here are the steps for KVM with a Windows Server 2012 guest of 100 GB that we want to shrink to 35 GB, using the QCOW2 format.
IMPORTANT: This method involves no modification of the virtual machine definition. Instead, it requires only disk image manipulations.
Assumptions for the guest:
Assumptions for the Host:
STEP 1: Preparation of the Windows Guest, shrinkage of the main C: partition
In this step, we'll just reduce our windows partitions directly from Windows. The resulting disk image at the end of this step will be the sum of the boot partition, the C: drive (reduced) and a leftover unused space that we will delete (by not copying it over to a new disk).
Once the “Shrink C:” dialog window appears, enter the amount of space in “Amount of space to shrink” that makes the “Total size after shrink in MB” value approach the desired 35 GB. Then click “Shrink”.
NOTE: You may get an error message if the new space is too small, in this case you should reduce the “Amount of space to shrink” by 1GB incrementally until the error disappears and the shrinking takes place. In practice, we like to keep 10 GB of free space.
Let’s assume you were able to shrink the C: partition to 34 GB.
Once done, shut down the VM by opening a command prompt and typing:
shutdown /s /t 0
STEP 2: Shrinkage of the disk on the VM host
The procedure is not really a shrinkage, but instead we're going to create a new disk (of the final size) in which we will copy the two partitions from the original disk, and skip carrying over the unused space.
The goal is to create a disk whose total size = boot partition + C: partition. We'll also end up with some tiny leftover space (unless your math was perfect) not to worry about because we'll deal with in the last step.
sudo su
cd /var/lib/libvirt/images
ls -l
we make a backup:
(go have coffee because this will take a while for a large disk)
install guestfs packages you might be missing:
Alright, let’s double check our windows disk by exploring the windows image with
virt-filesystems
:which outputs this:
Notice that we have
/dev/sda1
which is our windows boot partition of 350 MB,/dev/sda2
which is our C: partition of now 34 GB and that the total disk image/dev/sda/
is of 100 G leaving us with a bunch of space to trim.So here is the important step: do your math: 34 G + 350M fits in 35 G, therefore we are going to create an image of 35 GB. We’ll inevitably end up with some leftover space – unless your math is perfect – but don’t worry about it, we’ll deal with it below.
let’s create the new virtual QCOW2 disk that we are calling
newdisk.qcow2
of total size 35 GB:which outputs:
Let’s resize the disk by copying the old disk into the newly allocated one. This is the bit that is absolutely awesome. Most other guides show some awfully complicated stuff. This is simply done by this command after which you should go get more coffee – it’s likely going to take a a while:
which outputs this:
Notice the tool found the surplus of space... recall the comments about Math... So you can cancel that and recreate the disk or just move on as we do here and expand the
sda2
partition as is done on STEP 3.Once done. Inspect the resulting image:
which outputs this:
Notice how the type of the
/dev/sda3
is of type linux for the leftover space. Leftover space is OK, unless you did your math exactly right. We’ll deal with this extra partition from the windows guest further below. Right now, just ignore it.Swap the disk images:
Start your VM.
STEP 3: Finalization of the disk operation on the Window Guest
In this step, we're confirming windows boots fine, and we're going to expand our C partition into the extra bit of space.
Login to the windows guest
Open the “Computer Management” utility, by using the start menu search function to locate it.
On the left side, click on “Storage->Disk Management”
You should see 3 partitions: boot, C: and a small 439 MB partition (to the far right). Screenshot of Computer Management showing the 3 partitions
Delete the linux partition by right click->delete volume. (click yes to any prompts)
Right click on the C: partition and click on “Extend”, then Next and OK on the dialogs. It should only offer to extend by the amount of the last partition. Once done you have resized C: and be left with only two partitions.
That’s it. Your windows guest is now using only 35 GB or so. Remember the actual disk image may be larger (it could be closer to 38 GB) due to all the overhead, etc.
Check that everything works fine and delete your image backups or move them offline to storage.