Book Image

LEARNING PUPPET

Book Image

LEARNING PUPPET

Overview of this book

Build intelligent software stacks with the Puppet configuration management suite About This Book Develop high-quality Puppet modules in an isolated development environment Manage complex development environments with industry-leading configuration management tool A comprehensive guide to get you started with Puppet development and deployment in virtual environments Who This Book Is For If you are new to configuration management and IT automation processes and are looking for better ways to manage system configuration changes at scale, this book is for you. Basic knowledge of Linux System Administration is a prerequisite. What You Will Learn Manage your system with Puppet instantly Develop Puppet in an isolated development environment Make your manifests reusable to avoid re-inventing the wheel Automate monitoring to improve the user experience through increased uptime Enable nodes to communicate with each other via Puppet Master Make environment configuration dynamic using stored configurations and PuppetDB Extend Puppet beyond the built-in functionalities Manage your environment through the Puppet Enterprise console In Detail Puppet is a cross-platform, open source configuration management utility, which runs on various Unix, Linux, and Windows Microsoft platforms. It allows you to automate all your IT configurations, giving you control of what you do to each node, and also when and how you do it. You’ll be able to build and manage development, test, and production environments independently without requiring previous system administration experience. Learning Puppet is a step-by-step guide on how to get started with Puppet development and use Puppet modules as the building blocks to deploy production-ready application cluster in virtual environment. You will begin with the installation of development environment on the VirtualBox hypervisor and Puppet Learning VM that will be used as the platform for testing and development of Puppet modules. Next, you will learn how to manage virtual machines and snapshots effectively and enhance the development experience with advanced VirtualBox features. Later the book will focus on Puppet module development in detail. You will be guided through the process of utilizing existing modules that are available in the public module repository, write your own modules and use them to deploy a real-world web application that includes features such as monitoring and load balancing. You will then learn to scale your environment and turn your static configuration into a dynamic one through stored configurations and PuppetDB. Finally, the book will provide you with practical advice on Puppet troubleshooting and managing your environment with the wealth of features provided by the Puppet Enterprise console. Style and approach A comprehensive introductory guide to help you manage your infrastructure with Puppet. All instructions and explanations are supported with screenshots and code examples to ensure you get an easy start with Puppet.
Table of Contents (12 chapters)
11
Index

Creating Puppet manifests

We covered the Puppet DSL syntax that is used in the Puppet manifests. Let's try to create a manifest and learn how to apply it to the system.

Note

The simplest way to create a manifest is to use the puppet resource command to create the resource definition and redirect the output of the command to the manifest file.

The following are the steps to create a manifest:

  1. Use the puppet resource command to declare a user resource and redirect the command output to a file using a single greater than character > followed by the filename:
    puppet resource user Jakob > user.pp
    

    This command won't return any message to the screen as you have redirected the command output to a file called user.pp.

  2. Before we inspect the contents of the user.pp file, let's add another user definition to user.pp with the following commands. This time, the output redirection is done using the double greater than characters >>. The difference between the single and the double greater than characters is how the output file is managed. The > character overwrites the file contents if the file already exists, while the >> characters append to the file:
    puppet resource user Markus >> user.pp
    
  3. Let's take a look at the content of the user.pp file. To view the content, we can open the file in the text editor. Linux systems usually come with multiple text editors, such as Vi, but we'll use another editor called Nano, which is easier to use than Vi.
  4. You can open the user.pp file in the Nano text editor by typing the following command:
    nano user.pp
    
  5. You will see that the user.pp file contains two user definitions: the first definition is for the user Jakob and the second definition is for the user Markus. Currently, both the resources have the ensure attribute value as absent, which corresponds to the current state of the user accounts on the system.

    Here is the content of the file in the Nano text editor:

    user { 'Jakob':
      ensure => 'absent',
    }
    user { 'Markus':
      ensure => 'absent',
    }
    
    Creating Puppet manifests
  6. Using the arrow keys on the keyboard, you can move the cursor around the text file. Change both the ensure attribute values to present.
  7. Once the ensure attribute values for both the user resources have been changed, the content of the file should be as follows:
    user { 'Jakob':
      ensure => 'present',
    }
    user { 'Markus':
      ensure => 'present',
    }
    
  8. Now press Ctrl + X on the keyboard and save the changes by pressing Y and then Enter.

    Well done! You have just created your first manifest file that manages two resources. Now it's time to apply the manifest with the following command:

    puppet apply user.pp
    

    The following is the output generated by the preceding command:

    Creating Puppet manifests

You must have probably noticed that this time we ran the puppet apply command without the -–execute option. The --execute option is only used to provide the manifest content from the command line. Now that we have created the manifest file, and if we want to apply it, the --execute option can be omitted. Typically, the --execute option is used to pass parameters to the Puppet class that is declared in the manifest. We will discuss the Puppet classes more in detail later on in this book.

Idempotency

Let's run the command again, and you will notice the difference in the command output compared to the previous Puppet run:

puppet apply user.pp

This time, the output is shorter. The lines that notify us that the users Jakob and Markus were created are missing in this Puppet run:

Notice: Compiled catalog for learning.puppetlabs.vm in environment production in 0.14 seconds
Notice: Finished catalog run in 0.27 seconds

This is due to the idempotent nature of Puppet. As the users Jakob and Markus already exist in the system, Puppet doesn't attempt to recreate these accounts. Idempotency in Puppet means that you can apply the same manifest as many times as you like, and only when the state of the resource in the system is different from the state of the resource declared in the manifest, will Puppet ensure that the required configuration changes are performed according to the manifest.

To demonstrate how Puppet handles idempotency, we will remove the user Markus with the following command, which we are familiar with:

puppet resource user Markus ensure=absent

Then, apply the manifest again with the puppet apply user.pp command, and you can see that the user Jakob, which we did not remove earlier, does not appear in the output but the user Markus is recreated.

Here is the command again:

puppet apply user.pp

The output of the command is as follows:

Notice: Compiled catalog for learning.puppetlabs.vm in environment production in 0.15 seconds
Notice: /Stage[main]/Main/User[Markus]/ensure: created
Notice: Finished catalog run in 0.35 seconds

Puppet command line versus Puppet manifests

So far, we have practiced how to manage system resources from the command line with puppet resource command, and also learned how to manage resources with the Puppet manifest and puppet apply command. When we start expanding our environment with new hosts and increase the number of resources that Puppet manages on these hosts, you will notice that the Puppet command line doesn't scale very well. The Puppet command line typically manages a single resource, such as user Elisa or user Jakob. Each of these resources was created with its own command. If I have 100 user accounts to be managed, then that would result in the same amount of commands to be run, which would be a very tiring job for anyone to do.

Puppet is a configuration management and automation tool that helps you eliminate repetitive tasks, such as creating 100 user accounts. Instead of running the puppet resource command 100 times, it is better if we add all our users once to a single manifest file, call the file with a puppet apply command, and let the Puppet do the hard work for us. Puppet manifests are types of recipes for your system configuration. Once you have described your system configuration in the form of a manifest, you can easily transfer the recipe onto another host and apply the configuration with a single command.

Managing files and directories with a file resource

The phrase "everything is a file" that is often associated with the Linux operating system makes it an ideal environment for Puppet to manage. Puppet is very good at managing files. Puppet's file resource can create files from static source files. You can define the file content with the content attribute, or you can create files with a dynamic content using templates. A file resource can also be used to manage directories and links.

The syntax of a file resource is very similar to the user resource syntax, only the set of available attributes is different. Here is a simple example of how to create an empty directory called /root/Documents:

file {  '/root/Documents':
  ensure => directory;
}

The first line defines the type of resource we want Puppet to manage, followed by the name of the directory that Puppet creates.

The ensure attribute on line two says that the file resource must be a directory. If we omit the ensure attribute, Puppet will create a file instead of a directory.

The closing curly brace } on the third and the last line ends the file resource statement.

Let's do a practical experiment with the file resource and write a manifest file that sets a log in greeting message when the user Jakob logs in. In order to do this, our manifest must fulfill the following two criteria:

  • The user Jakob must have a home directory to store the login greeting message
  • The user Jakob must have a custom .bash_profile file present under the home directory

To start with, let's remove the user Jakob from the system so that we can easily recreate the account with a password, and tell Puppet to create a home directory for the user:

puppet resource user Jakob ensure=absent

Now when the user Jakob has been removed, let's generate a user resource for Jakob and redirect the output to the file called jakobs-login.pp. Again, we use the single > character to create a new file:

puppet resource user Jakob > jakobs-login.pp

Then, using the >> notation to redirect the output to the jakobs-login.pp file, we can generate the file resource snippet for the .bash_profile file that will be placed under the home directory of Jakob with the following command:

puppet resource file /home/Jakob/.bash_profile >> jakobs-login.pp

Now that we have the manifest body ready for editing, we can open the jakobs-login.pp file in the Nano editor:

nano jakobs-login.pp

On opening the file, you should see the following file content:

user { 'Jakob':
  ensure => 'absent',
}
file { '/home/Jakob/.bash_profile':
  ensure => 'absent',
}

Let's begin by changing the ensure attribute value from absent to present for the user resource Jakob.

Then, to tell Puppet to create the home directory for the user, we need to use the managehome attribute and set its value to true. The managehome attribute is specific to a user resource, and we can use it to tell Puppet to create a home directory for the user under the /home directory. The home directory is needed to store the .bash_profile file, which we will take a look at shortly.

Finally, to enable Jakob to log in using the password puppet, we should set the encrypted password attribute value to $1$jrm5tnjw$h8JJ9mCZLmJvIxvDLjw1M/.

This is how the user resource for Jakob should look like after the changes:

user { 'Jakob':
  ensure => 'present',
  managehome => true,
  password => '$1$jrm5tnjw$h8JJ9mCZLmJvIxvDLjw1M/',
}

Before we move on to the file resource, let's save the changes with Ctrl + X and hit Enter. Then, apply the manifest to the puppet apply command:

puppet apply jakobs-login.pp

If the Puppet run was successful, you should see the following output:

Notice: Compiled catalog for learning.puppetlabs.vm in environment production in 0.63 seconds
Notice: /Stage[main]/Main/User[Jakob]/ensure: created
Notice: /Stage[main]/Main/File[/home/Jakob/.bash_profile]/ensure: removed
Notice: Finished catalog run in 0.35 seconds

If we take a look at the third line of the output, we can see that Puppet removed the /home/Jakob/.bash_profile file although we had not yet created it. This is because of the managehome attribute that we declared for the user Jakob, which results in the Linux environment to create the file when the user is created. Because we haven't yet modified the file resource for /home/Jakob/.bash_profile in the manifest, the ensure attribute value is absent. This results in Puppet removing the file.

Don't worry, as we will now tell Puppet to recreate the file with the content that we specify:

  1. Open the jakobs-login.pp manifest file using the Nano editor using the following command:
    nano jakobs-login.pp
    
  2. Using the arrow keys, move to the file resource that currently has the following content:
    file { '/home/Jakob/.bash_profile':
      ensure => 'absent',
    }
    
  3. Instead of updating the ensure attribute value from absent to present, we can remove the attribute altogether and replace it with the content attribute. To greet the user Jakob with his name when he logs in, we can specify the content attribute in the following way:
    file { '/home/Jakob/.bash_profile':
      content => 'echo Hello $(logname)',
    }
    
  4. When you are done with the changes, you can save the file using Ctrl + X and press Enter.
  5. Now let's apply the most recent changes from the manifest;
    puppet apply jakobs-login.pp
    

    The output is as follows:

    Notice: Compiled catalog for learning.puppetlabs.vm in environment production in 0.22 seconds
    Notice:/Stage[main]/Main/File[/home/Jakob/.bash_profile]/ensure: defined content as '{md5}7af0d63debeedf19adbd8bb239f5ab36'
    Notice: Finished catalog run in 0.53 seconds
    
  6. Now, it is the big moment to test whether our configuration changes work as expected. Log out with the exit command and then log in as user Jakob using the password puppet.

    If the configuration changes were successful, you should see the bottom of the login banner, showing the message Hello Jakob.