SlideShare a Scribd company logo
Puppet { ‘basic’: }
Daehyung Lee <daehyung@gmail.com>
Configuration Management Advantage
• Infrastructure as Code
Track, Test, Deploy, Reproduce, Scale
• Reproducible setups
• Scale quickly
Done for one, use on many
• Aligned Environments
for development, testing, QA, production nodes
• Alternatives CM toolkit
Chef, CFEngine, SaltStack, Ansible
About Puppet
• The industry-leading configuration management
toolkit
• An open source IT Management tool written in Ruby
• Coding style is simular to Nagios
• Influenced by CFEngine
• Supports various OS
• Linux, Unix, OS X, Windows(>= 2.7)
Puppet Language
• DSL(Declarative Domain Specific Language)
• Defines STATES (Not procedure)
• Resources, Classes, and Nodes
Declaring resources(file, package, service, ...)
Groups of resources are organised in classes
A class may describe everything needed to configure an entire
service or application
Nodes that serve different roles will generally get different sets
of classes
How Puppet works
Every node checks in with a
puppet master
Do I look the way I'm supposed to look
I'm Puppet master
Lifecycle of a Puppet Run
1. Facts
The node sends data about its state to
the puppet master server.
2. Catalog
Puppet uses the facts to compile a
Catalog that specifies how the node
should be configured.
3. Report
Configuration changes are reported
back to the Puppet Master.
4. Report
Puppet's open API can also send data
to 3rd party tools.
Catalog
• Static documents which contain resources and
relationships
• Ruby object in memory
• Transmitted as JSON and persisted to disk as
YAML
• Agent nodes cache their most recent catalog
if the master fails compilation, re-use cached one.
Resource Abstraction Layer
types providers
ubuntu
SLES
macosx
Windows
user
file
package
service
exec
mount
group
host
RHEL
CentOS
Resource declaration
• file: The resource type
• ntp.conf: The title
• path: An attribute
• '/etc/ntp.conf': A value; in this case, a string
• template('ntp/ntp.conf'): A function call that returns a value; in this case, the
template function, with the name of a template in a module as its argument
file {'ntp.conf':
ensure => file,
path => '/etc/ntp.conf',
content => template('ntp/ntp.conf'),
owner => 'root',
mode => '0644',
}
Relationship meta-parameters
• before: Causes a resource to be applied before the target resource.
• require: Causes a resource to be applied after the target resource.
• notify: Causes a resource to be applied before the target resource. The target
resource will refresh if the notifying resource changes.
• subscribe: Causes a resource to be applied after the target resource. The
subscribing resource will refresh if the target resource changes.
package {'ntp':
ensure => installed,
before => File['ntp.conf'],
}
service {'ntpd':
ensure => running,
subscribe => File['ntp.conf'],
}
Package['ntp']
Service['ntpd']
monitor
Chaining Arrows
• -> (ordering arrow):
Causes the resource on the left to be applied before the resource on
the right. Written with a hyphen and a greater-than sign.
• ~> (notification arrow):
Causes the resource on the left to be applied first, and sends a refresh
event to the resource on the right if the left resource changes. Written
with a tilde and a greater-than sign.
Package['ntp'] -> File['ntp.conf'] ~> Service['ntpd']
File['ntp.conf'] Service['ntpd']Package['ntp']
Changed
Do restart
12
Data types
Boolean, Undef
• Boolean
• true
all other strings, including “false"
all numbers, including 0 and negative numbers
array, hash event though it's empty
any resource references
false
undef
• Undef
nil in Ruby
Strings
• Strings
single-quoted strings
double-quoted strings
Escape sequences
Good: 'C:Program Files(x86)'
Bad: 'C:Program Files(x86)'
path => "${apache::root}/${apache::vhostdir}/${name}",
$ — literal dollar sign " — literal double quote
' — literal single quote  — single backslash
n — newline r — carriage return
t — tab s — space
Numbers
• Numbers
$some_number = 8 * -7.992
$another_number = $some_number / 4
$product = 8 * +4 # syntax error
$product = 8 * 4 # OK
$product = 8 * .12 # syntax error
$product = 8 * 0.12 # OK
Arrays, Hashes
• Arrays
• Hashes
[ 'one', 'two', 'three' ] or [ 'one', 'two', 'three', ]
$foo = [ 'one', 'two', 'three' ]
notice( $foo[1] ) # one
notice( $foo[-2] ) # two
{ key1 => 'a', key2 => 'b' } or { key1 => 'a', key2 => 'b', }
$mysite = { port => 80,
server_name => { mirror0 => 'www.example.com',
mirror1 => 'abc.example.com' }
}
notice( $mysite[port] ) # 80
notice( $mysite[server_name][mirror1] ) # abc.example.com
Resource References
• Resource References
# A reference to a file resource:
subscribe =>
# A type with a multi-segment name:
before =>
# A multi-resource reference:
require => File['/etc/apache2/httpd.conf',
'/etc/apache2/magic', '/etc/apache2/mime.types'],
# An equivalent multi-resource reference:
$my_files = ['/etc/apache2/httpd.conf', '/etc/apache2/magic',
'/etc/apache2/mime.types']
require => File[$my_files]
Concat::Fragment['apache_port_header'],
File['/etc/ntp.conf'],
18
Types
Types
▪ http://docs.puppetlabs.com/puppet_core_types_cheatsheet.pdf
▪ http://docs.puppetlabs.com/references/3.8.latest/type.html
stage
filebucket
mcx
exec
schedule_task
notify
router
ssh_authorized_key
selboolean
file
mount
cronaugeas computer
resources
host
schedule
mailaliasmaillistmacauthorization
interface
k5login
service
sshkey
package
stage tidy user vlan yumrepo
zfs zone zpool nagios_*
Core Types - File
file {
}
title :
ensure =>
path =>
owner =>
group =>
mode =>
content =>
source =>
target =>
recurse =>
puppet:///modules/some_module/somefile,
template('some_module/somefile.erb'),
present | absent |file | directory | link ,
eg) '/etc/inetd.conf',
eg) 'root',
eg) 'root',
eg) '0644',
eg) '/etc/inet/inetd.conf',
true | false ,
'initd.conf':
Core Types - Package
package {
}
title :
ensure =>
source =>
present | latest | {version} | absent | purged,
eg) /tmp/abcpkg-1.1.rpm
eg) 'abcpkg':
Core Types - Service
service {
}
title :
ensure =>
enable =>
name =>
status =>
start =>
stop =>
restart =>
hasrestart =>
hasstatus =>
running | stopped ,
true | false ,
defaults to title
true | false,
true | false,
Manually specified commands for working
around bad init scripts
use stop+start instead of restart
use grepping process table instead of
status
eg) 'httpd':
Core Types - notify
notify {
}
title :
message => defaults to title
eg) 'This message is getting logged':
Core Types - exec
exec {
}
title :
command =>
path =>
refreshonly =>
onlyif =>
unless =>
The command to run; defaults to title
eg) ['bin', 'sbin', '/usr/bin', '/usr/sbin'],
true | false
only run, the result of this command is non-zero
eg) 'run-something':
only run as notified
only run, the result of this command is zero
Core Types - cron
cron {
}
title :
command =>
user =>
hour =>
minute =>
ensure =>
The command to run
eg) 'root',
eg) 2,
eg) 'logrotate':
eg) 2,
present | absent,
Core Types - user
user {
}
title :
uid =>
gid =>
shell =>
home =>
ensure =>
eg) '507',
eg) 'admin', or '10000',
eg) '/bin/bash',
eg) 'dave':
eg) '/home/dave',
present | absent,
managehome => true | false,
if it's false, you need to create user's home directory
manually.
Core Types - group
group {
}
title :
gid =>
ensure =>
eg) '10000',
eg) 'admin':
present | absent,
name => defaults to title
Variable
• prefixed with a $(dollar sign)
• any kind of data types can be assigned
$www_base_path = "/var/www"
file { "${www_base_path}/site":
ensure => directory,
}
$ssh_users = [ 'myself', 'someone' ]
class test {
$ssh_users += [ 'someone_else' ]
}
Interpolation
Appending Assignment
(Allow strings, arrays, hashes)
Facter/Facts
• Facter
• Puppet's cross-platform system profiling library
• Discovers and reports per-node facts which are
available in you Puppet manifests as variables
• Facts
Facts appears in Puppet as normal top-scope
variables
$ facter -p
Facts
http://docs.puppetlabs.com/facter/2.4/core_facts.html#summary
interfaces
facterversion
ipaddress
dhcp_servers
uptime
iphostnumber
kernelrelease
domain
lsb*
ec2_*
ipaddress6
blockdevicesarchitecture augeasversion
kernelmajorversion
filesystems
rsc_*
idhostnamehardwaremodel
fqdn
hardwareisa
macaddress
is_virtual
kernel
macosx manufacturer memory netmask network
operatingsystem* os osfamily partitions xendomains
and more...
Core Facts
architecture eg) x86_64
domain eg) example.com
fqdn eg) node01.example.com
filesystem eg) ext4, iso9660
hostname eg) node01
ipaddress eg) 10.0.2.15
kernelrelease eg) 2.6.32-504.8.1.el6.x86_64
memorysize eg) 458.39 MB
osfamily eg) RedHat
Custom fact
• You can extend facter by writing ruby code
• http://docs.puppetlabs.com/facter/2.4/custom_facts.
html
Facter.add(:rubypath) do
setcode 'which ruby'
end
Facter.add(:rubypath) do
confine :osfamily => "Windows"
# Windows uses 'where' instead of 'which'
setcode 'where ruby'
end
External Facts
• fact location
/etc/facter/facts.d
• Adding external facts
$ echo "application_tier=dev" > /etc/facter/facts.d/app.txt
$ facter application_tier
dev
$ cat <<EOF > /etc/facter/facts.d/mydata.yaml
yamlkey:
- hello
- world
EOF
$ facter yamlkey
["hello", "world"]
34
Conditional Statements
Conditional Statements
• booleans
$x = 1
$y = 2
($x == $y)
($x > $y)
($x < $y)
($x != $y)
($x < $y) and !($x < $y)
Conditional Statements
• Booleans • Arithmetic
$x = 1
$y = 2
($x == $y)
($x > $y)
($x < $y)
($x != $y)
($x < $y) and !($x < $y)
$x = 1
$y = 2
$x + $x == $y # true
$x - $x # 0
$y / 2 # 1
Conditional Statements
• if/elsif/else
• unless
if str2bool("$is_virtual") {
warning('Not work on virtual machine')
} elsif $::operatingsystem == 'Darwin' {
warning('Not support yet')
} else {
include ntp
}
unless $::memorysize > 1024 {
$maxclient = 500
}
Conditional Statements
• case
• selector
case $::hostname {
/^www/: { include apache }
/^dns/: { include bind }
/^mx[1-2]/: { include mx }
default: { include base }
}
$rootgroup = $::osfamily ? {
'Solaris' => 'wheel',
/(Darwin|FreeBSD)/ => 'wheel',
default => 'root',
}
Conditional Statements
• in
if $::hostname in [ 'www', 'web' ] {
service { 'httpd' :
ensure => true
}
}
40
Templates
» Documents that combine code, data, and literal text
to produce a final rendered output.
» The goal of a template is to manage a complicated
piece of text with simple inputs.
41
Template Syntax
<% Ruby codes %>
<%= Ruby expression %>
<%# comment %>
<% if @ssl -%>
## SSL directives
SSLEngine on
SSLCertificateFile <%= @ssl_cert %>
SSLCertificateKeyFile <%= @ssl_key %>
<% if @ssl_chain -%>
SSLCertificateChainFile <%= @ssl_chain %>
<% end -%>
No newline
42
Templates - iteration
# ntp/init.pp
$nameservers = [ ‘ns1.example.com’,
‘ns2.example.com’,
‘ns3.example.com’ ]
$searchdomains = [ ‘inside.example.com’,
‘outside.example.com’,
‘under.example.com’]
file {“resolvconf”:
path => “/etc/resolv.conf”,
mode => ‘0644’,
owner => root,
group => root,
content => template('resolvconf.erb')
}
# /etc/puppet/manifests/resolv.conf.erb
# resolv.conf build by Puppet
domain <%= @domain %>
search <% @searchdomains.each do |domain| -%>
<%= domain -%><% end -%> <%= @domain %>
<% @nameservers.each do |server| -%>
nameserver <%= server %>
<% end -%>
/etc/resolv.conf
# resolv.conf build by Puppet
domain example.com
search inside.example.com outside.com under.example.com example.com
nameserver ns1.example.com
nameserver ns2.example.com
nameserver ns3.example.com
43
inline_template
$day_of_week = inline_template("<%= Time.now.gmtime.wday %>”)
if $day_of_week ==0 {
exec { ‘Do Monday task’ :
# do something
}
} else {
exec { ‘Do rest of days task’ :
# do something else
}
}
44
Classes
Classes
• Named blocks of Puppet code, Stored in module
# A class with no parameters
class base::linux {
file { '/etc/passwd':
owner => 'root',
group => 'root',
mode => '0644',
}
file { '/etc/shadow':
owner => 'root',
group => 'root',
mode => '0440',
}
}
class
Type
Attribute
Type
Attribute
$variable
include other class
Defining class
• Class[‘apache’]
class apache {
package { ‘httpd’: ensure => latest }
service { ‘httpd’: ensure => running }
file { '/etc/httpd/conf': ensure => directory }
file { '/etc/httpd/conf/httpd.conf':
ensure => file,
require => [ Package['httpd'], File['/etc/httpd.conf'], ],
notify => Service['httpd'],
}
}
Looks OK, but Is it work on Debian?
Parameterized class
• Class[‘apache’]
class apache (
$package = ‘httpd’,
$service = ‘httpd’ ){
package { $package: ensure => latest }
service { $service : ensure => running }
…
}
# tests/debian.pp
class { ‘apache’
package => ‘apache2’,
service => ‘apache2’,
}
# tests/redhat.pp
class { ‘apache’ : }
# or
include apache
Params class
• Class[‘apache::params’]
class apache::params {
case $::osfamily {
'RedHat': {
$package = 'httpd'
$service = ‘httpd’
…
}
'Debian': {
$package = 'apache2'
$service = ‘apache2’
…
}
}
}
How to use it? The answer is inheritance
Class Inheritance
• Use inherits keyword
class test::parent {
$var = "parent"
notice("var in parent is ",$var)
}
class test::child inherits test::parent {
$var = "child"
notice("var in child is ",$var)
}
class test::nephew {
notice( "var in nephew is", $var)
}
[root@localhost modules]#
tree test/
test/
├── manifests
│ ├── child.pp
│ ├── init.pp
│ ├── nephew.pp
│ └── parent.pp
└── tests
└── inherits.pp
# manifests/init.pp
class test{
include test::child
include test::nephew
}
# tests/inherits.pp
include test[root@localhost test]# puppet apply tests/inherits.pp
Notice: Scope(Class[Test::Parent]): var in parent is parent
Notice: Scope(Class[Test::Child]): var in child is child
Notice: Scope(Class[Test::Nephew]): var in nephew is
Notice: Compiled catalog for localhost in environment production in 0.06
seconds
Notice: Finished catalog run in 0.01 seconds
Using params class
• Class[‘apache’]
class apache (
$package = $apache::params::package,
$service = $apache::params::service
) inherits apache::params {
package { $package: ensure => latest }
service { $service : ensure => running }
…
}
# tests/apache.pp
include apache
Use inheritance,
If you want to override some parent’s variables
or using params class
Declaring class
• include
standard way to declare classes
• require
become a dependency of the surrounding container
• contain (>= Puppet 3.4)
http://docs.puppetlabs.com/puppet/3.7/reference/lang_containm
ent.html#containing-classes
include-like behavior
-> multiple declaration is OK
class web {
}
include apache
include apache
include apache
include apache
class web {
}
class { ‘apache’: }
include apache
Declaring class
• class
Only way to declare parameterized classes
Resource-like behavior
-> Only one declaration is OK
# tests/debian.pp
class { ‘apache’
package => ‘apache2’,
service => ‘apache2’,
}
class web {
}
include apache
class { ‘apache’: }
include apache
53
Define
Define
• Can be evaluated multiple times with different
parameters
• Once defined, acts like a new resource type
class apache::vhost ($docroot, $server_name, $server_admin) {
include apache # contains Package['httpd'] and Service['httpd']
include apache::params # contains common config settings
$vhost_dir = $apache::params::vhost_dir
file { "${vhost_dir}/${server_name}.conf":
content => template('apache/vhost-default.conf.erb'),
owner => 'www',
group => 'www',
mode => '0644',
require => Package['httpd'],
notify => Service['httpd'],
}
}
# tests/vhosts.pp
class { 'apache::vhost':
docroot => '/var/www/html',
server_name => 'www01.abc.com',
server_admin => 'sysadmin@abc.com',
}
class { 'apache::vhost':
docroot => '/var/www/html',
server_name => 'www02.abc.com',
server_admin => 'sysadmin@abc.com',
}
[root@localhost apache]# puppet apply tests/http.pp
Error: Duplicate declaration: Class[Apache::Vhost] is already declared in file
/etc/puppet/modules/apache/tests/http.pp:5; cannot redeclare at
/etc/puppet/modules/apache/tests/http.pp:11 on node localhost
Error: Duplicate declaration: Class[Apache::Vhost] is already declared in file
/etc/puppet/modules/apache/tests/http.pp:5; cannot redeclare at
/etc/puppet/modules/apache/tests/http.pp:11 on node localhost
Define
define apache::vhost2($docroot, $servername = $title, $server_admin) {
include apache # contains Package['httpd'] and Service['httpd']
include apache::params # contains common config settings
$vhost_dir = $apache::params::vhost_dir
file { "${vhost_dir}/${server_name}.conf":
content => template('apache/vhost-default.conf.erb'),
owner => 'www',
group => 'www',
mode => '0644',
require => Package['httpd'],
notify => Service['httpd'],
}
}
# tests/define.pp
apache::vhost2 { 'www01.abc.com':
docroot => '/var/www/html',
server_admin => 'sysadmin@abc.com',
}
apache::vhost2 { 'www02.abc.com':
docroot => '/var/www/html',
server_name => 'www02.abc.com',
server_admin => 'sysadmin@abc.com',
}
[root@localhost apache]# puppet apply tests/define.pp
Notice: Compiled catalog for localhost in environment production in 0.28 seconds
Notice:
/Stage[main]/Main/Apache::Vhost2[www02.abc.com]/File[/etc/httpd/conf.d/www02.ab
c.com.conf]/ensure: defined content as '{md5}39cab336c208f334fde6b07ef8c33445'
Notice: /Stage[main]/Apache/Service[httpd]: Triggered 'refresh' from 1 events
Notice: Finished catalog run in 0.78 seconds
functions
• Pre-defined chunks of Ruby code
• Runs during compilation time
• http://docs.puppetlabs.com/references/3.7.latest/function.html
• https://forge.puppetlabs.com/puppetlabs/stdlib
template eg) template('apache/vhost-default.conf.erb'),
str2bool eg) $_result = str2bool($::is_virtual)
fail eg) fail('$server_name is needed')
alert eg) alert('$server_name is empty, it’s filled with $title')
notice eg) notice( "var in parent is", $var)
Scope
# /etc/puppet/modules/scope_example/manifests/init.pp
class scope_example {
$variable = "Hi!"
notify {"Message from here: $variable":}
notify {"Node scope: $node_variable Top scope: $top_variable":}
}
# /etc/puppet/manifests/site.pp
$top_variable = "Available!"
node 'puppet.example.com' {
$node_variable = "Available!"
include scope_example
notify {"Message from node scope: $variable":}
}
notify {"Message from top scope: $variable":}
$ puppet apply site.pp
notice: Message from here: Hi!
notice: Node scope: Available! Top scope: Available!
notice: Message from node scope:
notice: Message from top scope:
58
namespace
» Class and defined type names may be broken up
into segments
» Separated by double colon(::)
» analogous to the / [slash] in a file path.
class apache { ... }
class apache::mod { ... }
class apache::mod::passenger { ... }
define apache::vhost { ... }
apache <modulepath>/apache/manifests/init.pp
apache::mod <modulepath>/apache/manifests/mod.pp
apache::mod::passenger <modulepath>/apache/manifests/mod/passenger.pp
module
• Collection of manifests, resources, files, templates,
classes, and definitions.
• Can download pre-built modules from the Puppet
forge - http://forge.puppetlabs.com
$ puppet module generate daehyung-amodule
$ tree daehyung-amodule/
daehyung-amodule/
|-- Modulefile
|-- README
|-- manifests
| `-- init.pp
|-- spec
| `-- spec_helper.rb
`-- tests
`-- init.pp
foo/
|-- manifests
| |-- config.pp
| |-- defaults.pp
| |-- init.pp
| |-- install.pp
| `-- service.pp
|-- templates
| `-- foo-conf.erb
`-- tests
`-- init.pp
installing / uninstalling module
https://docs.puppetlabs.com/puppet/latest/referen
ce/modules_installing.html
puppet man module
puppet module list
puppet module search r10k
puppet module install zack/r10k --version 2.6.5
puppet module install zack-r10k-2.6.5.tar.gz --ignore-dependencies
puppet module upgrade zack/r10k --version 3.1.1
puppet module uninstall zack/r10k
61
Keep this in mind
• Make a new module for you or company?
• Search from Puppet Forge first!
• The simple answer is NO!!!
Not mentioned in here
• ENC
• Hiera
• Environments
• r10k
• etc.
• too many, I’m still learning it ;)
Demo
Simple wordpress server
63
Roles & Profiles
• Implementation layer
(Profiles)
Includes regular classes
Might add resources directly
create_resources call
• Business layer (Roles)
Only includes profiles
No logic at all
One server - One role
Installation
• Debian OS family
[Client] sudo apt-get install puppet
[Server] sudo apt-get install puppetmaster
• RedHat OS family
Register EPEL or puppetlabs' repository
• # rpm -ivh http://yum.puppetlabs.com/el/6/ 
products/x86_64/puppetlabs-release-6-11.noarch.rpm
• [Client] yum install puppet
• [Server] yum install puppet-server
Any Questions?

More Related Content

Learning Puppet basic thing

  • 1. Puppet { ‘basic’: } Daehyung Lee <daehyung@gmail.com>
  • 2. Configuration Management Advantage • Infrastructure as Code Track, Test, Deploy, Reproduce, Scale • Reproducible setups • Scale quickly Done for one, use on many • Aligned Environments for development, testing, QA, production nodes • Alternatives CM toolkit Chef, CFEngine, SaltStack, Ansible
  • 3. About Puppet • The industry-leading configuration management toolkit • An open source IT Management tool written in Ruby • Coding style is simular to Nagios • Influenced by CFEngine • Supports various OS • Linux, Unix, OS X, Windows(>= 2.7)
  • 4. Puppet Language • DSL(Declarative Domain Specific Language) • Defines STATES (Not procedure) • Resources, Classes, and Nodes Declaring resources(file, package, service, ...) Groups of resources are organised in classes A class may describe everything needed to configure an entire service or application Nodes that serve different roles will generally get different sets of classes
  • 5. How Puppet works Every node checks in with a puppet master Do I look the way I'm supposed to look I'm Puppet master
  • 6. Lifecycle of a Puppet Run 1. Facts The node sends data about its state to the puppet master server. 2. Catalog Puppet uses the facts to compile a Catalog that specifies how the node should be configured. 3. Report Configuration changes are reported back to the Puppet Master. 4. Report Puppet's open API can also send data to 3rd party tools.
  • 7. Catalog • Static documents which contain resources and relationships • Ruby object in memory • Transmitted as JSON and persisted to disk as YAML • Agent nodes cache their most recent catalog if the master fails compilation, re-use cached one.
  • 8. Resource Abstraction Layer types providers ubuntu SLES macosx Windows user file package service exec mount group host RHEL CentOS
  • 9. Resource declaration • file: The resource type • ntp.conf: The title • path: An attribute • '/etc/ntp.conf': A value; in this case, a string • template('ntp/ntp.conf'): A function call that returns a value; in this case, the template function, with the name of a template in a module as its argument file {'ntp.conf': ensure => file, path => '/etc/ntp.conf', content => template('ntp/ntp.conf'), owner => 'root', mode => '0644', }
  • 10. Relationship meta-parameters • before: Causes a resource to be applied before the target resource. • require: Causes a resource to be applied after the target resource. • notify: Causes a resource to be applied before the target resource. The target resource will refresh if the notifying resource changes. • subscribe: Causes a resource to be applied after the target resource. The subscribing resource will refresh if the target resource changes. package {'ntp': ensure => installed, before => File['ntp.conf'], } service {'ntpd': ensure => running, subscribe => File['ntp.conf'], } Package['ntp'] Service['ntpd'] monitor
  • 11. Chaining Arrows • -> (ordering arrow): Causes the resource on the left to be applied before the resource on the right. Written with a hyphen and a greater-than sign. • ~> (notification arrow): Causes the resource on the left to be applied first, and sends a refresh event to the resource on the right if the left resource changes. Written with a tilde and a greater-than sign. Package['ntp'] -> File['ntp.conf'] ~> Service['ntpd'] File['ntp.conf'] Service['ntpd']Package['ntp'] Changed Do restart
  • 13. Boolean, Undef • Boolean • true all other strings, including “false" all numbers, including 0 and negative numbers array, hash event though it's empty any resource references false undef • Undef nil in Ruby
  • 14. Strings • Strings single-quoted strings double-quoted strings Escape sequences Good: 'C:Program Files(x86)' Bad: 'C:Program Files(x86)' path => "${apache::root}/${apache::vhostdir}/${name}", $ — literal dollar sign " — literal double quote ' — literal single quote — single backslash n — newline r — carriage return t — tab s — space
  • 15. Numbers • Numbers $some_number = 8 * -7.992 $another_number = $some_number / 4 $product = 8 * +4 # syntax error $product = 8 * 4 # OK $product = 8 * .12 # syntax error $product = 8 * 0.12 # OK
  • 16. Arrays, Hashes • Arrays • Hashes [ 'one', 'two', 'three' ] or [ 'one', 'two', 'three', ] $foo = [ 'one', 'two', 'three' ] notice( $foo[1] ) # one notice( $foo[-2] ) # two { key1 => 'a', key2 => 'b' } or { key1 => 'a', key2 => 'b', } $mysite = { port => 80, server_name => { mirror0 => 'www.example.com', mirror1 => 'abc.example.com' } } notice( $mysite[port] ) # 80 notice( $mysite[server_name][mirror1] ) # abc.example.com
  • 17. Resource References • Resource References # A reference to a file resource: subscribe => # A type with a multi-segment name: before => # A multi-resource reference: require => File['/etc/apache2/httpd.conf', '/etc/apache2/magic', '/etc/apache2/mime.types'], # An equivalent multi-resource reference: $my_files = ['/etc/apache2/httpd.conf', '/etc/apache2/magic', '/etc/apache2/mime.types'] require => File[$my_files] Concat::Fragment['apache_port_header'], File['/etc/ntp.conf'],
  • 19. Types ▪ http://docs.puppetlabs.com/puppet_core_types_cheatsheet.pdf ▪ http://docs.puppetlabs.com/references/3.8.latest/type.html stage filebucket mcx exec schedule_task notify router ssh_authorized_key selboolean file mount cronaugeas computer resources host schedule mailaliasmaillistmacauthorization interface k5login service sshkey package stage tidy user vlan yumrepo zfs zone zpool nagios_*
  • 20. Core Types - File file { } title : ensure => path => owner => group => mode => content => source => target => recurse => puppet:///modules/some_module/somefile, template('some_module/somefile.erb'), present | absent |file | directory | link , eg) '/etc/inetd.conf', eg) 'root', eg) 'root', eg) '0644', eg) '/etc/inet/inetd.conf', true | false , 'initd.conf':
  • 21. Core Types - Package package { } title : ensure => source => present | latest | {version} | absent | purged, eg) /tmp/abcpkg-1.1.rpm eg) 'abcpkg':
  • 22. Core Types - Service service { } title : ensure => enable => name => status => start => stop => restart => hasrestart => hasstatus => running | stopped , true | false , defaults to title true | false, true | false, Manually specified commands for working around bad init scripts use stop+start instead of restart use grepping process table instead of status eg) 'httpd':
  • 23. Core Types - notify notify { } title : message => defaults to title eg) 'This message is getting logged':
  • 24. Core Types - exec exec { } title : command => path => refreshonly => onlyif => unless => The command to run; defaults to title eg) ['bin', 'sbin', '/usr/bin', '/usr/sbin'], true | false only run, the result of this command is non-zero eg) 'run-something': only run as notified only run, the result of this command is zero
  • 25. Core Types - cron cron { } title : command => user => hour => minute => ensure => The command to run eg) 'root', eg) 2, eg) 'logrotate': eg) 2, present | absent,
  • 26. Core Types - user user { } title : uid => gid => shell => home => ensure => eg) '507', eg) 'admin', or '10000', eg) '/bin/bash', eg) 'dave': eg) '/home/dave', present | absent, managehome => true | false, if it's false, you need to create user's home directory manually.
  • 27. Core Types - group group { } title : gid => ensure => eg) '10000', eg) 'admin': present | absent, name => defaults to title
  • 28. Variable • prefixed with a $(dollar sign) • any kind of data types can be assigned $www_base_path = "/var/www" file { "${www_base_path}/site": ensure => directory, } $ssh_users = [ 'myself', 'someone' ] class test { $ssh_users += [ 'someone_else' ] } Interpolation Appending Assignment (Allow strings, arrays, hashes)
  • 29. Facter/Facts • Facter • Puppet's cross-platform system profiling library • Discovers and reports per-node facts which are available in you Puppet manifests as variables • Facts Facts appears in Puppet as normal top-scope variables $ facter -p
  • 31. Core Facts architecture eg) x86_64 domain eg) example.com fqdn eg) node01.example.com filesystem eg) ext4, iso9660 hostname eg) node01 ipaddress eg) 10.0.2.15 kernelrelease eg) 2.6.32-504.8.1.el6.x86_64 memorysize eg) 458.39 MB osfamily eg) RedHat
  • 32. Custom fact • You can extend facter by writing ruby code • http://docs.puppetlabs.com/facter/2.4/custom_facts. html Facter.add(:rubypath) do setcode 'which ruby' end Facter.add(:rubypath) do confine :osfamily => "Windows" # Windows uses 'where' instead of 'which' setcode 'where ruby' end
  • 33. External Facts • fact location /etc/facter/facts.d • Adding external facts $ echo "application_tier=dev" > /etc/facter/facts.d/app.txt $ facter application_tier dev $ cat <<EOF > /etc/facter/facts.d/mydata.yaml yamlkey: - hello - world EOF $ facter yamlkey ["hello", "world"]
  • 35. Conditional Statements • booleans $x = 1 $y = 2 ($x == $y) ($x > $y) ($x < $y) ($x != $y) ($x < $y) and !($x < $y)
  • 36. Conditional Statements • Booleans • Arithmetic $x = 1 $y = 2 ($x == $y) ($x > $y) ($x < $y) ($x != $y) ($x < $y) and !($x < $y) $x = 1 $y = 2 $x + $x == $y # true $x - $x # 0 $y / 2 # 1
  • 37. Conditional Statements • if/elsif/else • unless if str2bool("$is_virtual") { warning('Not work on virtual machine') } elsif $::operatingsystem == 'Darwin' { warning('Not support yet') } else { include ntp } unless $::memorysize > 1024 { $maxclient = 500 }
  • 38. Conditional Statements • case • selector case $::hostname { /^www/: { include apache } /^dns/: { include bind } /^mx[1-2]/: { include mx } default: { include base } } $rootgroup = $::osfamily ? { 'Solaris' => 'wheel', /(Darwin|FreeBSD)/ => 'wheel', default => 'root', }
  • 39. Conditional Statements • in if $::hostname in [ 'www', 'web' ] { service { 'httpd' : ensure => true } }
  • 40. 40 Templates » Documents that combine code, data, and literal text to produce a final rendered output. » The goal of a template is to manage a complicated piece of text with simple inputs.
  • 41. 41 Template Syntax <% Ruby codes %> <%= Ruby expression %> <%# comment %> <% if @ssl -%> ## SSL directives SSLEngine on SSLCertificateFile <%= @ssl_cert %> SSLCertificateKeyFile <%= @ssl_key %> <% if @ssl_chain -%> SSLCertificateChainFile <%= @ssl_chain %> <% end -%> No newline
  • 42. 42 Templates - iteration # ntp/init.pp $nameservers = [ ‘ns1.example.com’, ‘ns2.example.com’, ‘ns3.example.com’ ] $searchdomains = [ ‘inside.example.com’, ‘outside.example.com’, ‘under.example.com’] file {“resolvconf”: path => “/etc/resolv.conf”, mode => ‘0644’, owner => root, group => root, content => template('resolvconf.erb') } # /etc/puppet/manifests/resolv.conf.erb # resolv.conf build by Puppet domain <%= @domain %> search <% @searchdomains.each do |domain| -%> <%= domain -%><% end -%> <%= @domain %> <% @nameservers.each do |server| -%> nameserver <%= server %> <% end -%> /etc/resolv.conf # resolv.conf build by Puppet domain example.com search inside.example.com outside.com under.example.com example.com nameserver ns1.example.com nameserver ns2.example.com nameserver ns3.example.com
  • 43. 43 inline_template $day_of_week = inline_template("<%= Time.now.gmtime.wday %>”) if $day_of_week ==0 { exec { ‘Do Monday task’ : # do something } } else { exec { ‘Do rest of days task’ : # do something else } }
  • 45. Classes • Named blocks of Puppet code, Stored in module # A class with no parameters class base::linux { file { '/etc/passwd': owner => 'root', group => 'root', mode => '0644', } file { '/etc/shadow': owner => 'root', group => 'root', mode => '0440', } } class Type Attribute Type Attribute $variable include other class
  • 46. Defining class • Class[‘apache’] class apache { package { ‘httpd’: ensure => latest } service { ‘httpd’: ensure => running } file { '/etc/httpd/conf': ensure => directory } file { '/etc/httpd/conf/httpd.conf': ensure => file, require => [ Package['httpd'], File['/etc/httpd.conf'], ], notify => Service['httpd'], } } Looks OK, but Is it work on Debian?
  • 47. Parameterized class • Class[‘apache’] class apache ( $package = ‘httpd’, $service = ‘httpd’ ){ package { $package: ensure => latest } service { $service : ensure => running } … } # tests/debian.pp class { ‘apache’ package => ‘apache2’, service => ‘apache2’, } # tests/redhat.pp class { ‘apache’ : } # or include apache
  • 48. Params class • Class[‘apache::params’] class apache::params { case $::osfamily { 'RedHat': { $package = 'httpd' $service = ‘httpd’ … } 'Debian': { $package = 'apache2' $service = ‘apache2’ … } } } How to use it? The answer is inheritance
  • 49. Class Inheritance • Use inherits keyword class test::parent { $var = "parent" notice("var in parent is ",$var) } class test::child inherits test::parent { $var = "child" notice("var in child is ",$var) } class test::nephew { notice( "var in nephew is", $var) } [root@localhost modules]# tree test/ test/ ├── manifests │ ├── child.pp │ ├── init.pp │ ├── nephew.pp │ └── parent.pp └── tests └── inherits.pp # manifests/init.pp class test{ include test::child include test::nephew } # tests/inherits.pp include test[root@localhost test]# puppet apply tests/inherits.pp Notice: Scope(Class[Test::Parent]): var in parent is parent Notice: Scope(Class[Test::Child]): var in child is child Notice: Scope(Class[Test::Nephew]): var in nephew is Notice: Compiled catalog for localhost in environment production in 0.06 seconds Notice: Finished catalog run in 0.01 seconds
  • 50. Using params class • Class[‘apache’] class apache ( $package = $apache::params::package, $service = $apache::params::service ) inherits apache::params { package { $package: ensure => latest } service { $service : ensure => running } … } # tests/apache.pp include apache Use inheritance, If you want to override some parent’s variables or using params class
  • 51. Declaring class • include standard way to declare classes • require become a dependency of the surrounding container • contain (>= Puppet 3.4) http://docs.puppetlabs.com/puppet/3.7/reference/lang_containm ent.html#containing-classes include-like behavior -> multiple declaration is OK class web { } include apache include apache include apache include apache class web { } class { ‘apache’: } include apache
  • 52. Declaring class • class Only way to declare parameterized classes Resource-like behavior -> Only one declaration is OK # tests/debian.pp class { ‘apache’ package => ‘apache2’, service => ‘apache2’, } class web { } include apache class { ‘apache’: } include apache
  • 54. Define • Can be evaluated multiple times with different parameters • Once defined, acts like a new resource type class apache::vhost ($docroot, $server_name, $server_admin) { include apache # contains Package['httpd'] and Service['httpd'] include apache::params # contains common config settings $vhost_dir = $apache::params::vhost_dir file { "${vhost_dir}/${server_name}.conf": content => template('apache/vhost-default.conf.erb'), owner => 'www', group => 'www', mode => '0644', require => Package['httpd'], notify => Service['httpd'], } } # tests/vhosts.pp class { 'apache::vhost': docroot => '/var/www/html', server_name => 'www01.abc.com', server_admin => 'sysadmin@abc.com', } class { 'apache::vhost': docroot => '/var/www/html', server_name => 'www02.abc.com', server_admin => 'sysadmin@abc.com', } [root@localhost apache]# puppet apply tests/http.pp Error: Duplicate declaration: Class[Apache::Vhost] is already declared in file /etc/puppet/modules/apache/tests/http.pp:5; cannot redeclare at /etc/puppet/modules/apache/tests/http.pp:11 on node localhost Error: Duplicate declaration: Class[Apache::Vhost] is already declared in file /etc/puppet/modules/apache/tests/http.pp:5; cannot redeclare at /etc/puppet/modules/apache/tests/http.pp:11 on node localhost
  • 55. Define define apache::vhost2($docroot, $servername = $title, $server_admin) { include apache # contains Package['httpd'] and Service['httpd'] include apache::params # contains common config settings $vhost_dir = $apache::params::vhost_dir file { "${vhost_dir}/${server_name}.conf": content => template('apache/vhost-default.conf.erb'), owner => 'www', group => 'www', mode => '0644', require => Package['httpd'], notify => Service['httpd'], } } # tests/define.pp apache::vhost2 { 'www01.abc.com': docroot => '/var/www/html', server_admin => 'sysadmin@abc.com', } apache::vhost2 { 'www02.abc.com': docroot => '/var/www/html', server_name => 'www02.abc.com', server_admin => 'sysadmin@abc.com', } [root@localhost apache]# puppet apply tests/define.pp Notice: Compiled catalog for localhost in environment production in 0.28 seconds Notice: /Stage[main]/Main/Apache::Vhost2[www02.abc.com]/File[/etc/httpd/conf.d/www02.ab c.com.conf]/ensure: defined content as '{md5}39cab336c208f334fde6b07ef8c33445' Notice: /Stage[main]/Apache/Service[httpd]: Triggered 'refresh' from 1 events Notice: Finished catalog run in 0.78 seconds
  • 56. functions • Pre-defined chunks of Ruby code • Runs during compilation time • http://docs.puppetlabs.com/references/3.7.latest/function.html • https://forge.puppetlabs.com/puppetlabs/stdlib template eg) template('apache/vhost-default.conf.erb'), str2bool eg) $_result = str2bool($::is_virtual) fail eg) fail('$server_name is needed') alert eg) alert('$server_name is empty, it’s filled with $title') notice eg) notice( "var in parent is", $var)
  • 57. Scope # /etc/puppet/modules/scope_example/manifests/init.pp class scope_example { $variable = "Hi!" notify {"Message from here: $variable":} notify {"Node scope: $node_variable Top scope: $top_variable":} } # /etc/puppet/manifests/site.pp $top_variable = "Available!" node 'puppet.example.com' { $node_variable = "Available!" include scope_example notify {"Message from node scope: $variable":} } notify {"Message from top scope: $variable":} $ puppet apply site.pp notice: Message from here: Hi! notice: Node scope: Available! Top scope: Available! notice: Message from node scope: notice: Message from top scope:
  • 58. 58 namespace » Class and defined type names may be broken up into segments » Separated by double colon(::) » analogous to the / [slash] in a file path. class apache { ... } class apache::mod { ... } class apache::mod::passenger { ... } define apache::vhost { ... } apache <modulepath>/apache/manifests/init.pp apache::mod <modulepath>/apache/manifests/mod.pp apache::mod::passenger <modulepath>/apache/manifests/mod/passenger.pp
  • 59. module • Collection of manifests, resources, files, templates, classes, and definitions. • Can download pre-built modules from the Puppet forge - http://forge.puppetlabs.com $ puppet module generate daehyung-amodule $ tree daehyung-amodule/ daehyung-amodule/ |-- Modulefile |-- README |-- manifests | `-- init.pp |-- spec | `-- spec_helper.rb `-- tests `-- init.pp foo/ |-- manifests | |-- config.pp | |-- defaults.pp | |-- init.pp | |-- install.pp | `-- service.pp |-- templates | `-- foo-conf.erb `-- tests `-- init.pp
  • 60. installing / uninstalling module https://docs.puppetlabs.com/puppet/latest/referen ce/modules_installing.html puppet man module puppet module list puppet module search r10k puppet module install zack/r10k --version 2.6.5 puppet module install zack-r10k-2.6.5.tar.gz --ignore-dependencies puppet module upgrade zack/r10k --version 3.1.1 puppet module uninstall zack/r10k
  • 61. 61 Keep this in mind • Make a new module for you or company? • Search from Puppet Forge first! • The simple answer is NO!!!
  • 62. Not mentioned in here • ENC • Hiera • Environments • r10k • etc. • too many, I’m still learning it ;)
  • 64. Roles & Profiles • Implementation layer (Profiles) Includes regular classes Might add resources directly create_resources call • Business layer (Roles) Only includes profiles No logic at all One server - One role
  • 65. Installation • Debian OS family [Client] sudo apt-get install puppet [Server] sudo apt-get install puppetmaster • RedHat OS family Register EPEL or puppetlabs' repository • # rpm -ivh http://yum.puppetlabs.com/el/6/ products/x86_64/puppetlabs-release-6-11.noarch.rpm • [Client] yum install puppet • [Server] yum install puppet-server

Editor's Notes

  1. Red: Mac OSX only Blue: Windows Only Yellow: solaris gray: solaris, FreeBSD, and some linux dist.
  2. facter is an accessory project, it's written in ruby, facter on the command line is a ruby script there are many resources that are mapped to facts. and we'll see later, we can make our own custom facts as well.
  3. Red: Mac OSX only Blue: Windows Only Yellow: solaris gray: solaris, FreeBSD, and some linux dist.
  4. - EPEL repository provides Puppet 2.7 only