August 11, 2008

Puppet can ease system administration tasks across the network

Author: Ben Martin

The Puppet project allows you to issue system administration commands to one or more machines, and will smooth over the differences between distributions for you. For example, if you want to install MySQL, that action should be your primary aim, and you shouldn't have to worry about if the machine is running Maemo, Ubuntu, or Fedora.

Most folks have a desktop and perhaps a server machine at home, one or two laptop machines, and perhaps a Mobile Internet Device (MID) and mobile phone running Linux. Making a single change on all your Linux devices becomes a burden to perform manually. This is compounded by the fact that a MID's Linux distribution might not be very similar to that of your laptop.

Puppet frees you from thinking about the hardware architecture a system is using, what Linux distribution it runs, or where that particular machine happens to store its Apache DocumentRoot by using a declarative language to specify the system administration task that you would like to perform. Puppet has many built-in facilities, such as classes, which allow the different details to be smoothed over when Puppet rolls out the system administration tasks you have declared.

The language used by Puppet is its biggest strength and also its biggest weakness -- having to learn a new language and way of doing things creates a learning curve during adoption. The abstraction of classes and resources in Puppet also work against it initially because most system administrators are used to creating and executing bash scripts to perform system administration. The need to learn a new language to perform tasks when you already implicitly think of how they should be done "by SSHing in" presents a barrier to adoption for Puppet.

Using a custom language for system administration tasks allows your tasks to be idempotent -- that is, safe to be run over and over. While many hand-rolled system administration scripts check to see if they should perform an action before going ahead, Puppet does these checks for you.

Puppet uses a client-server model. The server, called the puppetmasterd daemon, is responsible for telling the clients which system administration tasks they need to execute. Puppet is packaged in Hardy Universe for client and server, Fedora 9 as puppet and puppet-server, and openSUSE 11 1-Click client, server. I used a 64-bit Fedora 9 machine and version 0.24.4 of Puppet from the Fedora package repository.

The Fedora packages install puppet and its daemon, but these services are not started automatically and are not scheduled to start at bootup. The below commands start puppet and ensure it starts on system boot.

# chkconfig --add puppetmaster
# chkconfig --add puppet
# service puppetmaster start
# service puppet start

When you first set up a new client machine to use Puppet you have to get the client to contact the server and ask the server to sign an SSL certificate. After the client does this the first time you'll have to tell the server to sign the client's certificate. You should then be able to start the puppet service on the client. The steps are detailed in the installation pages.

You have to tell the Puppet client where the puppetmaster server is running. In this case I'm running them on the same machine. A method to tell Puppet clients where the server is that some Puppet users recommend is to leave the server name as puppet and use a DNS CNAME to let the clients resolve the address of the server at run time:

vi /etc/sysconfig/puppet
...
PUPPET_SERVER=virtualfed9

Pulling the strings

As a trivial example for this article, I'll ensure that if a configuration file exists, it will have a given owner, group, and permissions. I'll create a sample file with incorrect owner, group, and permissions so that we can see when Puppet fixes things:

# touch /etc/puptest
# chown ben.ben /etc/puptest
# l /etc/puptest
-rw-r--r-- 1 ben ben 0 2008-07-17 20:01 /etc/puptest

You tell Puppet what you want it to do by creating manifest files in /etc/puppet/manifests. Normally you will have a site.pp manifest that imports other manifest files depending on which host name the client has. You can set up specific configurations for each client or import a general manifest to be used across many hosts. The manifest files that are imported by site.pp are normally kept in a classes subdirectory. Classes are used by Puppet to declare how you would like a system to be configured and allow you to logically group things.

The two example manifest files shown below are based on those in Puppet's getting started guide. The site.pp manifest file can import all the other manifest files in your classes subdirectory, and only those that you explicitly use in a node entry will take effect. In this case, any Puppet client that connects will have these permissions enforced on its system. The node entry in the site.pp file on the master machine defines the configuration that you wish for each machine that connects. For example, a node "www.example.com" entry will only be applied when a Puppet client connects from that name. The name of the Puppet client is normally the same as its host name. See the node_name entry for precise details on node naming.

# mkdir -p /etc/puppet/manifests/classes
# cd /etc/puppet/manifests/classes
# vi puptest.pp
class puptest {
file { "/etc/puptest":
owner => "root",
group => "root",
mode => 440,
}
}

# cd /etc/puppet/manifests
# vi site.pp

import "classes/*"

node default {
include puptest
}

Starting the puppet service is the trigger for the /etc/puptest file to have its permissions changed.

Because the Puppet client runs as a service, the Puppet server can push configuration changes to the client machines at any time. Normally the client will periodically check if the system's configuration is inline with what you have described in the manifest for that client. For example, after starting Puppet and allowing it to change the permissions on the /etc/puptest file as shown above, if I manually change the owner of the file back to ben, then Puppet will revert that change the next time Puppet checks if the system matches the manifest for the host on the Puppet server. By default the configuration is checked every 30 minutes. To change this, set the runinterval to the number of seconds between checks in the [main] section of /etc/puppet/puppet.conf.

You do not need to run Puppet in client-server mode. If a host is not running Puppet as a service, you can run the Puppet client on a configuration file directly with a command like puppet /etc/puppet/manifests/site.pp. You can also tell Puppet to deploy whole configuration files to hosts from a central server. Alternately you can use variable substitutions and template files so that things like paths or host names can be feed into the configuration file as they are deployed to a client.

Puppet has support for keeping track of how things depend on each other. The language tutorial includes an example of telling Puppet that the SSH service's config file is dependent on the operating system. This is a major upshot of using a more declarative language to specify how you want your machines to be configured.

If you have two or three machines, having a Puppet server push your system configuration changes out to your machines can make installing and configuring software less of a burden. As an added benefit, if you have your /etc/puppet/manifests tree in a revision control system, you should be able to quickly revert a whole network of machines to a previous configuration that is known to be good.

The ultimate success of Puppet depends on how many system administrators are willing to learn its language and how many of those people subsequently contribute well coded, high quality recipes to lower the barrier for others to start using Puppet to perform useful tasks.

Categories:

  • System Administration
  • Tools & Utilities
Click Here!