This page describes the example from the OLS paper (pdf), and contains the details of how an appliance running Kronolith can be constructed both from a metadata-only recipe and from a binary image. Kronolith is a web-based calendaring application, and was mainly chosen because it makes for a fairly simple yet useful example.
The recipe allows creation of the Kronolith appliance in a reproducible manner, and in a way that can be easily integrated in a infrastructure managed by puppet. To make trying out the recipe easy, it is written so that it can be used without a running puppetmaster by default. Standalone installs, while they work, are a little besides the point of recipes. If you already have a puppetmaster, you should follow the instructions for that.
These instructions assume that you install the Kronolith appliance
on a paravirt Xen host, running, for example, Fedora Core 6/7 or RHEL
5. You also need a DHCP server that will hand out an IP to the
virtual machine; you can, of course, pin the IP to a fixed MAC address
and pass that MAC address to virt-install below.
The recipe requires puppet version 0.23.0 or later.
The install is done with virt-install. Use either the simple wrapper script or run the following command yourself:
virt-install -n kronolith -r 512 \
-f /var/lib/xen/images/kronolith/root.raw -s 5 \
-f /var/lib/xen/images/kronolith/database.raw -s 5 \
-p -l http://download.fedora.redhat.com/pub/fedora/linux/core/6/i386/os \
-x "ks=http://people.redhat.com/dlutter/kronolith-appliance/kronolith.cfg"
Once the install finishes, you need to restart the virtual machine
so that it configures itself. The first boot will take a while as
puppet installs packages, creates the database, starts services
etc. If you have local yum mirrors, you can speed this step up a
little: download the kickstart file and
the puppet scripts, unpack the puppet
scripts and edit the yum repo files in
modules/yum/files, pack everything back up and put the
new tarball on a webserver. Change the PP_TGZ variable
in the kickstart file to point to the URL for that tarball, and put
the kickstart file on a webserver, too. If you find yourself doing
that, you should really install puppet and run your own
server — you're already customizing the appliance recipe, and
that's much easier with a puppetmaster.
You can log into the virtual machine with ssh - the root password is
secret (and should probably be changed). To access
Kronolith, go to http://HOST/horde.
To install the appliance and have it register with an existing puppetmaster you need to do the following:
kronolith.example.com
modules/kronolith somewhere onto your
puppetmaster's module search path.
puppetca --clean kronolith.example.com on your
puppetmaster to make sure you don't have any old SSL
certificates for it sticking around.
node statement for the virtual machine to your
sitewide manifest:
import "kronolith"
node 'kronolith.example.com' {
include kronolith::default
}
If you have local yum mirrors, you might want to include the class
that does your local yum configuration in there, too — if you
don't have one, you can use the yum module from the
provided tarball as a starting point.
virt-install on the host; this is almost the same
command as the standalone case, just with a slightly different
Kickstart file:
virt-install -n kronolith -r 512 \
-f /var/lib/xen/images/kronolith/root.raw -s 5 \
-f /var/lib/xen/images/kronolith/database.raw -s 5 \
-p -l http://download.fedora.redhat.com/pub/fedora/linux/core/6/i386/os \
-x "ks=http://people.redhat.com/dlutter/kronolith-appliance/kronolith-puppet.cfg"
The provided kickstart file performs by
default a standalone install. If you already have a puppet master,
untar the puppet files and put the module
in modules/kronolith on the module path of the
puppetmaster. Add a node statement for the virtual
machine, following the file scripts/node.pp
As a first simple variation, one that doesn't affect the appliance at all, we change the root password on the appliance. The site manifest should contain this modified node statement:
import "kronolith"
node 'kronolith.example.com' {
user { root: password => 'CRYPTED_PASSWORD_HASH' }
include kronolith::default
}
where CRYPTED_PASSWORD_HASH is the hash of whatever password you want to use for root. Of course, if you'd rather enable login through authorized ssh keys, you can deploy the appropriate /root/.ssh/authorized_keys file in a similar manner.
A second variation, one that does change the appliance, is changing
some of the configuration of horde. Rather than editing the
conf.php file that came with the recipe directly, we want to
keep our changes separate from the recipe and therefore
create a new conf.php file on the puppetmaster and
use overrides in puppet to use that new file. The new
node statement for the site manifest is now
import "kronolith"
class kronolith::myhttpd inherits kronolith::httpd {
File['/etc/horde/conf.php']:
source => "puppet:///path/to/my/new/conf.php"
}
}
node 'kronolith.example.com' {
user { root: password => 'CRYPTED_PASSWORD_HASH' }
# We need to spell out what went into kronolith::default, and replace
# kronolith::httpd with our new kronolith::myhttpd class. This is mostly
# because puppet does not support multiple inheritance
include kronolith::postgres
include kronolith::myhttpd
include kronolith::iptables
}
The only change that is needed to generate a fullyvirt appliance from the recipe, is to change the names of the disks in the kickstart file from xvd? to hd?.
The recipe install produces an appliance image that can be distributed in its own right; because of its size, it's not included here.
Besides the two disk files root.raw and database.raw, you need a description of the image that a management tool can use to create virtual machines from it. We use virt-image, a tool that is part of the virtinst suite of virtual machine tools. You need at least version 0.300.0 of virtinst — on Fedora, you can simply yum install python-virtinst, on other distributions you will need to download the sources. To learn more about virt-image, look at the man pages for the virt-image command and the XML format it uses.
With virt-image at hand, you can create an image--based virtual machine using the provided metadata: download the file and save it in the same directory as the two disk images and run:
virt-image -n kronolith --vnc [--mac XX:XX:XX:XX:XX:XX] image.xml
If you built an image for a fullyvirt host, you need to use a slightly different metadata file for the invocation of virt-image above.
Obviously, for proper distribution of such an appliance, you'd want to bundle the two disk images and the metadata file into one tarball or, even better, an RPM. If such an appliance should register itself with the puppetmaster upon startup, you need to prepare it by removing the directory /var/lib/puppet/ssl from the image. When the VM is booted the next time, the puppet client in it will look for a host called puppet and register itself with the puppetmaster running on it. To give users a full record of the contents of the appliance, you should also give them the kickstart file and the puppet manifests used to construct it.
It is also posible to use existing appliances, add some metadata to them, and create virtual machines from them with virt-image. With that, end users don't have to touch Xen config files or know how to create KVM virtual machines - virt-image does that for them. Ideally, that metadata would come packaged with the appliance.
As a first example, we create a VM running an ISO SystemRescueCd:
virt-image -i sysresccd.xml -n sysresccd
This will only work on a fully-virtualized host; if you try to create the VM on a paravirt Xen host, you will get an error message, rather than an obscure error during boot. Note that virt-image creates a file to back the VM's hard disk — SystemRescueCD refuses to boot without one.
As a second example, we'll use an existing appliance: the JumpBox MediaWiki appliance. Running it on an HVM host follows the same step as the previous example:
virt-image -i mediawiki.xml -n mediawiki [--mac XX:XX:XX:XX:XX:XX] --vnc
As you can see from this example, running images with virt-image does not require much knowledge about virtualization technolgies from the end user, and makes it very simple to distribute prebuilt appliances. This will get even easier once virt-manager supports creating virtual machines based on images.