To use Puppet more effectively, you need to understand how modules and manifests are built. This tutorial will walk you through how these Puppet components work by setting up a LAMP stack on an Ubuntu 14.04 server.

Requirements

  • Installing Puppet (master and agent). More about this -.
  • Possibility to create at least one virtual server Ubuntu 14.04 for servicing the Puppet agent node.

Puppet Code Basics

Resources

Puppet code mainly consists of resources. A resource is a piece of code that describes the state of the system and determines the changes it needs. For example:

user("mitchell":
ensure => present,
uid => "1000",
gid => "1000",
shell => "/bin/bash",
home => "/home/mitchell"
}

The resource declaration has the following format:

resource_type("resource_name"
attribute => value
...
}

To view all Puppet resource types, issue the command:

puppet resource --types

You will learn more about resource types in this guide.

Manifestos

A manifest is an orchestration script. Puppet programs with a .pp extension are called manifests. The default Puppet manifest is /etc/puppet/manifests/site.pp.

Classes

As in any regular programming language, classes are responsible for organizing and reusing parts of the orchestration.

Within a class definition is a block of code that describes how the class works. Once you define a class, you can use it in manifests.

The class definition has the following format:

class example_class(
...
code
...
}

This code defines the example_class class. The Puppet code will be in curly braces.

A class declaration is the place in the code where a particular class is called. With a class declaration, Puppet processes its code.

The class declaration can be ordinary and by resource type.

A regular class declaration is added to the code using the include keyword.

include example_class

When declared as a resource type, the class is declared in resource format:

class("example_class":)

This declaration allows you to add class parameters to your code that override the default values ​​of class attributes. For example:

node "host2" (
class ("apache": ) # use apache module
apache::vhost ( "example.com": # define vhost resource
port => "80",
docroot => "/var/www/html"
}
}

Modules

A module is a group of manifests and other files organized in a predefined way that makes it easy to share and reuse individual parts of the orchestration. Modules help organize Puppet code because they can be used to separate code into multiple manifests.

Puppet modules are stored in the /etc/puppet/modules directory.

Writing a manifesto

You can practice writing Puppet manifests, modules, and classes using the example of installing a LAMP stack on an Ubuntu server (the result will be ).

So, to orchestrate an Ubuntu 14.04 server and install a LAMP stack on it, you need resources for the following actions:

  • installing the apache2 package.
  • starting the apache2 service.
  • package installation MySQL server, mysql-server.
  • starting the mysql service.
  • installing php5 package
  • creating a PHP test script, info.php.
  • updating the apt index before installing each package.

Below you will find three examples of Puppet code that can be used to achieve such a LAMP stack setup.

The first example will teach you how to write basic manifests in one file. The second example will help you assemble and use a class and module based on previously written manifests. The third example will show you how to use pre-built public modules to install a LAMP stack.

Note: For testing it is better to use a fresh virtual server.

Example 1: Installing LAMP with one manifest

The Puppet manifest can be written on the agent node and then executed using the puppet apply command (you don't need to have a master and agent setup to do this).

IN this section You'll learn to write manifests that use these types of resource declarations:

  • exec: Execute commands.
  • package: install packages.
  • service: service management.
  • file: file management.

Creating a manifest

Create a new manifest:

sudo vi /etc/puppet/manifests/lamp.pp

Add the following code to it to declare the required resources.

# run "apt-get update" command
exec("apt-update": # resource exec "apt-update"
command => "/usr/bin/apt-get update" # command that this resource will run
}
# install apache2 package
package("apache2":
require => Exec["apt-update"], # request "apt-update" before installing the package
ensure => installed,
}
# start apache2 service
service("apache2":
ensure => running,
}
# install mysql-server
package("mysql-server":
require => Exec["apt-update"], # request "apt-update" by reinstalling
ensure => installed,
}
# start the mysql service
service("mysql":
ensure => running,
}
# install php5 package
package("php5":
require => Exec["apt-update"], # request "apt-update" before installation
ensure => installed,
}
# start the info.php service
file("/var/www/html/info.php":
ensure => file,
content => "", # phpinfo code
require => Package["apache2"], # request for package "apache2"
}

Applying a manifest

To use the new manifest, enter the command:

sudo puppet apply --test

It will display a voluminous result that displays all changes in the state of the environment. If there are no errors in the output, you should be able to open your external IP address or domain name in the browser. A test test will appear on the screen. PHP page with information about the stack. This means that Apache and PHP are working.

Now the LAMP stack is installed on the server using Puppet.

This is a fairly simple manifest since it can be executed on an agent. If you don't have a Puppet master, other agent nodes won't be able to use this manifest.

The Puppet master server checks for server state changes every 30 minutes.

Example 2: Installing a LAMP stack using a module

Now try creating a simple module based on the LAMP manifest you wrote in the previous section.

To create a module, create a new directory in the modules directory (its name must match the name of the module). This directory should contain a manifests directory and an init.pp file. The init.pp file specifies the Puppet class (its name must also match the name of the module).

Creating a Module

Go to the Puppet master server and create a directory structure for the module:

cd /etc/puppet/modules
sudo mkdir -p lamp/manifests

Create and open the init.pp file in the editor:

sudo vi lamp/manifests/init.pp

Insert the lamp class into the file:

class lamp(
}

Copy the contents of the manifest from section 1 and paste it into the lamp class block. You now have a lamp class definition. Other manifests will be able to use this class as a module.

Save and close the file.

Using a module in the main manifest

Now you can configure the main manifest and use the lamp module to install the LAMP stack on the server.

On the Puppet master server, edit the following file:

sudo vi /etc/puppet/manifests/site.pp

Most likely, the file is empty at the moment. Add the following lines to it:

node default ( )
node "lamp-1" (
}

Note: Replace lamp-1 with the hostname of your Puppet agent on which to install the stack.

The node block allows you to specify Puppet code that will only apply to some nodes.

The default block applies to all agent nodes that do not have an individual block (leave it empty). The lamp-1 block will be applied to the lamp-1 agent node.

Add the following line to this block, which uses the lamp module:

Save and close the file.

Now the Puppet agent node will be able to download settings from the master server and install the LAMP stack. If you want to make changes right now, run the command on the agent:

sudo puppet agent --test

Modules are the most convenient way to reuse Puppet code. In addition, modules help you logically organize your code.

Example 3: Installing LAMP using public modules

The MySQL module is used in a similar way. Add the following lines to the node block:

class("mysql::server":
root_password => "password",
}

You can also pass MySQL module parameters.

Add a resource that will copy info.php to the desired location. Use the source parameter. Add the following lines to the node block:

file("info.php": # resource file name
path => "/var/www/html/info.php", # target path
ensure => file,
require => Class["apache"], # apache class to use
source => "puppet:///modules/apache/info.php", # location to copy the file to
}

This class declaration uses the source parameter instead of content. This option not only uses the contents of the file, but also copies it.

Puppet will copy the file puppet:///modules/apache/info.php to /etc/puppet/modules/apache/files/info.php.

Save and close the file.

Create an info.php file.

sudo sh -c "echo""> /etc/puppet/modules/apache/files/info.php"

Now the Puppet agent node will be able to download settings from the master server and install the LAMP stack. If you want to make changes to the agent environment right now, run the command on this node:

sudo puppet agent --test

This command will download all updates for the current node and install the stack on it. To verify that Apache and PHP are working, open the node's IP address or domain in a browser:

http://lamp_1_public_IP/info.php

Conclusion

You now have basic knowledge of working with Puppet modules and manifests. Try creating a simple manifest and module yourself.

Puppet is great for managing application configuration files.

Tags: ,

Not long ago, on the pages of the magazine, we looked at the Cfengine remote configuration management system for UNIX machines, which makes life much easier system administrator by automating the steps to configure multiple network nodes. But, no matter how convenient Cfengine is, it has many disadvantages that a system called Puppet does not have.

Imagine yourself as a system administrator, responsible for maintaining the functionality of hundreds of machines running UNIX-type operating systems. Each of them requires configuration, periodic updating and monitoring, and it is assumed that many of them perform similar functions.

Two thirds are workstations, a few more are routers, and the rest are several web servers and data storage. Question: how to manage all this business? The simplest answer is to simply connect to each of them using SSH and make the necessary changes. However, this method has two problems. Firstly, it is very labor-intensive. Secondly, the administrator will constantly have to perform many monotonous actions (for example, to update OpenOffice.org on all workstations, you will have to execute the same commands several dozen times). You can try to avoid this problem by writing several scripts that will connect to each machine themselves and execute pre-written commands. But here, too, problems await you.

Scripts will constantly have to be modified to adapt them to each task; Scripts will have to take into account differences in operating systems and versions, and they will have to be debugged for a long time before being applied to running machines. In general, not comme il faut. The correct answer is to use so-called remote configuration management systems, the most famous representatives of which are open systems Cfengine and Puppet. Such systems take on all the responsibilities for bringing the machine configuration to the desired form, requiring the administrator only to describe the final state of the system in a special language (for example, a description of which packages should be installed in the OS, which lines should be added to configuration files, which commands must be executed, etc.). After this, all nodes themselves will receive information about the required state from the server and perform auto-configuration of the system. Thanks to this mechanism, new machines can be fully configured without human intervention, and existing ones can be reconfigured by adding just a few lines to the state description.

Puppet?

We have already devoted an entire article to the Cfengine system, so today we will focus on the Puppet system, which can well be called its ideological follower. Puppet was developed by Luke Kanies, who got tired of Cfengine's limitations and decided to create a better version from scratch. If you've already used Cfenfine, you'll probably find Puppet a more convenient and powerful system. Puppet's state language is more high-level and flexible, so administrators don't have to worry about things like writing separate rules for each OS type or detailed description performing trivial actions. Puppet allows its master to focus on what he wants to do, instead of how to do it (for example, to install a specific package on any of the system's supported OS, you just need to write literally a few lines saying "Install this program" instead of describing the commands, necessary for its installation). Puppet is written in a simple Ruby language, which makes it easy to adapt it to a specific task and expand its functionality (a flexible system of plugins is provided).

Additionally, unlike Cfengine's development model, which essentially revolves around one person, Puppet has a large community of enthusiasts who make improvements to the code, share configuration examples, and write documentation.

Overall, Puppet seems to be a more modern and sophisticated system with good design. Like Cfengine, it supports almost all modern UNIX-like operating systems (including MacOS X), and can also run in the Cygwin environment on top of Windows. Its dependency list only includes the Ruby interpreter and the Factor tool, so there should be no problems with installation (to be fair, Cfengine's dependency list is even shorter).

Installation

Like Cfengne, Puppet is a client-server system that consists of a control server and slave nodes. The server stores a description of the final states of the nodes (which in Puppet terms is called a manifest) and waits for them to connect. Every half hour (by default), the client connects to the server, receives from it a description of the final state, compares it with the current one, and, if it and/or the described state has changed, reconfigures the system, and then goes to sleep. Communication is carried out through an encrypted channel, so attacks based on substitution of the state description are excluded (but if an attacker takes over the server, then all nodes will be under his control).

Puppet is included in the repositories of all popular distributions, so installing it should not be difficult. For example, on Debian/Ubuntu the Puppet client can be installed like this:

$ sudo apt-get install puppet

And the server is like this:

$ sudo apt-get install puppet puppetmaster

The client and server configuration files are stored in the /etc/puppet directory. The most important of these is the file /etc/puppet/manifests/site.pp, which contains the manifest.

It stores a description of the states and should only exist on the server. For ease of debugging, let’s add a simple configuration to it:


class passwd(
file("/etc/passwd":
owner => root,
group => root,
mode => 644,
}
}
node default(
include passwd
}

These lines describe the state in which the owner of the /etc/passwd file must be root and its permissions are set to 644. We'll take a closer look at the manifest file format in the next section. The second most important file is /etc/puppet/puppet.conf. It sets the configuration of the server and clients, so it must be present on all machines organized in the Puppet network. In Ubuntu, this file contains the minimum necessary and in most cases sufficient settings. Below they are given with comments:

# vi /etc/puppet/puppet.conf
# Standard directory paths
logdir=/var/log/puppet
vardir=/var/lib/puppet
ssldir=/var/lib/puppet/ssl
rundir=/var/run/puppet
# Facter tool location,
# used to obtain information about the OS
factpath=$vardir/lib/facter
# Synchronize plugins
# (installed plugins on the server - they are copied to clients)
pluginsync=true
# Catalog with templates (read about them below)
templatedir=$confdir/templates
# Synchronization with etckeeper
# (who knows, will understand, others don’t need it)
prerun_command=/etc/puppet/etckeeper-commitpre
postrun_command=/etc/puppet/etckeeper-commitpost

The configuration file can include a large number of different options, information about which can be obtained by generating a default config:

$ sudo puppetmasterd -genconfig > /etc/puppet/
puppetd.conf.default

The default client config is generated using another command:

$ sudo puppet -genconfig > /etc/puppet/puppetd.conf.default

Fileserver.conf and auth.conf files are used for configuration file server(read about this in the “File Server” section) and authentication. There is no point in touching them yet. Once configuration is complete, the Puppet server must be restarted:

$ sudo /etc/init.d/puppetmaster restart

After which he will be ready to accept customer requests. However, without a signed certificate, no client will be able to receive the manifest from the server and configure the machine.

Therefore, we must run the Puppet clients in test mode so that they can submit their certificates to the server for signing (by the way, this can be done on all machines at the same time using the shmux tool):

$ sudo puppetd -server puppet-server.com -verbose -test

We return to the server and receive a list of certificates ready for signing:

$ sudo puppetca --list

Select a host from the list and sign its certificate:

$ sudo puppetca --sign nomad.grinder.com

Or we sign everything at once:

$ sudo puppetca --sign --all

Now you can launch clients in combat mode. But first you need to enter the name of the Puppet server in the configuration file (by default its name is just puppet):

$sudo su
# echo "" >> /etc/puppet/puppet.conf
# echo "server=puppet-server.com" >> /etc/puppet/puppet.conf
# exit

Launching clients:

$ sudo /etc/init.d/puppet start

State description language

As mentioned above, Puppet uses its own language for describing the final state operating system, with the help of which the system administrator indicates what form the OS components should be brought to in order for it to achieve the desired state. This is a rather complex language, which, nevertheless, is much simpler than any programming language. If you are at least superficially familiar with the bash scripting language, you will easily understand the Puppet language. The key element of the language is the resources that are used to describe what form one of the OS components should be converted to. For example, the following simple resource describes the desired state of the /etc/passwd file:

# vi /etc/puppet/manifests/site.pp
file("/etc/passwd":
owner => "root"
}

Here file is the resource type. There are several dozen of them in total, ranging from resources that manage files, as in this example, to packages and services. The line /etc/passwd is the name of the resource.

In the case of the file type, the name is the same as the path to the file, but in some other types the name can be arbitrary. The line owner => "root" describes setting the owner attribute to root, that is, it says that the owner of the specified file must be an administrator.

Each type of resource has its own set of attributes available for modification, plus there are special meta attributes that can be used in any resource. One of the important qualities of resources is the ability to link to them. This can be used to form dependency chains. The following entry creates the /etc/group resource, which depends on the /etc/passwd resource (dependencies are specified using the require meta attribute):

# vi /etc/puppet/manifests/site.pp
file("/etc/group":
require => File["/etc/passwd"],
owner => "root",
}

This means that the /etc/group resource can be configured (brought to the described form) only when the /etc/passwd resource is configured. Resources can be grouped into collections of resources called classes. This is necessary in order to combine resources that are similar in meaning and type of task performed into one abstract resource. For example, for convenience we could combine installation and launch nginx web server into one abstract resource of the same name:

# vi /etc/puppet/manifests/site.pp
class nginx(
package("nginx":
ensure => installed
}
service("nginx":
ensure => running,
require => Package["nginx"],
}
}

Here, the package resource type is used to install the nginx package on the system, and service is used to launch the service of the same name. With require we force the system to start the service only if the package has been successfully installed. The convenience of classes is that they can also be included depending on:

# vi /etc/puppet/manifests/site.pp
service("squid":
ensure => running,
require => Class["nginx"],
}

As in real OOP languages, classes can inherit from each other and override attributes:

# vi /etc/puppet/manifests/site.pp
class passwd(
file("/etc/passwd":
owner => "root",
group => "root",
}
}
class passwd-bsd inherits passwd (
File["/etc/passwd"] ( group => "wheel" )
}

Here the passwd-bsd class inherits from passwd to override the group attribute of the /etc/passwd resource (on BSD systems /etc/passwd belongs to the wheel group, so we created a separate class for such systems). Later we will look at a more correct and obvious way to select alternative attribute values ​​using conditions.

Variables are one of the integral components of any programming language, and Puppet has them too. Variables begin with a $ sign and can contain any number, string, or boolean value (true, false):

$want_apache = true
$apache_version = "2.2.14"

One of the most powerful variable-related features of Puppet is its integration with the facter machine information tool. This utility returns all machine-specific information in the form of key-value pairs, which are turned into variables of the same name in Puppet. Together with conditional instructions in the Puppet language, they can be used to alter resource attributes depending on the properties of the machine.

For example, the passwd class described above can be easily rewritten to automatically select an attribute depending on the OS type (and the class itself is no longer needed):

# vi /etc/puppet/manifests/site.pp
file("/etc/passwd":
owner => "root",
group => $kernel ? (
Linux => "root",
FreeBSD => "wheel",
},
}

Depending on which OS this manifest fragment will be analyzed on, the value of the group attribute will be either root or wheel. Except conditional operator, the Puppet language also supports a case selection operator, which can be used to create a particular resource depending on the value of a variable:

# vi /etc/puppet/manifests/site.pp
case $operatingsystem (
redhat: (service("httpd": ensure => running))
debian: (service("apache": ensure => running))
default: ( service ( "apache2": ensure =>
running))
}

This code defines different variants of a resource of type service depending on the operating system (service names may differ between Linux distributions, so which service Puppet should run must be specified individually for each of them).

The default option is used if the value of the variable does not match any of the previous options. In addition to the previously discussed file, package, and service resource types, Puppet supports a large number of other resource types, including those created by third-party developers. Their detailed description, including examples, supported attributes and features, can be found in the official documentation - http://docs.puppetlabs.com/references/stable/type.html. Below is a list and brief description the most used ones are:

Popular Puppet resource types

  • cron - manage cron jobs
  • exec - run scripts and commands
  • file - file management
  • filebucket - backup files
  • group - group management
  • host - manage entries in the /etc/hosts file
  • interface - configuration of network interfaces
  • mount - mounting file systems
  • notify - send a message to the Puppet log file
  • package - package management
  • service - service management
  • sshkey - manage SSH keys
  • tidy - deleting files depending on conditions
  • user - user management
  • zones - Solaris zone management

The second most important element of the Puppet language after resources is nodes. With their help, the administrator can describe to which machines certain resources and classes should be applied. In other words, it is a way to specify an individual configuration for each of the machines participating in the Puppet network. The simplest example of a node is given at the beginning of the article in the “Installation” section:

# vi /etc/puppet/manifests/site.pp
node default(
include passwd
}

This is the definition of the default node, which includes the passwd resource/class. The name default means "all other nodes", so the passwd resource/class defined somewhere above will be configured on each of them. Keyword include is used here for convenience; in fact, all classes and resources can be described directly in the node description, but this is not recommended. In addition to default, in the node name you can specify the network name of the machine (then all resources described in the node will be configured only on this machine), or an arbitrary name (then this node can be inherited by another node). To understand how this all works together with classes and resources, let's look at an example of a ready-made Puppet manifest used to configure two network machines (a web server and an NTP server):

# vi /etc/puppet/manifests/site.pp
# Installing and running an SSH server
class sshd (
package ( openssh-server: ensure => installed )
service(sshd:
name => $operatingsystem ? (
fedora => "sshd",
debian => "ssh",
default => "sshd",
},
enable => true,
ensure => running,
}
}
# Install and run Apache
class httpd(
package ( httpd: ensure => installed )
service(httpd:
enable => true,
ensure => running,
}
}
# Installing and starting an NTP server
class ntpd(
package ( ntp-server: ensure => installed )
service (
ntp-server:
enable => true,
ensure => running,
}
}
# The base node, used only as the parent of all others
node base(
include sshd
}
# The node where the web server will be located
node web.server.com inherits base (
include httpd
}
# NTP server node
node ntp.server.com inherits base (
include ntpd
}

This seemingly simple configuration does quite a lot: it gets Apache installed and running on the machine at web.server.com and an NTP server installed and running on the machine. ntp.server.com. Additionally, both machines install an SSH server. This configuration is unlikely to suit even one administrator; it will have to be seriously improved in order to teach how to properly configure servers, receive fresh configs and other files from the main Puppet server.

However, it clearly shows the power of Puppet. Using a simple config, we made the machines install and run the necessary software themselves and maintain it in working order (if the server crashes, Puppet itself will reconfigure to bring the systems to the required state).

File server

Many remote administration tasks cannot be solved without copying to machines additional files. These can be pre-prepared configs, web pages for Apache, packages not in the official repository, and much more. To ease the process of transferring these files to remote hosts, Puppet includes a file server.

File server settings are stored in the /etc/puppet/fileserver.conf file. To force Puppet to serve the contents of a specific directory to clients, you need to put a few lines in it:

# vi /etc/puppet/fileserver.conf
path = /var/puppet/files
allow *.server.com

These two lines indicate that the /var/puppet/files directory should be accessible to all hosts in the server.com domain. In addition, we can specify the full domain name of a permitted machine or its IP address, and also cut off unwanted ones using the deny directive. Any file in that directory can then be moved to the client using the file resource. For example:

# vi /etc/puppet/manifests/site.pp
file("/etc/httpd/conf/httpd.conf":
source => "puppet://httpd/httpd.conf",
mode => 644,
}

The httpd.conf file, located on the server in the /var/puppet/files/httpd directory, will be copied to the target machine along the path specified in the resource name.

Conclusions

In this article, we've covered a very small portion of Puppet's capabilities. In fact, this is a complex system, which can only be fully described on the pages of a book. At the same time, Puppet is very easy to configure and maintain, especially since you can find a lot of examples of its configuration on the Internet.

Info

  • Puppet uses HTTP protocol, so to increase performance it can be run under the control of a web server.
  • Puppet can be used to auto-configure and maintain a single local machine.
  • By combining Puppet, network installation OS (pxe-install) and self-assembled installation images, you can create a completely self-configuring network of machines that can be deployed with just one command.
  • Many large companies use Puppet in their work, such as Google, Fedora Project, Stanford University, Red Hat, Siemens IT Solution and SugarCRM.

Links

  • http://docs.puppetlabs.com - Puppet Documentation
  • http://docs.puppetlabs.com/guides/language_tutorial.html - Full description Puppet language
  • http://docs.puppetlabs.com/references/stable/type.html - Resource types

Some time ago, the list of servers in my bookmarks exceeded 200. As the number of servers increases, deploying any new configuration or installing new packages wastes a huge amount of time. So I decided to use puppet.
Puppet(English puppet) - cross-platform client-server application, which allows you to centrally manage the configuration of operating systems and programs installed on several computers. Puppet is written in the Ruby programming language.

They also say that puppet is a remote configuration management system, the most famous representatives of which are the open systems Cfengine and Puppet.

After reading the reviews, I decided to use puppet.

Puppet server installation and configuration:
Installing a puppet server:
Install puppet-server on OpenSuSE 11.4:

zipper in puppet-server

Let's change the server name to puppet:
/etc/HOSTNAME:

The DNS record must resolve to 127.0.0.2
cat /etc/hosts:

127.0.0.2 puppet.site puppet

Let's give the user rights puppet:

Let's start the Puppet Master service:

rcpuppetmasterd start

Let's add the launch of the puppet daemon to startup:

chkconfig -a puppetmasterd

Setting up a puppet server:
Let's define the directory where files will be stored that puppet-server will transfer to client machines in manifests of the file type.

vim /etc/puppet/fileserver


path /etc/puppet/files
allow *

mkdir /etc/puppet/files

chown -R puppet:puppet /etc/puppet/files

We will create a file of any content for deployment and testing on clients

touch /etc/puppet/files/puppettesting

Let's restart the puppet server:

rcpuppetmasterd restart

Puppet uses its own language for describing the final state of the operating system, with the help of which the system administrator indicates to what form the OS components should be brought in order for it to achieve the desired state. The state may mean the presence of a certain file, folder, running services installed packages, updates and more. All state settings are described in files or manifests, which are located in the directory: /etc/puppet/manifests. These files have names like *.pp.

Let's create the simplest manifesto:
/etc/puppet/manifests/1.file.pp:

file("/tmp/puppettetesting":
source => "puppet:///files/puppettesting",
}

To use this manifest:
puppet apply 1.file.pp

Installing and configuring the puppet client:

zipper in puppet

Let's give puppet rights to the user:

chown -R puppet.puppet /var/lib/puppet/

To establish a connection with the puppet server, the puppet client sends a request to confirm the certificate; after this request is confirmed on the server, the puppet client will begin to use the manifests intended for it. We will send a request to confirm the certificate:

On the server we can see what confirmation requests are pending:

"puppet-client.localdomain" (B5:12 :69 :63 :DE:19 :E9:75 :32 :2B:AA:74 :06:F6:8E:8A)

We confirm:

puppetca --sign "puppet-client.localdomain"

It's time to look at the simplest examples of creating manifests:
create a file /etc/puppet/manifests/site.pp:

node default(
file("/tmp/puppettetesting":
source => "puppet:///files/puppettesting",
}
service("ntp":
ensure => running,
enable => true ,
}
package("htop":
ensure => installed,
}
}

default - apply to all clients
file - this section says to create or overwrite the /tmp/puppettetesting file which is located on the server in the /etc/puppet/files directory
service: check whether the service is running, if not running, then start it, and also add it to startup
package: check if the htop package is installed on the client and if not, install it.

To check, run on the client:

As you can see, on the client, ntp was added to startup, the ntp daemon was launched, the htop package was installed, and the puppettetesting file was copied to the /tmp/ directory

info: Caching catalog for puppet-client.localdomain
info: Applying configuration version "1370163660"
notice: / Stage[ main] // Node[ default] / Service[ ntp] / ensure: ensure changed "stopped" to "running"
notice: / Stage[ main] // Node[ default] / Package[ htop ] / ensure: created
notice: / Stage[ main] // Node[ default] / File[ / tmp/ puppettesting] / ensure: defined content as "(md5)f2171ac69ba86781bea2b7c95d1c8e67"
notice: Finished catalog run in 3.95 seconds

In the next article I will describe more complex examples creating manifests and the puppet-dashboard web interface.

Popular Puppet resource types
cron- managing cron jobs
exec- running scripts and commands
file- file management
filebucket- file backup
group- group management
host- managing entries in the /etc/hosts file
interface- configuration of network interfaces
mount- mounting file systems
notify- sending a message to the Puppet log file
package- package management
service- service management
sshkey- SSH key management
tidy- deleting files depending on conditions
user- user management
zones- Solaris zone management

When the number of servers you manage is less than ten, rarely does anyone think about their centralized management, this may not be required. When there are dozens of servers, centralized software and configuration management is extremely useful. When there are hundreds and thousands of servers, this is vital. There are many programs of this kind, for example: Chef, CFEngine, Puppet... It’s the latter that will be discussed in this post.

Puppet is deservedly considered one of best solutions like that. It is used by companies such as Google, Citrix and Red Hat. This is a client-server application written in the Ruby programming language, which is distributed in two versions:

  • Puppet Open Source - completely free version
  • Puppet Enterprise - free for up to 10 servers, then licenses required

Let's consider installing the Puppet Open Source server and agent, which are included in the packages of most modern distributions. Next we will talk about Ubuntu 12.04 Precise Pangolin.

Server part Puppet is called puppetmaster, let's start the installation from there:

:~# apt-get install puppetmaster

And now the client:

:~# apt-get install puppet

In the client configuration file /etc/puppet/puppet.conf you need to talk about the server by adding the following section:

Server=puppet.local report=true pluginsync=false

At the initial stage, it is better to turn off pluginsync.

Let's run the puppet client so that it creates a request for a certificate:

:~# puppetd --verbose --test info: Creating a new SSL key for linux.local info: Caching certificate for ca info: Creating a new SSL certificate request for linux.local info: Certificate Request fingerprint (md5): E5: EA:AC:5B:22:9A:BA:42:B8:A1:63:9E:1F:1F:23:51 Exiting; no certificate found and waitforcert is disabled

On the server, you need to check that the certificate request has been received and, if so, issue a certificate:

:~# puppetca --list "linux.local" (E5:EA:AC:5B:22:9A:BA:42:B8:A1:63:9E:1F:1F:23:51) :~# puppetca - -sign linux.local notice: Signed certificate request for linux.local notice: Removing file Puppet::SSL::CertificateRequest linux.local at "/var/lib/puppet/ssl/ca/requests/linux.local.pem"

Repeat the previous step on the client:

:~# puppetd --verbose --test info: Caching certificate for linux.local info: Retrieving plugin info: Caching certificate_revocation_list for ca info: Caching catalog for linux.local info: Applying configuration version "1356278451" info: Creating state file / var/lib/puppet/state/state.yaml notice: Finished catalog run in 0.02 seconds

Great, everything works. Let's move on to creating the first manifesto. Manifests, or configurations, are described in a special declarative language. We will immediately get used to good things, use a modular structure and classes. For example, let's write a module that will keep the file up to date /etc/hosts on all our servers.

Let's check where puppet looks for modules:

:~# puppet apply --configprint modulepath /etc/puppet/modules:/usr/share/puppet/modules

Create directories for your module

:~# cd /etc/puppet/modules :~# mkdir hosts; cd hosts; mkdir manifests; cd manifests

The first manifest, also known as the main module file, should be called init.pp

Class hosts ( # puppet.local host ( "puppet.local": ensure => "present", target => "/etc/hosts", ip => "192.168.0.1", host_aliases => "puppet", ) # linux.local host ("linux.local": ensure => "present", target => "/etc/hosts", ip => "192.168.0.2", host_aliases => "linux", ) )

By default, puppet looks for a file /etc/puppet/manifests/site.pp to load the configuration, let's bring it to the following form:

Node default ( include hosts )

We check the manifest on the server:

:~# puppet apply --verbose /etc/puppet/manifests/site.pp info: Applying configuration version "1356281036" notice: /Stage//Host/ensure: created info: FileBucket adding (md5)notice: /Stage// Host/ensure: created notice: Finished catalog run in 0.03 seconds

On the client:

:~# ll /etc/hosts rw-r--r-- 1 root root 290 Dec 16 19:10 /etc/hosts :~# puppetd --verbose --test info: Caching catalog for linux.local info: Applying configuration version "1356283380" info: FileBucket adding (md5)notice: /Stage/Hosts/Host/ensure: created notice: /Stage/Hosts/Host/ensure: created notice: Finished catalog run in 0.04 seconds :~# ll /etc /hosts -rw-r--r-- 1 root root 551 Dec 23 20:43 /etc/hosts

After we are sure that everything is working, we allow the service to start, in /etc/default/puppet change:

# Start puppet on boot? START=yes

Starting the service

:~# service puppet start

Puppet will poll the puppetmaster server every 30 minutes for configuration changes and, if necessary, adjust the system accordingly.


Close