LVM-Based Virtualization with KVM and Jaunty
Posted by on April 27, 2009 in the Ubuntu category.
A month ago, I had three tower PCs running in my home office 24x7 - a desktop PC, a web server, and a home media server. Routinely high electric bills prompted me to make the decision to combine the two servers into one, but I wanted to do everything possible to isolate the media server activity from the web server. I decided on virtualization to accomplish this, allowing the web and media servers to run as separate virtual machines on the same hardware.
I liked the idea of virtualization, because it allowed me to install the bulky multimedia conversion packages that I needed for my media server, while keeping my web server streamlined and focused. Additionally, if I switch hardware later on, I can simply set up the core virtualization system and then copy my VMs over without having to reinstall and reconfigure my entire stack for both servrs. After deciding on virtualization, I went out to my local Frys and picked up a low-power AMD 64-bit CPU to save further energy. One important point before you begin - your CPU must support hardware virtualization in order to use KVM.
I reviewed several sources of information while completing this project, and I found this guide at the Ubuntu Community Documentation site, this guide on the HowtoForge site, and this forum thread very helpful. Below is a quick rundown of the method I used after extensive trial & error to get this working on my setup. I went through a lot of grief because of my decision to pursue LVM-based virtual machines instead of simple disk images, but I think the performance gain and optimization of disk I/O was worth it. Hopefully I'll be able to save you some of that grief.
I started out with a fresh Jaunty install with the openssh-server package installed, and I used an SSH console to log into my machine remotely. I used the command below to make sure that my CPU supports hardware virtualization, checking to make sure I got some output:
egrep '(vmx|svm)' --color=always /proc/cpuinfo
VMX is Intel-based hardware virtualization, and SVM is AMD's technology. If nothing is shown when you run the command on your machine, then you are out of luck.
Next, I installed the ubuntu-virt-server package.
sudo apt-get install ubuntu-virt-server
Then, I added myself to the libvirtd group.
sudo adduser myusername libvirtd
Next, I needed to set up network bridging. I installed the bridge-utils package.
sudo apt-get install bridge-utils
Then, I reconfigured my /etc/network/interfaces file.
sudo nano /etc/network/interfaces
I manage my static IP address through the DHCP server on my router, so I kept DHCP as the method of IP discover for my network. My interfaces file looked like this when I was done:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet manual
auto br0
iface br0 inet dhcp
bridge_ports eth0
bridge_fd 9
bridge_hello 2
bridge_maxage 12
bridge_stp off
Since I was remotely connecting to my machine via SSH, I went ahead and instructed the machine to reboot to make sure that the connection was set up correctly. This shouldn't be necessary, you can also use sudo invoke-rc.d networking stop and sudo invoke-rc.d networking start (this is preferred over a networking restart if you are switching from DHCP to static), but I decided to go ahead and reboot anyway to make sure everything was configured correctly.
sudo reboot
The next step I took was to create a minimal image-based VM that I later converted into an LVM-based VM. Every attempt I made at skipping the image-based VM and going with LVM from the start failed. I had a large chunk of space reserved for LVM, but I didn't have the logical volumes that I was planning use for the VMs created yet. I followed Falko's recommendation on HowtoForge, and created a set of directories in my home folder that I copied the vmbuilder template to.
mkdir -p ~/vm1/templates/libvirt
cp /etc/vmbuilder/libvirt/* ~/vm1/templates/libvirt/
Then I altered the template to enable bridged networking.
nano ~/vm1/mytemplates/libvirt/libvirtxml.tmpl
I changed <interface type='network'> to <interface type='bridge'>
and <source network='default'/> to <source bridge='br0'/>.
I wanted an SSH server on my VMs, but I found that if I used the --addpkg argument on the vmbuilder command, my VMs wouldn't get unique SSH keys. Instead, I used a script that is run at the first boot.
nano ~/vm1/boot.sh
apt-get update
apt-get install -qqy --force-yes openssh-server
The first time I attempted this, I created a VM with multiple partitions matching the layout and sizes that I intended for the machine once it was up and running. I had a root partition, swap space, and a 500GB partition that I planned to use for my web applications, Mercurial repositories, etc. I created the VM with these specifications, and when I went to convert it from image-based to LVM, I found that the process took way too long. 12 hours into the conversion, I finally gave up and decided to go with a minimal VM at first which I would expand with fdisk after it was up and running.
I kept my root at 12 GB, and my swap space at 1.5 times the amount of physical memory I planned to allocate to the VM. I used the following command to create my VM, which you will want to tweak for your setup:
sudo vmbuilder kvm ubuntu --suite=jaunty --flavour=virtual --arch=amd64 -o --libvirt=qemu:///system --tmpfs=- --templates=templates --user=myusername --name="My User Name" --pass=mypassword --addpkg=acpid --firstboot=boot.sh --mem=512 --hostname=vm1 --rootsize=15000 --swapsize=1250
The next step was to convert the disk image to a raw image, which can later be copied to the LVM with the dd command.
cd ~/vm1/ubuntu-kvm/
qemu-img convert disk0.qcow2 -O raw disk0.raw
Then, I was ready to create the logical volume that would house the VM. I used the full 500GB that I was planning to allocate to the VM. I already had a volume group that is called vg01 in this example. The logical volume in this example is called vm1.
lvcreate -n vm1 -L500G vg01
Then, I used dd to copy the raw image to the new logical volume.
dd if=disk0.raw of=/dev/vg01/vm1 bs=1M
Once that was complete, I needed to change the location of the VM that libvirt was looking for.
cd /etc/libvirt/qemu
nano vm1.xml
I changed the disk tag to look like this:
<disk type='block' device='disk'>
<source dev='/dev/vg01/vm1'/>
<target dev='hda' bus='ide'/>
</disk>
Since we've changed the configuration xml, we now need to instruct KVM to reload it.
sudo virsh --connect qemu:///system
define /etc/libvirt/qemu/vm1.xml
I moved my .qcow2 and .raw images out of the ubuntu-kvm folder to make sure that they weren't being used by KVM.
Next, I needed to set up a management interface. I'm running Ubuntu Jaunty on my desktop, so I simply installed the virt-manager package. Once installed, you can access it under Applications-->System Tools-->Virtual Machine Manager. Upon launch, click File-->Add Connection. Choose QEMU as the hypervisor, and Remote Tunnel over SSH as the Connection. Enter the hostname of your physical host machine, and connect. Your new virtual machine should show up underneath your physical machine. You can double-click it to connect using QEMU and see the console output.
If everything has gone well, your machines should show up as running in virt-manager. If the boot.sh script ran correctly, you should be able to SSH into them using the IP assigned by your DHCP server or the static IP you've established. Like I mentioned previously, I manage static IPs through my DHCP server, so my router assigned the servers the predetermined IP I set for them and automatically registered their hostname on the router's DNS gateway. Because of this, I was able simply ssh vm1 to get to my servers. You will need to adjust based on your own setup.
Once you are able to connect to your virtual server via SSH, you can take care of the final step of provisioning the rest of your storage. I used fdisk.
sudo fdisk /dev/sda
After creating the desired partition, I set up a mount point and added a line to fstab.
sudo mkdir /mystorage
sudo nano /etc/fstab
/dev/sda3 /mystorage ext4 defaults 0 0
And that was it, I was ready to set up my server. I finished this project a couple of weeks ago, so hopefully I've remembered everything. If I'm missing something, please let me know in the comments.
Comments are closed.
Comments have been closed for this post.
Other posts:
« Installing Adobe Air on Ubuntu Jaunty 64-bit | Easily Working With Pinax on Multiple Machines »
Categories
By Month
- November, 2009
- October, 2009
- August, 2009
- April, 2009
- March, 2009
- February, 2009
- December, 2008
- November, 2008
- October, 2008
- September, 2008
By Year
Atom Feeds
Latest Comments
-
-posted by hokOffillaCal on Easily Working With Pinax on Multiple Machines, 1 day, 11 hours ago
-
-posted by test on DRY Ajax Comments, 2 weeks ago
-
-posted by test on DRY Ajax Comments, 2 weeks ago
-
-posted by srn on DRY Ajax Comments, 1 month, 1 week ago
-
-posted by Brandon Konkle on DRY Ajax Comments, 4 months ago
9 comments so far:
Wow, the
prettify.jsscript really messed with the command-line examples here. I might have to look into a different syntax-highlighting engine. Maybe I'll go with Pygments on the server-side instead of using a client-side solution.Posted by Brandon Konkle 10 months, 2 weeks ago.
Thanks for the great info. Is there a web based management tool for KVM that you would recommend instead of virt-manager? I too am running an Ubuntu desktop, but if I install virt-manager it drags in KVM on my workstation which subsequently installs the intel-kvm kernel modules which interferes with some other software I have. Thanks!
Posted by Dave Vree 9 months, 4 weeks ago.
@Dave - I'm glad this was helpful to you! There is a web-based management tool made by RedHat that looks very promising called oVirt. I haven't installed it yet, but it looks fantastic and it boasts some great enterprise-level features.
Posted by Brandon Konkle 9 months, 3 weeks ago.
Nice howto! May be you'd like to note that the harddisk can be paravirtualized by changing the vm1.xml to
This increased disk i/o by 350% on my system.
Tim Kaufmann
Posted by Tim Kaufmann 7 months, 2 weeks ago.
Ahem, the comment function just ate up the code :-)
Set the target dev to 'vda' and the bus to 'virtio'.
Tim
Posted by Tim Kaufmann 7 months, 2 weeks ago.
I fixed your comment above (just needed to add 4 spaces in front of the code so that Markup would recognize it as such), and I'm definitely going to try that when I get home. Can you point me to a good summary of how paravirtualization actually works?
Thanks!
Posted by Brandon Konkle 7 months, 2 weeks ago.
You could have just installed virt-manager from the start to setup your VM parameters in a GUI. Jaunty supports attaching to lvm as a host disk for VM images, then all you need to do is copy the old raw vm image over top. Just an easier way. They did all this work in libvirt to make our lives easier.
Posted by Jeremy 7 months, 2 weeks ago.
Jeremy: That's definitely great news - I didn't realize that virt-manager was capable of that! Next time I set up a virtual machine, I'll give that a try and post a new blog entry. Thanks!
Posted by Brandon Konkle 7 months, 2 weeks ago.
Maybe you can have a look at PROXMOX VE. I use that for my servers to control the KVM virtual machines. Setup only takes 30 minutes :).
Posted by Jorem 7 months, 2 weeks ago.