Thursday, March 6, 2008

System Administration with Puppet

I manage quite few Linux workstations (mostly Red Hat EL4 and EL5, CentOS) and found that my home grown scripting approach to maintaining these systems was becoming increasingly difficult.

One obvious problem with using a mountain of scripts to maintain systems, what happens when I want to go on vacation and have to leave the Windows guy in charge? I needed a system that would make it easy for a temporary admin (or new team member) to take the reigns.

A couple recent issues of Linux Magazine (a great publication by the way) reviewed CFengine and Puppet for systems management. I had known that there were open source solutions out there, but had not spent the time to do the research, preferring to handle the latest challenge by writing another script.

The articles finally convinced me to do further research. I ultimately chose Puppet for several reasons, including:
  • Written in Ruby
  • Very easy to get a base system up and running
  • Helpful community
  • Active development
I really like the fact that the configuration files use Ruby syntax, so by configuring Puppet, I'm also learning something about Ruby. I'm a Perl guy, but have been interested in learning Ruby for system administration. Now I have the excuse :-)

Example Syntax
A short example of the power of Puppet.

class baseclass {
   service { "sshd":
      enable => true,
      ensure => running,
   }

   file { "/etc/shadow":
      owner => "root",
      group => "root",
      mode => 400,
   }
}

Puppet will ensure that nodes that include this class (baseclass) have the sshd service set to startup on boot and verify that it is running, starting it if necessary. Puppet will also verify the owner, group and permissions of the /etc/shadow file, if they don't match our definition Puppet will make the necessary changes.

These definitions will work regardless of the target operating system (Red Hat EL, Fedora, SuSE, Sun Solaris, BSD, whatever). That's very appealing to administrators because they don't have to script for each unique environment, Puppet handles it in the background.

Puppet uses another Ruby based utility called 'facter' that returns a whole slew of data about the node (architecture, hostname, fqdn, ipaddress, kernelrelease, ...). You can use these facter defined variables in your configurations. For example, Puppet provides for basic 'if' and 'case' statements to allow you to define conditions, for example, only include the class '64bitonly' if the architecure (returned by facter) is x86_64:

case $architecture {
   x86_64: { include 64bitonly }
   default: { }
}


Useful Puppet Links