Let’s Build a Cloud — Puppet

In last week's blog, I talked about familiarizing yourself with the OpenStack components. This week, I will focus on Configuration Management Systems (CMS), which have greatly grown in popularity over the past few years.

While it used to be that CFEngine was the main open source CMS, it'€™s now been overtaken by the likes of Puppet and Chef. Similar to the web framework trend of seven to eight years ago, several homemade CMS projects have sprung up as well.

I won'€™t spend this space advocating one CMS over the other; each has its pros and cons. My suggestion is to think about the goals that you would like a configuration management system to reach and then find one that matches those goals and suits your style.

For the rest of this series, though, I will focus on Puppet as the CMS choice. In this blog, will give a brief introduction to Puppet and its OpenStack-specific features.

Installing Puppet

As with the other parts of this series, I will focus on Ubuntu 12.04 as the operating system.

To install Puppet, simply enter

root@server:~# apt-get install puppet

This will download and install Puppet as well as its dependencies. 

Configuring Puppet

Puppet is able to run in two different modes: stand-alone and client/server. The client/server mode requires a dedicated server known as the Puppet Master. This allows you to manage several servers from a central location. The stand-alone mode allows you to manage just a single server locally. Normally, you would want to run the client/server model in production, but for this series, I'€™ll just use standalone.

When using the stand-alone mode, no configuration needs to be made, short of the base configuration that comes with the Ubuntu package.

First Step

Puppet configures servers by reading and applying files known as '€œmanifests.'€ Manifests contain a simple scripting-like language that describe the state that you want the server to be in.

To create a manifest, just open a text editor and create a plain text file. Manifests, by convention, have a file extension of .pp. 

Create a file called manifest.pp that contains the following:

notify { 'Hello, World!': }

Next, apply the manifest:

root@server:~# puppet apply --verbose manifest.pp

Once applied, you should see:

notice: Hello, World!

Let'€™s dissect the contents of the first manifest.pp:

notify { 'Hello, World!': }

The first word, notify, is known as a resource type. Puppet has several resource types. Some create files, some install packages, and some are custom-created by users.

Each resource declaration has a name. The name comes right after the { and before the :. In this case, the name of the notify resource is '€˜Hello, World!'€™.

Names must be unique between resources. For example, make manifest.pp look like this:

notify { 'Hello, World!': }
notify { 'Hello, World!': }

And apply the manifest again:

root@server:~# puppet apply --verbose manifest.pp

The error will read:

Duplicate definition: Notify[Hello, World!] is already defined in file /home/ubuntu/manifest.pp at line 1; cannot redefine at /home/ubuntu/manifest.pp:2

Between the : and } are usually the options for the resource. In the notify example, there are no options. Erase the contents of manifest.pp and add the following:

package { 'logwatch':
    ensure => installed,

Apply the manifest:

root@server:~# puppet apply --verbose manifest.pp

You'€™ll see that Puppet has downloaded and installed the '€œlogwatch'€ package. If you apply the manifest again, Puppet will not do anything. This is due to Puppet'€™s philosophy of idempotency — meaning, the same manifest can be run multiple times and Puppet will only make changes when they are not in line with the manifest.

Puppet Modules

Puppet manifests can be grouped into modules. These modules can then be shared so others can re-use work already done. Puppet Forge has a very large collection of community contributed modules. There are even more floating around on GitHub.

Let'€™s take a look at using the MySQL module. 

First, install the module. Starting with Puppet 2.7.12, the puppet command will have the ability to natively download modules that are published on Puppet Forge. As of the time of this writing, Ubuntu 12.04 uses Puppet 2.7.11. While it is possible to add in the module abilities to Puppet 2.7.11, this procedure will soon be moot. 

Instead, I'€™ll demonstrate how to download a module from GitHub. This way, if a module is not published on Puppet Forge, you will still know how to manually obtain the module.

Ensure you are root:

root@server:~# sudo su

Install git:

root@server:~# apt-get install -y git

Change to the standard module directory:

root@server:~# cd /etc/puppet/modules

Finally, clone the module'€™s repository:

root@server:/etc/puppet/modules# git clone https://github.com/puppetlabs/puppetlabs-mysql mysql

Now we'€™ll create a simple manifest that installs and configures MySQL by using the MySQL module:

class { 'mysql': }
class { 'mysql::server': 
   config_hash => { 'root_password' => 'password' }

Apply the manifest like so:

root@server:~# puppet apply --verbose --noop manifest.pp

The –noop flag stands for '€œno operation'€. Puppet will simply print what it would have done without the –noop flag. This is very useful for testing.

Review the output. The only error should be about Puppet not being able to evaluate '€˜/sbin/status mysql'€™. This make sense since MySQL is not yet installed and so this error can be ignored.

Now apply the module without –noop:

root@server:~# puppet apply --verbose manifest.pp

Once done, MySQL should be installed and running. You can verify this by typing '€œmysql'€ and getting a MySQL prompt.

Further Puppet

This only scratched the surface of Puppet. To learn more, Puppet has an excellent documentation section.

Puppet and OpenStack

Puppet provides a set of modules that have the ability to install and configure an entire OpenStack cloud. We will utilize these modules in the next part of the series.

This is part three in the Let's Build a Cloud series. To start from the beginning, please click here.