Puppet tutorial series
(Linux configuration management)
Puppet tutorial part 1: Powering up with Puppet 2.6
This Linux Puppet tutorial will help you install Puppet for the first time and start managing your servers.
Server configuration management (
CM) is big news in the
IT world these days. Rightly so, because Linux automation, devops and
CM tools like
Puppet and
Chef
can save you an enormous amount of time and money and help you build a
really reliable and automated Linux infrastructure. In this tutorial,
I’ll show you how to set up Puppet on Linux.
If you’re a sysadmin, or anyone else who manages a bunch of servers,
CM
tools can help you create patterns or recipes which you can use to
build lots of identical servers, or cloud instances, or re-use in
different places and for different applications. Automating Linux
servers is a snap with Puppet. Puppet can manage thousands of servers as
easily as just one or two - but let’s start with one or two!
If you’re a developer, Linux configuration management lets you write
code which describes how servers should be set up - saving you the time
and effort of doing it manually, and letting you create large,
load-balanced groups of interchangeable servers which are guaranteed to
be identically configured.
Installing Puppet
So much for the sales pitch. Let’s take a look at the steps required
to get up and running with your first Puppet install (we’ll come to Chef
in a later article).
Puppet example
For this Puppet example install, we’re going to assume you’re using
an Ubuntu Linux machine. You can use a virtual machine for this, running
in VMWare, VirtualBox or Xen if you like, or just a spare Linux box
that happens to be lying around the office.
First, we need to install Puppet itself (you’ll need to log in as root or
sudo su -
on your server):
# apt-get install libopenssl-ruby rdoc libopenssl-ruby1.8 libreadline-ruby1.8 libruby1.8 rdoc1.8 ruby1.8
# wget http://puppetlabs.com/downloads/facter/facter-1.5.8.tar.gz
# wget http://puppetlabs.com/downloads/puppet/puppet-2.6.4.tar.gz
# tar xvzf facter-1.5.8.tar.gz
# cd facter-1.5.8
# ruby install.rb
# cd ..
# tar xvzf puppet-2.6.4.tar.gz
# cd puppet-2.6.4
# ruby install.rb
# puppetd --version
2.6.4
There are
gems and packages for Puppet,
but for the sake of simplicity we’re installing from source; this also
guarantees that you’ll get an up-to-date version, as Puppet is under
active development and there are frequent new releases.
Creating a Puppet configuration
Next, we need to give Puppet something to do. The code snippets that tell Puppet how a machine should be configured are called
manifests
- like a shipping manifest, it tells Puppet what things (packages,
users, files and other resources) should be present, and what they
should contain.
The first thing to do is create a directory structure to hold your
manifests. Puppet itself is not too fussy about how these are laid out,
but we’re going to follow the Puppet community’s
best practices document and use the recommended layout there. To save time, you can download a (nearly) empty
template layout. To use this:
# cd /etc
# wget http://bitfieldconsulting.com/files/powering-up-with-puppet.tar.gz
# tar xvzf powering-up-with-puppet.tar.gz
You should now have an
/etc/puppet
directory with two subdirectories:
modules
and
manifests
. Roughly speaking,
modules
is where Puppet code lives, and
manifests
is where we specify which code should be applied to each machine under Puppet’s control.
Starting the Puppetmaster
Puppet comes in two parts: a server (the Puppetmaster) which listens
for connections from clients and then tells them what manifest they
should have, and a client program, which runs on each machine under
Puppet control and connects to the Puppetmaster to get its manifest.
In our example, we’re running the master and client on the same machine, so let’s start the server:
# puppet master --mkusers
Running the Puppet client
With the Puppetmaster running, we can now check that everything is working as it should by running the client:
# puppet agent --test --server=`hostname`
info: Caching catalog for localhost.localdomain
info: Applying configuration version '1256130640'
notice: Finished catalog run in 1.23 seconds
Creating Puppet classes
While technically we have just applied a Puppet manifest to the
machine, it’s not a very interesting one, as it does nothing at all.
Let’s create a manifest that manages a simple service:
NTP (the Network Time Protocol).
NTP is a daemon which keeps the machine’s clock synchronised with reference servers on the Internet.
First we’re going to create a
class for the
NTP service (if you haven’t done any object-oriented programming, a class is just a named chunk of code which we can refer to).
I’ve created a (nearly) empty template for you for the
NTP class, so go ahead and edit the file
/etc/puppet/modules/ntp/manifests/ntp.pp
. Currently it looks like this:
class ntp {
}
Change it to this:
class ntp {
package { "ntp":
ensure => installed
}
service { "ntp":
ensure => running,
}
}
And save the file. We’ve now created a Puppet manifest which will manage the
NTP daemon (
ntp
).
Creating Puppet nodes
Because Puppet can manage many machines at once, we still need to tell it to apply the
NTP manifest to
this machine. To do that, edit the file
/etc/puppet/manifests/nodes.pp
. You’ll see a template that looks like this:
node myserver {
}
Change it to this:
node myserver {
include ntp
}
(Replace
myserver
with the name of your machine - that is, the output of
hostname -s
.)
When Puppet runs, it looks for a
node
definition that matches the name of the client machine, and applies all the classes that it finds listed there with
include
.
You’ve now told Puppet that the server
myserver
(or whatever your machine is named) should have the NTP manifest applied to it.
Applying changes with Puppet
When you run Puppet again:
# puppet agent --test --server=`hostname`
info: Caching catalog for localhost.localdomain
info: Applying configuration version '1256130643'
notice: //ntp/Service[ntp]/ensure: ensure changed 'stopped' to 'running'
notice: Finished catalog run in 0.94 seconds
What happened here? Puppet looked up the manifest for
myserver
and found this:
package { "ntp":
ensure => installed
}
service { "ntp":
ensure => running,
}
This says that the package
ntp
should be installed, and the service
ntp
should be running. Your system may or may not have
ntp
already installed, but if not, Puppet will install it. Puppet checks to
see if the service is started, and if it’s not, it starts the service
for you. If you run Puppet again now:
# puppet agent --test --server=`hostname`
info: Caching catalog for localhost.localdomain
info: Applying configuration version '1256130643'
notice: Finished catalog run in 0.66 seconds
you’ll see that Puppet does nothing, because the manifest is satisfied.
Puppet manifests are declarations
Puppet manifests are not a set of instructions, in the way that a
shell script or a Ruby program is. They’re a declaration of how the
world should be (or that part of it under Puppet’s control, anyway). If
reality differs from the manifest, Puppet takes steps to adjust reality.
This means that Puppet isn’t just useful for building machines. It
can also check them regularly to make sure that nothing important has
changed, and if it has, to correct it. If you stop the
NTP service manually and then run Puppet again, you’ll find Puppet restarts it.
Conversely, if you decide you no longer want
NTP running on your machines, you can change the word
running
to
stopped
,
and Puppet will enforce this policy on every machine that includes the
NTP manifest (which could be hundreds or even thousands of servers).
Imagine making a change like that to a large production network by
logging in to each machine in turn and running the necessary commands
manually. Not only would it be tedious and time-consuming, but if you
got interrupted halfway through, you might not remember which machines
you’d fixed, and your whole network would be in an inconsistent and
unknown state.
In our next thrilling episode
You’ve just powered up your system with Puppet! Next time in
Puppet Tutorial part 2: Client and Server,
we’ll look at how to set up Puppet to control multiple machines. If
you’ve got any comments on this Puppet tuto, do let me know!
Puppet links
Puppet books
If you’re excited about Puppet and want to learn more, may I modestly recommend the
Puppet 2.7 Cookbook?
The Puppet 2.7 Cookbook takes you beyond the basics to explore the full
power of Puppet, showing you in detail how to tackle a variety of
real-world problems and applications. At every step it shows you exactly
what commands you need to type, and includes full code samples for
every recipe.