December 5, 2011

Embiggen Your KVM Virtual Machines

When you provision virtual machines, you try to ensure that they have the storage that they need. But as we all know, storage needs tend to change over time. If you have KVM machines that need more space, we can up their storage with tools you already have handy.

In Managing Live and Offline Migrations with Linux's KVM we learned how to migrate virtual machines, and how to manage disk storage. Today we'll learn how resize VMs and add storage space.

When your virtual machine needs more storage space there are multiple ways to add it. The most flexible method is to put your virtual machine images into LVM (Linux volume manager) volumes. This isn't an LVM tutorial, so please refer to Weekend Project: Migrate from Direct Partitions to LVM Volumes.

Two methods we're going to use today are adding file-based storage as a separate partition, and increasing the size of the virtual machine's storage volume.

Adding File-Based Storage

If you have enough disk space on your KVM server you can create an empty container file, connect it to your VM, and then format it from inside the VM with the usual filesystem utilities such as mke2fs, fdisk, Gparted, or Parted. The default location for VM images is /var/lib/libvirt/images/, so let's go there and create a gigabyte storage image. This example is for a Jeoss Linux VM, so of course you must substitute your own output file name, which is whatever you want it to be:

# cd /var/lib/libvirt/images/
# dd if=/dev/zero of=jeoss-storage.img bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 10.7728 s, 99.7 MB/s

Now dump your VM's configuration into an XML file with the virsh command, using your own guest and configuration file names:

# virsh dumpxml jeoss > jeoss-config.xml

The virsh utility doesn't want the whole VM filename, which in this example is jeoss.img, but the VM domain, which is plain old jeoss. Open the new XML file and look for the "disk" entry for your hard drive, which will look something like this:

<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/jeoss.img'/>
<target dev='hda' bus='ide'/>
<alias name='ide0-0-0'/>
<address type='drive' controller='0' bus='0' unit='0'/>

Create a new stanza in the file with a copy of this, and modify it for your new storage image:

<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/jeoss-storage.img'/>
<target dev='hda' bus='ide'/>
<alias name='ide0-0-1'/>
<address type='drive' controller='0' bus='0' unit='1'/>

There are three changes: the source file, the alias name, and the address. Check the rest of the file for any duplicate entries with the same alias and address, and if there are any duplicates then make the unit value (for the new storage image) one bigger. Save and close the file, and shutdown the VM. Then restart it using the new configuration file: Booting a virtual machine to System Rescue CD, and resizing the filesystem with Gparted.










# virsh create jeoss-storage.xml

It should boot normally and attach the new storage image. In my Jeoss VM fdisk shows it as a new partition:

carla@jeoss:~$ sudo fdisk -l
Disk /dev/sdb: 1024 MB, 1073741824 bytes
Disk /dev/sdb doesn't contain a valid partition table.

Perfect! Now I can partition and format it using ordinary Linux partitioning and formatting tools. The default configuration file is in /etc/libvirt/qemu, and it should be updated automatically by virsh with the new storage volume, so you don't need to call your generated XML configuration file the next time you start your VM.

Resize Virtual Machines

If your VMs are in either raw or qcow2 format, you can resize them. I have Fedora 16 Linux in a 8GB storage volume, and I want to increase it to 9GB. We'll use the qemu-img disk image utility because it is part of KVM, so we won't have to hunt it down and install it separately. It is a three-step process: first make a backup copy of the virtual machine image, resize the volume, then resize the virtual machine's filesystem to fill the volume.

First stop your virtual machine, and then make a backup copy of your VM image. The default location is /var/lib/libvirt/images/:

# cd /var/lib/libvirt/images/
# cp fedora16.img fedora16-bak.img

Then run qemu-img. In this example I increase the volume size by one gigabyte:

# qemu-img resize fedora16.img +1GB
Image resized.

Now the filesystem must be resized to make use of the additional space. The tricky bit is you can't resize a live filesystem (unless you're using LVM), but must unmount it first. So you need a bootable live Linux CD/DVD that includes filesystem utilities. I use Gparted from a SystemRescue CD. The live media must be booted into the virtual machine volume, and the qemu command will do this for us. With the virtual machine still stopped, insert your live CD/DVD and run this command:

# qemu -hda fedora16.img -cdrom /dev/cdrom -boot d

The -hda /vmimages/fedora16.img argument tells the location of the virtual machine image your live CD is booting into, so you must substitute the name of your own image. -cdrom gives the location of your CD drive, which in this example is an ordinary IDE CD/DVD drive, and boot -d means boot from the CD first, so it boots the CD instead of the virtual machine image. It's just like booting a physical PC with a live CD. Once the CD has booted you can fire up your favorite filesystem resizer and expand the VM to the new volume size. Figure 1 shows how it looks in System Rescue with Gparted.

After verifying that your resized virtual machine works, you can delete the backup image and enjoy your embiggened VM.

To learn more read man qemu and man virsh, because they are full of amazing and little-known features, and man dd to learn what the options mean.