'Y'

Controlling your systems with Puppet

Even if it may seem so, keeping a correct configuration on all your systems is not a trivial task. And, more than that, it is also a very important one. Regardless of their role - development environments, regression test beds, production servers etc. - it is vital that every machine is configured correctly for producing reliable results or serving adequate content.

The challenge. Even if it may seem so, keeping a correct configuration on all your systems is not a trivial task. And, more than that, it is also a very important one. Regardless of their role - development environments, regression test beds, production servers etc. - it is vital that every machine is configured correctly for producing reliable results or serving adequate content.

The naive solution. The classical approach involves developing scripts and using configuration files to make sure that everything is in its place. Indeed, this is the most cost effective solution in simple scenarios: a few systems running a relatively low number of services. But, unfortunately, it is not a scalable one. As we scale up, by adding more services, the scripts become more complex and coupled, making them hard to manage. Adding a new functionality or debugging a script failure will prove to be very time consuming. The same goes for scaling out, by increasing the number of managed systems. We will feel the need for centralized management, monitoring and reporting, which we cannot achieve with naive solutions.

The smart solution. This is where configuration management tools show their power. There are many different options to choose from (CFengine, Chef, Puppet), and they all endorse two basic ideas. First, we need to have a declarative language that accurately describes the desired state of a system, and in a uniform way. In other words, we will say where we want to go, not how to get there. We set a "destination" and the tool will take care of the "journey". Second, centralized management must be possible. A "master" will be in charge of monitoring the managed systems and pushing the correct configuration, if needed.

Puppet. Puppet is a relatively new entry in this market, but it is increasingly popular, because of its flexibility and smooth learning curve. It is written in Ruby and it has its own declarative language. The building blocks of Puppet are resources and manifests. Understanding these two concepts provides a good insight in Puppet's philosophy.

Controlling your systems with Puppet.jpeg


Resources. Nearly every aspect of a system - files, users, packages, services etc - is abstracted as a resource. This abstraction means that the description of a resource is separated from its implementation. This is achieved by modeling the states that a resource may have. For example, we will say that we want a service to be "running", without knowing what the command for starting a service is. More to the point, starting the "apache2" service is as simple as running the following command:

puppet resource service apache2 ensure=running

Even if different Linux distributions have different ways of starting a service, we don't need to bother about it. The Puppet implementation layer takes care of all the backend jobs for us. And, more than that, we can use the same command across different operating systems - Linux and Windows, for example. For listing all the resource types that Puppet can handle, we can use the "puppet describe" command, and for inspecting what attributes a resource type can have we use the same command followed by the desired type (e.g. "puppet describe service"). The output is similar to that of a "man" page.

Manifests. If we want persistent configurations, we need to store resource definitions in files, called manifests. They contain definitions written using the Puppet declarative language, with a syntax similar to Ruby. We don't need to list all the possible attributes for a resource. Each attribute has a default value that will be used if not explicitly stated. For example, we define the user "luxoft" with the home directory in "/home/luxoft" and the default shell "/bin/bash":

user { "luxoft":
      ensure => present,
      home => "/home/luxoft",
      shell => "/bin/bash",
}

The manifest can be "executed" with the "puppet apply" command. If we saved it in a file called "luxoft.pp", we will run "puppet apply luxoft.pp". Or we can tell the Puppet agent to periodically run it, this way ensuring that the user is always present.

Going forward. More complex scenarios can be modeled and managed using Puppet. Resources can have dependencies between them and can be parameterized with templates. Reports can be generated and visualized using a web dashboard.

References. In-depth information can be found on the Puppet Labs website [1]. They feature extensive documentation [2] and an online learning platform [3]. A virtual machine for practicing is also provided.

[1] http://puppetlabs.com/
[2] http://docs.puppetlabs.com/
[3] https://learn.puppetlabs.com/

Alexandru-Mihai Carp
Consultant in Software Administration

Share the knowledge

Still have questions?
Connect with us
Thank you.
Your request has been received.