I've spent a lot of time to get KVM on Ubuntu up and running. Now it's done and I want to share it with you.
Installing the host system
Boot into rescue system (linux 64-bit)
# installimage
Select the following image.
ubuntu-9.10-64-bit
Now modify your installimage.conf to use LVM instead of normal partitioning.
DRIVE1 /dev/sda
DRIVE2 /dev/sdb
SWRAID 1
SWRAIDLEVEL 1
BOOTLOADER grub
HOSTNAME Ubuntu-910-karmic-64-minimal
PART /boot ext2 256M
PART lvm vg0 all
LV vg0 root / ext3 10G
LV vg0 swap swap swap 4G
IMAGE /root/.oldroot/nfs/install/../images/Ubuntu-910-karmic-64-minimal.tar.gz
Reboot your server.
# reboot
Preparing the host system to work with KVM
Login to your new system and prepare it for the KVM action. We are using libvirt as wrapper around QEMU. This simplifies a lot.
# apt-get update
# apt-get -y upgrade
# apt-get -y install libvirt-bin
Networking
First we need to configure the network on the host system. I’ve added the pointopoint command and removed the routing at the end of the file.
/etc/network/interfaces
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address <host-ip>
netmask 255.255.255.255
gateway <gateway-ip>
pointopoint <gateway-ip>
Enably routing by uncommenting the follwing in /etc/sysctl.conf
net.ipv4.ip_forward=1
and reload the settings.
# sysctl -p
Load the tun module into kernel
# modprobe tun
KVM
Add the following to /root/vg0.xml. This defines LVM as primary storage source for our virtual machines.
<pool type="logical">
<name>vg0</name>
<target>
<path>/dev/vg0</path>
</target>
</pool>
Hook it into the system using libvirt.
# virsh pool-define vg0.xml
# virsh pool-autostart vg0
# virsh pool-start vg0
Creating a new guest
Storage
Create a new logical volume for our guest. You can later expand the volume. Even shrinking is possible but not recommended.
# lvcreate -n vm1 -L 100G vg0
VM definition
Now we have to define the machine itself. Put the following in /etc/libvirt/qemu/vmt.xml
This is the definition file for a KVM guest in libvirt format.
<domain type="kvm">
<name>vm1</name>
<uuid>593654cd-1d7f-6584-76ec-75496968e0b7</uuid>
<memory>1048576</memory>
<currentMemory>1048576</currentMemory>
<vcpu>2</vcpu>
<os>
<type arch="x86_64" machine="pc-0.11">hvm</type>
<boot dev="cdrom"/>
</os>
<features>
<acpi/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/kvm</emulator>
<disk type="file" device="disk">
<source file="/dev/vg0/vm1"/>
<target dev="hda" bus="ide"/>
</disk>
<disk type="file" device="cdrom">
<source file="/root/install-amd64-minimal-20100408.iso"/>
<target dev="hdc"/>
<readonly/>
</disk>
<interface type="ethernet">
<mac address="52:18:00:a7:cf:47"/>
<script path="/srv/vms/vm1-ifup"/>
<model type="virtio"/>
</interface>
<console type="pty" tty="/dev/pts/2">
<source path="/dev/pts/2"/>
<target port="0"/>
</console>
<graphics type="vnc" port="-1" autoport="yes" passwd="secret" keymap="de" listen="0.0.0.0"/>
<video>
<model type="cirrus" vram="9216" heads="1"/>
</video>
</devices>
</domain>
Hook it into the libvirt domain registry.
# virsh define /etc/libvirt/qemu/vm1.xml
Networking
Networking is based on simple routing. Therefor we’ll create a simple script that is called once the VM has been started. This script adds the necessary routing stuff for you.
# mkdir -p /srv/vms
Put the following in /srv/vms/vm1-ifup
#!/bin/sh
main_ip="<host-ip>"
main_dev="eth0"
vnet_ip="<guest-ip>"
vnet_dev=$1
echo 1 >/proc/sys/net/ipv4/ip_forward
echo 1 >/proc/sys/net/ipv4/conf/${main_dev}/proxy_arp
echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 1 >/proc/sys/net/ipv4/conf/all/rp_filter
echo 1 >/proc/sys/net/ipv4/conf/${vnet_dev}/proxy_arp
ifconfig ${vnet_dev} ${main_ip} netmask 255.255.255.255 up
ip route add ${vnet_ip} dev ${vnet_dev} src ${main_ip}
# chmod +x /srv/vms/vm1-ifup
Guest installation
As I’m installing gentoo as the guest OS, we’ll have to download the install CD.
# cd / && wget http://gentoo.osuosl.org/releases/amd64/current-iso/install-amd64-minimal-20100408.iso
App Armor has a strange bug in the current version. It doesn’t work well together with QEMU and prevents it from starting properly. Thats why I’m going to deactivate it.
# /etc/init.d/apparmor stop
# /etc/init.d/libvirt-bin restart
Finializing
After the guest is installed (Gentoo in my case). We need to define the network settings.
My /etc/conf.d/net is:
config_eth0=(
"<guest-ip> netmask 255.255.255.255 peer <host-ip>"
)
routes_eth0=(
"default via <host-ip>"
)
And here’s the corresponding /etc/resolv.conf with the Google DNS.
nameserver 8.8.8.8