Packages, Files, and Services
Puppet
In Puppet, the combined configuration to be applied to a host is called a catalog, and the process of applying it is called a run.
The Puppet client software is called the agent. Puppet calls the definition of the
host itself a node. The Puppet server is called the master.
The most common types of resources we'll manage with Puppet are packages, files, and services.
With Puppet, to install nginx, we give a resource declaration like this:
# /etc/puppet/manifests/site.pp node 'puppet-agent' { package { 'nginx': ensure => installed, } }
Then, Puppet will take the necessary actions by running apt-get behind the scenes.
Let's look at the code in detail:
node 'puppet-agent' { ... }
Note that the node keyword introduces a node declaration, a list of resources that are to be applied only to node 'puppet-agent'.
package { 'nginx': ensure => installed, }
In our case, there is one type of resource, package. As with the file resource, the resource declaration consists of the following:
- The type of resource: package
- The name of the instance: nginx
- A list of attributes
Each resource type has a different list of attributes that we can control. A useful attribute for package resources is ensure. We use this attribute to install (or sometimes remove) packages.ensure => installed,
Run Puppet:
root@puppet-agent:~# puppet agent --test Info: Retrieving plugin Info: Caching catalog for puppet-agent.ec2.internal Info: Applying configuration version '1419668689' Notice: /Stage[main]/Main/Node[puppet-agent]/Package[nginx]/ensure: ensure changed 'purged' to 'present' Notice: Finished catalog run in 4.08 seconds
When we apply the manifest, Puppet checks whether the nginx package is installed. If this is the first time we've applied the manifest, the package probably won't be present, so Puppet prints a message telling us that the package is being installed as shown above
Once the resource has been created the first time, subsequent Puppet runs will do nothing because the state of the system already matches the manifest:
root@puppet-agent:~# puppet agent --test Info: Retrieving plugin Info: Caching catalog for puppet-agent.ec2.internal Info: Applying configuration version '1419668689' Notice: Finished catalog run in 0.03 seconds
Sometimes we need to make sure a package is removed entirely from a machine:
package { 'nginx': ensure => absent, }
Using ensure => absent will remove the package if it's installed.
Another value that ensure can take on a package resource is latest. This will cause Puppet to check which version of the package is available in the repository (if we're using Ubuntu, this includes any additional APT sources that we may have configured, such as the Puppet Labs repo). If it is newer than the installed version, Puppet will upgrade the package to the latest version:
package { 'nginx': ensure => latest, }
To make our Puppet manifests more readable and maintainable, it's a good idea to arrange them into modules. A Puppet module is a way of grouping related resources. In our example, we're going to make an nginx module that will contain all Puppet code relating to nginx.
Create the file modules/nginx/manifests/init.pp with the following contents:
# /etc/puppet/modules/nginx/manifests/init.pp class nginx { package { 'nginx': ensure => installed, } }
Edit the manifests/sites.pp file as follows:
# /etc/puppet/manifests/site.pp node 'puppet-agent' { include nginx }
Run puppet:
ubuntu@puppet-agent:~$ sudo puppet agent --test Info: Retrieving plugin Info: Caching catalog for puppet-agent.ec2.internal Info: Applying configuration version '1419714937' Notice: Finished catalog run in 0.04 seconds
Note that we've modified our puppet code for node from:
# /etc/puppet/manifests/site.pp node 'puppet-agent' { package { 'nginx': ensure => installed, } }
to:
# /etc/puppet/manifests/site.pp node 'puppet-agent' { include nginx }
As we can see the nginx resource has been replaced by the line include nginx. We're telling Puppet, "Look for a class called nginx and include all the resources on this node."
The class keyword declares a group of resources (here, the package resource for nginx) identified by the name nginx. We can then use the include keyword elsewhere to include all the resources in the class at once.
But why we do this?
That's because this enables us to include the nginx class on many nodes
without repeating the same resource declarations over and oover as shown below:
node 'node1' { include nginx } node 'node2' { include nginx } node 'node3' { include nginx }
Also, by grouping resources into classes and modules helps us organize our code, and it's easy to read and maintain.
To manage services, use the service resource type. The ensure attribute controls whether or not the service should be running. To specify that the service should be running, use
ensure => running
To specify that it should be stopped, use
ensure => stopped
The enable attribute controls whether or not a service is started at boot time. To start the service at boot time, use
enable => true
If we don't want it to start on boot, use
enable => false
We can specify a dependency between resources using the require attribute:
require => Package['nginx']
If resource 'resB' requires resource 'resA', then Puppet will make sure the resources are applied in the right order.
We can have Puppet deploy a copy of a file using the source attribute:
file { '/etc/nginx/sites-enabled/default': source => 'puppet:///modules/nginx/myfile', }
File resources can trigger a service to be restarted using the notify attribute. This is useful for configuration files, for which changes often don't take effect until the relevant service is restarted:
notify => Service['nginx'],
Puppet
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization