Monday, January 30, 2012

Setting up KVM on Ubuntu Server

This article describes setting up KVM on Ubuntu. I have both a Ubuntu server host and guest machine, version 11.10 (oneiric). Guest machine runs network services accessible from the outside.



File format

First thing you have to decide is the file format and size. KVM can use disk partition or a file. Disk partition is reported to be the fastest option, notably using format raw and cache none.

You can also make a file on the filesystem and install guest machine inside this file. The 2 most common formats are raw and qcow2.

File format - raw

The raw format is very simple, it is reported to be faster, you can mount it from the host using a loop, and it can dynamically grow on filesystems that support sparse files (eg. ext3 and ext4).

Sparse file is a file that does not allocate space on the disk as long as it is not really needed. You specify maximum size of the file and ls command reports this size. But the real space on the filesystem is allocated only for the data. You can see the real current size of the file using ls -ls. This way the filesystem space can be "overcommitted", ie. you can create files bigger than the filesystem. You have to take special care not to run out of real space in this situation.

Creating sparse files is a snap. Eg. a 30GB file is created in a second, while non-sparse file of this size can take about 30minutes to create. Some people say that non-sparse files are faster once they are created in KVM but I don't know and I think that there is technically no reason for this.

Several system utilities on Linux can take advantage of sparse files, eg. cp command has a --sparse parameter to create the target file as a sparse file. This way you can convert non-sparse files into sparse files and vice versa.

File format - qcow2

This is more advanced format. Use it, if you need the features it provides. This format allows the image to grow automatically on any filesystem, supports snapshots and overlays, encryption and compression. It can be mounted on the host using qemu-nbd utility that is using network communication internally.

In any case, you can create the file yourself and later use it when creating a virtual machine or let an installation utility create it for you.

Swap file

You may ask yourself whether to create a swap file for every guest. As I understand it, you need not. It is enough to create a swap file for the host as if it was running standalone, using all the available RAM. This is because it is the host who manages the RAM and guests are just processes using it. But consider if you really need a swap at all.

Network - setting up

If your guest will not be a server, there is nothing to do, it will work out of the box. The guest will be able to access the internet but it will be impossible to connect to the guest from the outside (and run network services). In order to enable this, you need to set up bridged networking.

Network - bridging

Bridging means that your ethernet interface will work as a network hub, ie. through this interface may be connected several others. The most important thing is that you can run either ethernet interface or bridge on the physical device, you cannot run both at the same time.

Let us have look at this picture. We have a host machine with 2 physical NICs eth0 and eth1. Eth0 is facing the outside internet, eth1 is facing the internal network. The Figure 1 shows the basic situation. Then we replace the eth1 with network bridge and we will set up the guests using this bridge - Figure 2. There may be several guests using the same bridge and every one can have several (virtual) network interfaces.

Figure 1 - Basic setup

----------------------------------
|                                |
-- eth0 1.2.3.4                  |
|                                |
|              192.168.0.1 eth1 --
|                                |
----------------------------------

Figure 2 - Bridging

-------------------------------------------------------------------
|                                                                 |
-- eth0 1.2.3.4                                                   |
|                                                                 |
|             192.168.0.1 br0-eth1 ---------------------------------
|                          |                                      |
|                          |-------------------------|            |
|                   guest0 |                  guest1 |            |
|                      --------------------          |            |
|                      | eth0 192.168.0.2 |  -------------------- |
|                      | eth1 192.168.0.3 |  | eth0 192.168.0.4 | |
|                      --------------------  -------------------- |
|                                                                 |
-------------------------------------------------------------------



The important thing is that inside the interfaces file, we assign an IP address to either eth1 or br0, never to both of them. Doing so will result is network breakdown.

Example interfaces file according to Figure 1 (simplified, ie. not all networking options shown):

auto eth0
iface eth0 inet static
   address 1.2.3.4
   netmask 255.0.0.0

auto eth1
   iface eth1 inet static
   address 192.168.0.1
   netmask 255.255.255.0


Example interfaces file according to Figure 2:

auto eth0
iface eth0 inet static
   address 1.2.3.4
   netmask 255.0.0.0

auto eth1
iface eth1 inet manual

auto br0
iface br0 inet static
   address 192.168.0.1
   netmask 255.255.255.0
   network 192.168.0.0
   broadcast 192.168.0.255
   gateway x.y.z.z
   bridge_ports eth1
   bridge_stp off
   bridge_fd 0
   bridge_maxwait 0

 

As you see, we set up eth1 as manual and all the actual settings we do for br0 which is linked to eth1. When we have changed interfaces like this and restarted the network, the network should work fine on host (both interfaces and IP addresses). Network interfaces (cards) for guests are setup inside QEMU configuration files. IP addresses are set using interfaces file of the guest.

Note: it is not possible to assign multiple IP addresses to an interface in a guest (using eth0:0, eth0:1, etc). But this is no problem, since we can configure several network cards for a guest and then assign an IP address to each card (ie. eth0, eth1, eth2, ...).

Utilities to install VMs

VM can be setup either manually or using an installation utility. Manual setup generally means to create a file for virtual host and to create a XML file describing the guest configuration. These configuration files are stored in the /etc/libvirt/qemu/ directory. It is generally better to use a utility.


Ubuntu provides 2 utilities - ubuntu-vm-builder (sometimes called python-vm-builder) and virt-install. Ubuntu-vm-builder is provided by Canonical and it has many many dependencies. The advantage of this utility probably is that you need not have an installation CD and the installation process of the guest is fully automated with no dialogs and settings. It is probably suitable for admins who have many servers.

Virt-install is provided by RedHat, it is very simple. It takes a bunch of command-line arguments, checks your system and creates the KVM/QEMU XML configuration file. It creates or mounts your filesystem file and mounts an ISO image of your installation CD. Then you proceed with installation as usual. I will describe this way in this article.

Virt-install

Let us consider these things: the name of the guest, filesystem file location, size and type, installation CD iso image location, how much memory we will give to the guest, how many virtual processors and to which physical processors we will bound it, network type and interface the guest will use.

My example setup is:

  •     the guest is named myguest
  •     installer creates a filesystem file /opt/myguest.img, format raw, size 30GB, sparse file
  •     installer mounts CD ISO image at /opt/ubuntu-server.iso
  •     guest will have a 1 virtual CPU which will be bound to physical CPU #2
  •     guest will have 4GB RAM
  •     maximum acceleration
  •     network will be bridged using br0 and virtio driver

virt-install \
   --name myguest \
   --ram 4096
   --disk path=/opt/myguest.img,bus=virtio,size=30,sparse=true \
   --cdrom /opt/ubuntu-server.iso \
   --accelerate \
   --network bridge=br0,model=virtio \
   --vcpus=1 \
   --cpuset=2 \
   --os-type linux \
   --os-variant ubuntuoneiric \
   --virt-type kvm \
   --graphics vnc \
   --noautoconsole


Notes: raw is the default file format; sparse defaults to true; cpuset is optional - if not set, all available processors are used (remember that guests are just processes to host); paravirtualization is faster than full virtualization and it is used by default on linux/linux; virtio drivers (for disk and network) are recommended, they provide very fast virtual devices.

Installer creates the image file, the configuration XML file and starts the virtual machine which boots off the CD. Normally the installer drops to the console afterwards. But because console does not work yet (and install is graphical anyway) it is usually better to disable this using --noautoconsole. If you forget it and the console starts, just escape from it using Ctrl+].

Now you need to connect to the guest to walk through the installation procedure. We have set up KVM to provide VNC server for the guest (option --graphics vnc). The best way is to have a graphical work-station which is able to connect to the host machine using SSH and to install virt-viewer on the station. This program uses SSH+VNC to connect to the host and through it to the guest. Use this command:

virt-viewer --connect qemu+ssh://user@1.2.3.4/system myguest

You will have to provide your SSH password twice (I don't know why) and afterwards you will have a graphical terminal to your guest and you can proceed with the installation. You will have one network card eth0 available by default.

Note that Ubuntu server CD provides a special option to install a minimal guest server. Highlight the first option on the installation menu, press F4 (Mode) and choose the "Minimal Guest OS" option.

Guest - network settings

To set the network, connect to the guest, set up /etc/network/interfaces and restart the guest network.

If you need more than one network card / IP address on the guest, you have to add more NICs to the guest in the KVM/QEMU setup file. Log into host, stop the guest and export the configuration file. The files are located inside /etc/libvirt/qemu/ but it is bad practice to edit them in place. Always export the file, edit it and import it back.

virsh dumpxml myguest > myguest.xml

Find the section <interface> and add more like this:

<interface type="bridge">
   <mac address="00:16:3e:3d:bf:12"/>
   <source bridge="br0"/>
   <model type="virtio"/>
</interface>


You need not specify nothing more, virsh will fill in other option during import. Random and safe MAC address can be generated eg. like this:

echo  'import virtinst.util ; print virtinst.util.randomMAC()' | python

Import the definition file back and then start your guest. Then you can edit interfaces file inside the guest to set up its IP addresses.

virsh define myguest.xml

Guest - shutdown

After the installation, shutdown does not work (destroy always works). You need to log into the guest and install acpid package.

Guest - console access

To make console access from virsh work (virsh# console myguest), you need to log into the guest and set up a terminal on /dev/ttyS0. Create the file /etc/init/ttyS0.conf which looks like this:

# ttyS0 - getty
#
# This service maintains a getty on ttyS0 from the point the system is
# started until it is shut down again.

start on stopped rc RUNLEVEL=[2345]
stop on runlevel [!2345]

respawn
exec /sbin/getty -L 115200 ttyS0 xterm

 

Then start the service:

sudo start ttyS0

If you have problems with terminal repaints, change the xterm option to another which suits your terminal better. More info here (https://help.ubuntu.com

/community/KVM/Access).

Guest autostart 

You will usually want to start your guest automatically as soon as the host is started. This can be done using virsh.

virsh# autostart myguest




Useful links:


No comments: