You are on page 1of 31

Puppet Basic Concepts

Martha Greenberg

11/25/15

Why do we need Configuration Management?


We have 90 servers currently, and growing.
This is too many for anyone to know what is on each system.
We need to be able to replace a server if it dies or to be able to add
another server that is exactly like it.
We need to ensure that all our servers are configured the same.
We need a better way to push out changes to all the servers that need a
particular change.
We want to stop duplicating effort.

What is Puppet?
Puppet is:
a declarative language for expressing system configuration.
a client and server for distributing it.
a library for realizing the configuration.
Puppet is an abstraction layer between the system administration and the
system.
Puppet is written in Ruby and distributed under the GPL.

How Puppet Works


Client (Agent) - puppetd
Server - puppetmasterd
The client connects to the server every half an hour.
The server compiles the configuration for the client (based on what you
write) and sends it to the client.
The client checks the configuration it receives (or a cached version if it
can't contact the server) against what is really on the machine and
tries to fix whatever is wrong.
Client (node) configuration can be stored in LDAP, in a database or in the
puppet configuration files.

Puppet Components

Why Puppet?
Puppet supports all of the operating systems that we are using, as well as
those that we may use in the future.
Puppet comes the closest (of the currently available tools) to how we
already think about our configurations.
Puppet uses SSL to securely communicate between the client and server.
Puppet has a large and active user community and is being actively
developed and supported.

What Puppet Needs


ruby
facter
puppet

What is Facter?
Facter gathers information about the client, which can be used as
variables within puppet.
You can add custom facts as needed.
case $operatingsystem {
freebsd: {
$rootgroup = "wheel"
}
default: {
$rootgroup = "root"
}
}

Example Facts
debiantest:~# facter
architecture => i386
debianversion => etch
domain => example.com
facterversion => 1.3.8
fqdn => debiantest.example.com
hardwareisa => unknown
hardwaremodel => i686
hostname => debiantest
id => root
ipaddress => 192.168.1.41
ipaddress_eth0 => 192.168.1.41
kernel => Linux
kernelrelease => 2.6.18-4-686
macaddress => 00:0C:29:DC:FC:D9
macaddress_eth0 => 00:0C:29:DC:FC:D9
manufacturer => VMware, Inc.

Example Facts continued


memoryfree => 214.37 MB
memorysize => 250.95 MB
operatingsystem => Debian
operatingsystemrelease => 2.6.18-4-686
processor0 => Intel(R) Xeon(TM) CPU 3.06GHz
processorcount => 1
productname => VMware Virtual Platform
ps => ps -ef
puppetversion => 0.23.2
rubysitedir => /usr/local/lib/site_ruby/1.8
rubyversion => 1.8.5
serialnumber => VMware-56 4d 99 87 23 bb 5e 0e-bb 1e
e8 75 32 dc fc d9
swapfree => 235.29 MB
swapsize => 235.29 MB
uniqueid => 00000000

What Can Puppet Do?


Puppet manages objects on the client, called resources.
Resources are come in different types. Some of the types are:
cron
exec
file
group
host
mailalias
package
service
user

Types and Providers


Types are implemented by providers.
Puppet automatically figures out which provider to use on which platform.
For example, package management is done with apt-get by default on
debian, but by up2date on redhat.
You can override the type if you want.

Getting Started
Install puppet (and facter and ruby).
Set up the server (puppetmasterd).
Write a manifest for your node and upload it to the server.
Start puppetmasterd on the server.
Run puppetd on the node.

What is a Node?
A configuration block matching a client
Can contain types, classes
default node matches any client without a node block

What is a Manifest?
Manifest are recipes that Puppet uses to build the client configuration.
Let's create a simple manifest:
class bacula-client {}
node debiantest {
include bacula-client
}
This creates a class called bacula-client, and node (puppet client) called
debiantest which includes that class. Of course, it doesn't do anything
yet.

A More Useful Class


class bacula-client {
package { "bacula-client": ensure => present; }
service { "bacula-fd":
ensure => running,
enable => true,
}
file {"/etc/bacula/bacula-fd.conf":
mode
=> "644",
owner
=> "root",
group
=> "root",
ensure => present,
content => template("bacula/bacula-fd.conf"),
}
}

What about FreeBSD?


case $operatingsystem {
freebsd: {
$rootgroup = "wheel"
$baculadir = "/usr/local/etc"
}
default: {
$rootgroup = "root"
$baculadir = "/etc/bacula"
}
}
file {"$baculadir/bacula-fd.conf":
mode
=> "644",
owner
=> "root",
group
=> $rootgroup,
ensure => present,
notify => Service[bacula-fd],
content => template("bacula/bacula-fd.conf"),
require => Package["bacula-client"],

Templates
class apache2 {
define simple-vhost ( $admin = "webmaster",
$aliases, $docroot) {
file { "/etc/apache2/sites-available/$name":
mode
=> "644",
require => [ Package["apache2"],
Package["cronolog"], Service["apache2"] ],
content => template("apache/vhost.conf"),
}
}
}
node debiantest {
include apache2
apache2::simple-vhost { "debian.example.com":
admin => "system@example.com", aliases =>
[ debiantest.examplet.com], ["debian" ],
docroot => "/var/www/debian"}
}

vhost.conf Template
Puppet uses Ruby's ERB template system:
<VirtualHost *>
ServerAdmin
<%= admin %>
DocumentRoot
<%= docroot %>
ServerName
<%= name %>
<% aliases.each do |al| -%>
ServerAlias
<%= al %>
<% end -%>
ErrorLog "|/usr/bin/cronolog
/var/log/apache/<%= name %>/%Y-%m/error-%d"
CustomLog "|/usr/bin/cronolog
/var/log/apache/<%= name %>/%Y-%m/access %d" sane
</VirtualHost>

Template Output
# more /etc/apache2/sites-available/debian.example.com
<VirtualHost *>
ServerAdmin
system@example.com
DocumentRoot
/var/www/debian
ServerName
debian.example.com
ServerAlias
debiantest.example.com
ServerAlias
debian
ErrorLog "|/usr/bin/cronolog
/var/log/apache/debian.example.com/%Y-%m/error-%d"
CustomLog "|/usr/bin/cronolog
/var/log/apache/debian.example.com/%Y-%m/access-%d"
sane
</VirtualHost>

Classes and Definitions


Classes are groups of resources.
Definitions are similar to classes, but they can be instantiated multiple
times with different arguments on the same node.
class apache2 {
define simple-vhost ( $admin = "webmaster",
$aliases, $docroot) {
file { "/etc/apache2/sites-available/$name":
mode
=> "644",
require => [ Package["apache2"],
Service["apache2"] ],
content => template("apache/vhost.conf"),
} } }
node debiantest {
include apache2
apache2::simple-vhost { "debian.example.com":
docroot => "/var/www/debian"}
apache2::simple-vhost { "test.example.com":
docroot => "/var/www/test"}
}

Dependencies
Dependencies allow you specify the order objects will be applied. For
example, you don't want to try to put a file in /etc/apache2 if apache2
is not installed yet.
class apache2 {
define simple-vhost ( $admin = "webmaster",
$aliases, $docroot) {
file { "/etc/apache2/sites-available/$name":
mode
=> "644",
require => [ Package["apache2"],
Service["apache2"] ],
content => template("apache/vhost.conf"),
}
}
}

Notify, Subscribe and Exec


Let us make sure mail to postmaster goes to root and run newaliases
when we update this:
mailalias { "postmaster":
ensure
=> present,
recipient => "root",
notify
=> Exec["newaliases"],
}
exec { "newaliases":
path
=> ["/usr/bin", "/usr/sbin"],
refreshonly => true,
}
On the other hand, we can tell puppet that a service should be restarted
when a file changes:
service { "nrpe":
ensure
=> running,
enable
=> true,
subscribe => File["/etc/nagios/nrpe.cfg"];
}

Inheritance
Puppet types can inherit from similar types and override if needed:
class bacula-client {
package { "bacula-client": ensure => present; }
service { "bacula-fd": ensure => running, enable =>
true, }
file {"/etc/bacula/bacula-fd.conf":
mode
=> "644",
content => template("bacula/bacula-fd.conf"),
}
}
class bacula-special inherits bacula-client {
File[/etc/bacula/bacula-fd.conf] {
content => template("bacula/bacula-fd.confspecial"),
}
}
A node that includes bacula-special will also have the package installed
and the service running, but /etc/bacula/bacula-fd.conf will be taken
from the second template.

Modules
Modules allow you to group both the logic and the files for an application
together.
Puppet automatically searches its module path to find modules.
Modules can contain four types of files, each of which must be stored in a
separate subdirectory:
Manifests - must be stored in manifests/, and if you create
manifests/init.pp then that file will be loaded if you import the
module name directly, e.g. import "mymodule".
Templates - must be stored in templates/, and the module name must
be added to the template name:
template("mymodule/mytemplate.erb")
Files - stored in files/, these are available from the file server under
modules/<module name>/files/<file name>.
Plugins additional types, providers or facts.

Fileserver & Filebucket


Puppet also includes a file server which you can use for transferring files
from the server to the client.
If you configure it, puppet can also save a backup of each file that is
changed on the client to the server. The backups go in a filebucket
and can be retrieved later.

Client Install on Debian Linux


debiantest:~# cat >> /etc/apt/sources.list:
deb http://debian.example.com etch main
^D
debiantest:~# aptitude update
debiantest:~# aptitude install puppet

Client Install continued

New Workflow

Advanced Topics
Tags
Reports
CA
SSL issues

Questions?

You might also like