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.

Recipe

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.

Prerequisites

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.

Standalone Installation

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.

Installation with a puppetmaster

To install the appliance and have it register with an existing puppetmaster you need to do the following:

  1. Assign a hostname, IP address, and MAC address for the virtual machine in your DHCP/DNS infrastructure. We'll assume that the full hostname is kronolith.example.com
  2. Unpack the puppet scripts and copy modules/kronolith somewhere onto your puppetmaster's module search path.
  3. Run puppetca --clean kronolith.example.com on your puppetmaster to make sure you don't have any old SSL certificates for it sticking around.
  4. Add a 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.
  5. Start the install of the virtual machine by running 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

Variations

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
}

Fullyvirt version

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?.

Image

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.

Other Appliances

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:

  1. Download the ISO
  2. Download the image metadata into the same directory as the ISO
  3. Start the virtual machine with
    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:

  1. Download the appliance and unzip it.
  2. Download the image metadata and store it in the disks subdirectory that the unzip created (mediawiki-1.0RC4/disks)
  3. Start the virtual machine with
    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.

Last modified: 2007-09-14