Provisioning virtual machines for KVM

I describe here an automated installation procedure to easily create Ubuntu virtual servers on the KVM hypervisor, using vmbuilder.

All the attributes of the virtual server will be defined in configuration files, so we will be able to reproduce and tune our server configurations later. Using this technique, complete server stacks can be provisioned. In this example we will create a virtual server for Drupal development. We apply some performance tuning for the install process, and the automated install of a new Drupal developer server can happen in 10 Minutes.

You will need an Ubuntu box with KVM and other tools for this exercise. How to get the proper environment with KVM working on Ubuntu 9.10, check this Howto.

  1. vmbuilder
  2. The magic happens with vmbuilder, a tool introduced in Ubuntu 8.10, and targeted to build Ubuntu virtual machines for multiple hypervisors. Currently it supports Xen, KVM and VMware.

    First, to learn the parameters for Ubuntu and KVM, type:
    sudo vmbuilder kvm ubuntu --help

    Defining a virtual machine with Ubuntu's vmbuilder is quite simple, as vmbuilder uses configuration files to create virtual machines. So at the end, we'll create a Drupal LAMP server with Ubuntu for KVM with this simple command:
    sudo vmbuilder kvm ubuntu -c drupal-vm.cfg -d DESTINATION-PATH
    where DESTINATION_PATH is where the image files of the new virtual machines should be located. You will need some GBs free there.

  3. Configuration file
  4. The minimal content of drupal-vm.cfg file is like here:

    [DEFAULT]
    arch = i386
    ip = 192.168.2.10
    mask = 255.255.255.0
    net = 192.168.2.0
    bcast = 192.168.2.255
    domain = local
    d = /var/vm-pool/d6
    part = ./drupal-vm.partitions
    firstboot = ./drupal-vm-boot.sh
    firstlogin = ./drupal-vm-login.sh

    [ubuntu]
    suite = karmic
    flavour = virtual
    components = main,universe,restricted,multiverse
    addpkg = nano, wget, acpid
    hostname = drupal6
    mem = 1024
    cpus = 1

    [kvm]
    libvirt = qemu:///system
    bridge = br0

    This configuration defines a 32 bit Karmic Koala virtual server (arch, suite, flavour), with 1024 MB RAM and 1 CPU (cpus, mem), the partitions defined in a plan text file (part). It will be integrated to libvirt, and use bridged networking (libvirt, bridge). For the IP setting, use your own network parameters (ip, mask, net, bcast). Scripts running during first boot as root (firstboot) and during first login as user (firslogin) can configure the server as wanted. The first user is called ubuntu and its password is also ubuntu.

  5. Partitions for the VM
  6. The partitions are defined in drupal-vm.partitions file, as follows:

    root 2000
    swap 1000
    /home 1000
    ---
    /var 4000

    It defines two disk, both with 4 GB. The first one is for /root, swap and a separate partition for /home. The second disk is for the /var partiton with 4 GB. Play with the numbers and adjust them to your needs. The disk spaces are allocated by demand, so the initial size will be around 300 MBs!

  7. The first-boot script
  8. The first-boot script (./drupal-vm-boot.sh) will be copied to /root of the virtual machine, and will be executed the first time the VM boots, and must not be interactive!

    apt-get update
    apt-get upgrade
    apt-get install -qqy --force-yes openssh-server
    apt-get autoclean
    apt-get autoremove

  9. The first-login script
  10. The first-login script (./drupal-vm-login.sh) was also copied to /root/firstlogin.sh on the virtual machine, and should be executed the first time the first user logs in. It can be interactive!


    # Install Drupal 6 and the necessary LAMP stack
    sudo apt-get install drupal6
    # PHP memory increase to 64M
    sed -i 's/memory_limit = 16M/memory_limit = 64M/' /etc/php5/apache2/php.ini
    # correct some errors in drupal6 package
    # 1. enable mod_rewrite in Apache2
    sudo a2enmod rewrite
    sudo /etc/init.d/apache2 restart
    # 2. set the correct base URL in htaccess
    sudo sed -i 's/# RewriteBase \/drupal/ RewriteBase \/drupal6/' /etc/drupal/6/htaccess

    Due to a recent bug in vmbuilder, this script is not ran automatically, so we have to start manually:
    sudo /root/firstlogin.sh

  11. How to use it
  12. Putting all together:

    • Make a directory for scripts, and prepare four files: one config file, one for the partions, one for booting and the last one for first login
    • Adjust the parameters and settings of the files, as wanted
    • Call sudo vmbuilder kvm ubuntu -c drupal-vm.cfg -d DESTINATION-PATH and wait some minutes to finish
    • Start the virtual machine via Virtual Manager or virsh
    • login to VM using the first user paramaters
    • run sudo /root/firstlogin.sh to finish the install
  13. Optional: performance
  14. There are many hints how to accelerate the install process. Here you have some, and if you know others, please make a comment.

    • Use temporary file system: the tmpfs option
    • simply add this line
      tmpfs = - to the vm.cfg file. It creates the image in RAM disk during install.

    • Ubuntu mirrors
    • Define a local Ubuntu mirror (a local apt-cache), instead of the default. Specify the host's IP, as this mirror setting should be valid for the VM, as it's Apt's sources.list will use it. On the host you have to install a local cache, see AptProxy, as one option.
      mirror = http://192.168.2.31:9999/ubuntu
      There is a possibility to use mirror just for the install process, in that case the source.list won't be changed.
      install_mirror = http://192.168.2.31:9999/ubuntu
      See help in vmbuilder for more details.

  15. Other settings
    • Use 64 bit architecture
    • simply add this line
      arch = amd64 to the vm.cfg file. It allows to allocate more memory to the VMs, and you can use 64 bit VMs, as well.

    • Define first user
    • simply add this line
      user = doka
      name = Doka
      pass = wepoca
      to vm.cfg

    • define source image for installation
    • iso = /home/storage/iso/ubuntu-8.10-server-i386.iso
      Also requires suite and kernel parameter to match

    • Set the locale
    • Set the locale to your language, i.e.:
      lang = hu_HU.UTF-8

    • ...