Running a central Puppet Master server will allow us to build configurations that are specific to a particular system and then hand them out to be executed on demand. It can be a central repository for the configuration of all servers in your data center, allowing for the centralized deployment of updates and applications.
Once the Puppet Master is installed, you’ll have an empty Puppet repository in /etc/puppet. When the Puppet Master starts up, the first file it loads is /etc/puppet/manifests/site.pp. Generally this file will include a nodes.pp file as well as set some default parameters. nodes.pp will tell the Puppet Master how to decide what classes it should apply to a system, called a node, when it checks in.
Note
The Puppet Master and agent communicate over tcp port 8140. Make sure that any applicable firewall settings allow communication on that port between the two.
Let’s step through how to set up a node definition and apply a class to it with a central Puppet Master rather than by manually applying the manifest.
First, you’ll need to have both agent and master installed. For simplicity’s sake, these can be on the same system. Then set up a simple /etc/puppet/manifests/site.pp and nodes.pp.
This site.pp includes our nodes.pp and sets up a couple of defaults. The first of these is the filebucket. When Puppet makes some change to the filesystem, such as overwriting a config file with an update, it will make a backup of the original. When we define a filebucket on our Puppet Master server (which we assume to have the hostname puppet.example.com), we can then tell all the file type resource declarations to default their backup to that bucket. The way that I’ve set up that default here is called a metaparameter. When I declare a capitalized file resource with no title, the parameters I specify for it will become the default for that resource type. I’ve also specified a metaparameter default for the path of the exec resource type. Exec is used to execute arbitrary commands from the agent and it is convenient to have a standard default path set to look for executables:
# site.pp import "nodes" filebucket { main: server => "puppet.example.com" } # defaults File { backup => main } Exec { path => "/usr/bin:/usr/sbin/:/bin:/sbin" }
In this example, I’ve defined a node explicitly as puppet.example.com and also as a default. The
Puppet Master matches nodes based upon their hostnames and will fall back
to a default node declaration if a matching node is not found. In this
case, either way, the apps::ntp
class
will be applied to the node:
# nodes.pp node default { include apps::ntp } node "puppet.example.com" { include apps::ntp }
Now that we’ve told our Puppet Master how to identify our agent and
what to do with it, we need to put the ntp
manifest that we created earlier into the
apps::ntp
class. This way, when the
agent runs it will execute our ntp
installation just as it did when it was applied with the puppet apply
command. We’ll put the class in
/etc/puppet/modules/apps/init.pp.
You’ll notice that the source parameter has changed for our
ntp.conf file. I’ve defined a string
here that points to a place where our Puppet server expects module files
to be kept. This puppet:///modules/apps/ntp/ntp.conf
location
maps to the /etc/puppet/modules/apps/files/ntp/ntp.conf
location on our Puppet Master. This allows us to distribute files from the
master to the clients without having to jump through any extra hoops, such
as setting up nfs
. Make sure to copy
the ntp.conf file to the proper place
on the master before continuing:
# apps/init.pp class apps::ntp { package { 'ntp': ensure => '1:4.2.6.p2+dfsg-1ubuntu5' } file { '/etc/ntp.conf': mode => '640', owner => root, group => root, source => "puppet:///modules/apps/ntp/ntp.conf", require => Package[ntp], } service { "ntp": ensure => running, enable => true, pattern => 'ntpd', subscribe => [Package["ntp"], File["/etc/ntp.conf"]], } }
With our node defined and importing the ntp
class that we’ve written, we can now test out the agent. On the Puppet agent
node, run sudo puppetd --test --noop --server
. This will tell
the agent to run without daemonizing into the background (puppet.example.com
--test
) and without actually modifying anything
(--noop
). The first run will not obtain
a configuration from the Puppet Master because the agent has not yet been
authenticated. It did, however, leave its certificate on the master for
inspection. The next step in getting our agent and master talking is to
have the Puppet Master sign our agent’s SSL certificate. This initial
authentication step is done with the puppetca
command. On the Puppet Master, run
sudo puppetca -la
. This will list
all of the certificates in our Puppet Master’s certificate store.
Certificates that are signed will have a +
in front of them, and unsigned certificates
will not. You should see a certificate for your agent that is not yet
signed. To sign it, simply run sudo puppetca
-sa
. This will sign all the outstanding requests and allow
those agents to talk to the master.
Note
You can define client node names in the /etc/puppet/autosign.conf file in the format agenthost.example.com or even *.example.com. Names matching these patterns will be signed automatically by the master.
At this point, we should have a fully functional master and agent
pair. The client certificate is
signed, the node has a definition, and there is a class for the ntp
installation assigned to it. Let’s prove
that it works by running sudo puppetd --test
--server
on our
client. You should see the agent run through our manifest and install
puppet.example.com
ntp
.
Congratulations, you’ve taken a big step toward implementing a scalable configuration management architecture. Some deployments will need more complicated logic than packages and configuration files, but there are plenty of resource types, plug-ins, and examples to help you out. In the next chapter, we’ll look at the more advanced features of Puppet that will let you take these simple configuration definitions and apply them in a larger-scale fashion.
Get Managing Infrastructure with Puppet now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.