VirtualBox/KVM: Reduce VM sizes

There are two utilities that can help discard unused blocks so that VMs can be shrunk.

zerofree finds unused blocks with non-zero content in ext2, ext3 and ext4 filesystems and fills them with zeros. The volume can’ be mounted which makes the process of running it a bit convoluted.

fstrim will discard unused blocks on a mounted filesystem. It is best and preferred when working with SSD drives and thinly provisioned storage. It will work with more filesystems, and it won’t hammer your SSD with unnecessary writes.

It is recommended to use fstrim and only use zerofree if unavoidable.

CentOS 7/8

fstrim

# fstrim -va

zerofree (ext2, ext3, ext4)

# yum install epel-release
# yum install zerofree

[Reboot]
Press e on GRUB menu
Go to line that starts with 'linux'
Add init=/bin/bash
Ctrl-X

[Find which disk to trim]
# df
# zerofree -v /dev/mapper/centos_centos7-root

[Shutdown machine]

zerofree (xfs)

# yum install epel-release
# yum install zerofree

[Reboot]
Press e on GRUB menu
Go to line that starts with 'linux'
Change ro to rw
Add init=/bin/bash
Ctrl-X

[Find the partition/filesystem to trim]
# df

[Fill the filesystem with zeros. This will work with any filesystem but it will write a lot of data on your drives.]
# dd if=/dev/zero of=/tmp/dd bs=$((1024*1024)); rm /tmp/dd
# sync
# exit

[Shutdown machine]

Debian 9/10

fstrim

[Debian 9]
# fstrim -va

[Debian 10]
# fstrim -vA

zerofree

# apt install zerofree

[Reboot]
Press e on GRUB menu
Go to line that starts with 'linux'
Add init=/bin/bash
Ctrl-X

[Find disk to trim]
# df
# zerofree -v /dev/sda1

[Shutdown machine]

Ubuntu 18.04/20.04

[Ubuntu 18.04]
# fstrim -va

[Ubuntu 20.04]
# fstrim -vA

Be aware that if you are using ZFS on Ubuntu (or any other distro) the above commands won’t work. In fact, it will generate a lot of extra writes on the filesystem.

Just ensure that ZFS is using compression, or avoid it in the guest system.

Reducing the image size

Virtualbox

[List all disks]
$ vboxmanage list hdds

[Just the paths]
$ vboxmanage list hdds | grep  'Location.*.vdi' | awk '{$1=""}1'

[Compress one image]
$ vboxmanage modifymedium disk --compact /home/user/Virtualbox/Kali-Linux-2021.1/Kali-Linux-2020.4-vbox-amd64-disk001.vdi

[List all images path]
$ vboxmanage list hdds | grep  'Location.*.vdi' | awk '{$1=""}1' | sed 's/^ /"/;s/$/"/'

I wish I knew the syntax to automatise compressing all the images with one line. I might revisit it in the future with a script.

KVM

# qemu-img convert -O qcow2 originalfile compressedfile

I have a script to do all of the files in one go:

#!/bin/sh

# All images
for file_name in `ls -1 *.cow2`

do
	echo
	echo ==================
	echo Image: $file_name
	echo -n Old `qemu-img info $file_name | grep 'disk\ size'` ; echo
	mv $file_name $file_name.tmp
	qemu-img convert -O qcow2 $file_name.tmp $file_name
	rm $file_name.tmp
	echo -n New `qemu-img info $file_name | grep 'disk\ size'` ; echo
	echo ==================
done