Puppet
A Configuration Management ToolA framework for Systems Automation
A Declarative Domain Specific Language ()
An OpenSource software in written Ruby
Works on Linux, Unix (Solaris, AIX, *BSD), MacOS, Windows
Developed by Labs
Used by (http://puppetlabs.com/customers/companies/) ...
... and many others
Configuration Management advantages
Infrastructure as Code: Track, Test, Deploy, Reproduce, ScaleCode commits log shows the history of change on the infrastructure
Reproducible setups: Do once, repeat forever
Scale quickly: Done for one, use on many
Coherent and consistent server setups
Aligned Environments for devel, test, qa, prod nodes
References and Ecosystem
Labs - The Company behind- The OpenSource version
Enterprise - The commercial version
The Community - Active and vibrant
Documentation - Main and Official reference
Modules on: Module Forge and GitHub
Software related to :
MCollective - Infrastructure Orchestration framework
Hiera - Key-value lookup tool where data can be placed
PuppetDB - An Inventory Service and StoredConfigs backend
DashBoard - A Web frontend and External Node Classifier (ENC)
The Foreman - A well-known third party provisioning tool and ENC
Geppetto - A IDE based on Eclipse
Installation
Debian, UbuntuAvailable by default
RedHat, Centos, Fedora# On clients (nodes):
apt-get install puppet
# On server (master):
apt-get install puppetmaster
Add EPEL repository or RHN Extra channel
Use PuppetLabs repositories for latest updates# On clients (nodes):
yum install puppet
# On server (master):
yum install puppet-server
Installation Instructions for different OS
Puppet configuration: puppet.conf
It's main configuration file.On opensource is generally in:
/etc/puppet/puppet.conf
On Enterprise:/etc/puppetlabs/puppet/puppet.conf
When running as a normal user can be placed in the home directory:/home/user/.puppet/puppet.conf
Configurations are divided in [stanzas] for different sub commandsCommon for all commands: [main]
For puppet agent (client): [agent] (Was [puppetd] in pre 2.6)
For puppet apply (client): [user] (Was [puppet])
For puppet master (server): [master] (Was [puppetmasterd] and [puppetca])
Hash (#) can be used for comments.
Configuration options
To view all or a specific configuration setting:Important options under [main] section:puppet config print all
puppet config print modulepath
vardir: Path where stores dynamic data.
ssldir: Path where SSL certifications are stored.
Under [agent] section:
server: Host name of the PuppetMaster. (Default: puppet)
certname: Certificate name used by the client. (Default is the hostname)
runinterval: Number of minutes between runs, when running as service. (Default: 30)
report: If to send runs' reports to the **report_server. (Default: true)
Under [master] section:
autosign: If new clients certificates are automatically signed. (Default: false)
reports: How to manage clients' reports (Default: store)
storeconfigs: If to enable store configs to support exported resources. (Default: false)
Full configuration reference
Common command-line parameters
All configuration options can be overriden by command-line options.Run puppet agent in foreground and verbose mode.
A very common option used when you want to see immediately the effect of a run.
It's actually the combination of: -onetime, -verbose, -ignorecache, -no-daemonize, -no-usecacheonfailure, -detailed-exit-codes, -no-splay, and -show_diff
puppet agent --test
Run puppet agent in foreground and debug modepuppet agent --test --debug
Run puppet without making any change to the systempuppet agent --test --noop
Run puppet using an environment different from the default onepuppet agent --environment testing
Wait for certificate approval (by default 120 seconds) in the first
RunUseful during automated first fime installation if PuppetMaster's autosign is false
puppet agent --test --waitforcert 120
Other configuration files:
auth.confDefines ACLs to access 's REST interface. Details
fileserver.conf
Used to manage ACL on files served from sources different than modules Details
puppetdb.conf
Settings for connection to PuppetDB, if used. Details
tagmail.conf , autosign.conf , device.conf , routes.yaml
These are other configuration files for specific functions. Details
Puppet Language
A Declarative Domain Specific Language ()Defines STATES (Not procedures)
code stays in manifests (files .pp)
Code contains resources that affects elements of the systme (file, package, service ...)
Resources are often grouped in classes which are generally organized in modules
Variables may be defined nodes and can be Facts (generated from the node) or User defined
On the Master are defined the resources or classes to include on the nodes (clients)
All the resources to apply on a node are defined in the catalog, generated by the Master
Resource Types (Types)
Resources are single units of configuration composed by:A type (package, service, file, user, mount, exec ...)
A title (how is called and referred)
One or more arguments
Example for a file resource type:type { 'title':
argument => value,
other_arg => value,
}
Complete Type Reference Online or at the command linefile { 'motd':
path => '/etc/motd',
content => 'Tomorrow is another day',
}
puppet describe file
Give a glance to code for the list of native
resource types:ls $(facter rubysitedir)/puppet/type
Simple samples of resources
Installation of OpenSSH packageCreation of /etc/motd filepackage { 'openssh':
ensure => present,
}
Start of httpd servicefile { 'motd':
path => '/etc/motd',
}
service { 'httpd':
ensure => running,
enable => true,
}
More Complex examples of resources
Installation of Apache package with the correct name for different OSManagement of nginx service with parameters defined in module's variablespackage { 'apache':
ensure => present,
name => $operatingsystem ? {
/(?i:Ubuntu|Debian|Mint)/ => 'apache2',
default => 'httpd',
}
}
Creation of nginx.conf with content retrived from different sources (first found is served)service { 'nginx':
ensure => $nginx::manage_service_ensure,
name => $nginx::service,
enable => $nginx::manage_service_enable,
}
file { 'nginx.conf':
ensure => present,
path => '/etc/nginx/nginx.conf',
source => [ "puppet:///modules/site/nginx/nginx.conf--${fqdn}",
"puppet:///modules/site/nginx/nginx.conf-${role}",
"puppet:///modules/site/nginx/nginx.conf" ],
}
}
Resource Abstraction Layer
Resources are abstracted from the underlining OSResource Types have different providers for different OS
Package type is known for the great number of providers
ls $(facter rubysitedir)/puppet/provider/package
Use puppet resource to interrogate the RAL:Or to directly modify resources:puppet resource user
puppet resource user root
puppet resource package
puppet resource service
puppet resource service httpd ensure=running enable=true
Classes
Classes are containers of different resources. Since 2.6 they can have parametersExample of a class definition:
Usage (declaration) of "old style" classea (without parameters):class mysql {
package { 'mysql-server':
ensure => present,
}
service { 'mysql':
ensure => running,
}
[...]
}
Even if a class is a singleton, you can include it multiple times: it's applied only once.
include mysql
Usage (declaration) of a parametrized classesYou can declare a parametrized class only once for a node
class { 'mysql':
required_param => 'my_value',
optional_param => 'dont_like_defaults',
}
Defines
Also called: Defined resource types or defined typesSimilar to parametrized classes but can be used multi times, with different parameters
Definition example:
Usage example (declaration):define apache::virtualhost (
$template = 'apache/virtualhost.conf.erb' ,
[...] ) {
file { "ApacheVirtualHost_${name}":
ensure => $ensure,
content => template("${template}"),
}
}
apache::virtualhost { 'www.example42.com':
template => 'site/apache/www.example42.com-erb'
}
Variables
You need them to provide different configurations for different kind of serversCan be provided by client nodes as facts
Facter runs on clients and collects facts that the server can use as variables
Or can be defined by usersal$ facter
architecture => x86_64
fqdn => Macante.example42.com
hostname => Macante
interfaces => lo0,eth0
ipaddress => 10.42.42.98
ipaddress_eth0 => 10.42.42.98
kernel => Linux
macaddress => 20:c9:d0:44:61:57
macaddress_eth0 => 20:c9:d0:44:61:57
memorytotal => 16.00 GB
netmask => 255.255.255.0
operatingsystem => Centos
operatingsystemrelease => 6.3
osfamily => RedHat
virtual => physical
User Variables
You can define custom variables in different ways:In manifests:
In an External Node Classifier ( DashBoard, the Foreman, Enterprise)$role = 'mail'
$package = $operatingsystem ? {
/(?i:Ubuntu|Debian|Mint)/ => 'apache2',
default => 'httpd',
}
In an Hiera backend
$syslog_server = hiera(syslog_server)
Nodes
A node is identified by the PuppetMaster by its hostname or certnameYou can decide what resources, classes and variables to assign to a node in 2 ways:
Using language ( Starting from /etc/manifests/site.pp )
Using an External Node Classifier (DashBoard, Foreman or custom scripts)node 'web01' {
include apache
}
When a client connects a PuppetMaster builds a catalog with all the resources to apply on the client
The catalog is in Pson format (a version of Json)
Modules
Self Contained and Distributable recipes contained in a directory with a predefined structureUsed to manage an application, system's resources, a local site or more complex structures
Modules must be placed in the Master's modulepath
module tool to interface with Modules Forgepuppet config print modulepath
/etc/puppet/modules:/usr/share/puppet/modules
GitHub, also, is full of modulespuppet help module
[...]
ACTIONS:
build Build a module release package.
changes Show modified files of an installed module.
generate Generate boilerplate for a new module.
install Install a module from the Puppet Forge or an archive.
list List installed modules
search Search the Puppet Forge for a module.
uninstall Uninstall a puppet module.
upgrade Upgrade a puppet module.
Paths of a module
Modules have a standard structure:This layout enables useful conventionsmysql/ # Main module directory
mysql/manifests/ # Manifests directory. Puppet code here. Required.
mysql/lib/ # Plugins directory. Ruby code here
mysql/templates/ # ERB Templates directory
mysql/files/ # Static files directory
mysql/spec/ # Puppet-rspec test directory
mysql/tests/ # Tests / Usage examples directory
mysql/Modulefile # Module's metadata descriptor
Modules paths conventions
Classes and defines autoloading:Provide files based on Erb Templates (Dynamic content)include mysql
# Main mysql class is placed in: $modulepath/mysql/manifests/init.pp
include mysql::server
# This class is defined in: $modulepath/mysql/manifests/server.pp
mysql::conf { ...}
# This define is defined in: $modulepath/mysql/manifests/conf.pp
include mysql::server::ha
# This class is defined in: $modulepath/mysql/manifests/server/ha.pp
Provide static files (Static content). Note you can use content OR source for the same file.content => template('mysql/my.cnf.erb'),
# Template is in: $modulepath/mysql/templates/my.cnf.erb
source => 'puppet:///modules/mysql/my.cnf'
# File is in: $modulepath/mysql/files/my.cnf
Erb templates
Files provisioned by can be Ruby ERB templatesIn a template all the variables (facts or user assigned) can be used :
But also more elaborated Ruby code# File managed by Puppet on <%= @fqdn %>
search <%= @domain %>
The computed template content is placed directly inside the catalog<% @dns_servers.each do |ns| %>
nameserver <%= ns %>
<% end %>
(Sourced files, instead, are retrieved from the puppetmaster during catalog application)
Principes behind a Reusable Module
Data SeparationReusability- Configuration data is defined outside the module (or even Puppet manifests)
- Module's behavior is managed via APIs
- Allow module's extension and override via external data
Standardization- Support different OS. Easily allow new additions.
- Customize behavior without changing module code
- Do not force author's idea on how configurations should be provided
Interoperability- Follow PuppetLabs style guidelines (puppet-lint)
- Have coherent, predictable and intuitive interfaces
- Provide contextual documentation (puppet-doc)
- Limit cross-module dependencies
- Allow easy modules' cherry picking
- Be self contained, do not interfere with other modules' resources
What's a Good Module anyway?
The most reusable and customizableThe one full of features
The one that works for you
The most essential, and optimized (but not reusable) one
The quickest one to do now
as usual... your mileage may vary
In 's world the concept of "Best Practices" is somehow fluid... :-)
(It follows the language's features evolution and the blog post of the moment...)
Modules documentation with Puppet Doc
Puppetdoc generates documentation from manifests comments:Comment classes as below:$ puppetdoc [--all] --mode rdoc [--outputdir ] [--debug|--verbose] [--trace]
[--modulepath ] [--manifestdir ] [--config ]
# Class: apache
#
# This module manages Apache
#
# Parameters:
#
# Actions:
#
# Requires:
#
# [Remember: No empty lines between comments and class definition]
class apache {
...
}