You are on page 1of 7

Introduction to Managed Infrastructures with

Puppet
by Luke Kanies

Reductive Labs, Inc.

luke@reductivelabs.com

Presentation available at
git://github.com/reductivelabs/velocity_puppet_workshop_2009.git

Goals
Get an Introduction to Puppet
Build a simple Puppet Repository
Know how to use the tools

Introduction to Puppet
It's all about Resources
We've got a custom language
Some executables

Getting Help
#puppet on irc.freenode.net
http://groups.google.com/group/puppet-users
Support Contracts :)

Resources
1 ralsh package
2 ralsh user luke
3 ralsh user foo
4 ralsh user foo ensure=present shell=/bin/bash home=/Users/foo
5 ralsh user foo shell=/usr/bin/bash
6 ralsh user foo ensure=absent

examples/ralsh.sh

Try ralsh package.

Language
1 file { "/tmp/example_file":
2 ensure => present
3 content => "This is a test\n",
4 mode => 640
5 }

examples/language.pp

Executables
puppet
ralsh
puppetd
puppetmasterd
puppetca

There are more, but this is all we're covering today

Your First Puppet Script


1 puppet -e 'file { "/tmp/eh": ensure => present }'

Produces:

1 notice: //File[/tmp/eh]/ensure: created

Try it twice. Try it with --noop.

Your Second Puppet Script


1 puppet -e 'file { "/tmp/eh": ensure => absent }'

Produces:

1 notice: //File[/tmp/eh]: Filebucketed to with sum d41d8cd98f00b204e9800998ecf8427e


2 notice: //File[/tmp/eh]/ensure: removed

Puppet Classes
1 class foo {
2 file { "/tmp/foo": ensure => present }
3 }

examples/class_but_no_include.pp

Produces:

Including Classes
1 class foo {
2 file { "/tmp/foo": ensure => present }
3 }
4 include foo

examples/class_with_include.pp

Produces:

1 notice: //foo/File[/tmp/foo]/ensure: created

A Puppet Repository
Basic Repository Structure:

1 manifests/site.pp
2 modules/
3 modules/mymod/manifests/init.pp
4 modules/mymod/templates/mytemplate.erb
5 modules/mymod/plugins/puppet/parser/functions/myfunction.rb

Your First Module


1 mkdir repo
2 mkdir -p repo/manifests repo/modules/foo/manifests
3 cp examples/class_but_no_include.pp repo/modules/foo/manifests/init.pp
To use:

1 puppet --modulepath repo/modules -e 'include foo'

Your First Node


1 node default {
2 include foo
3 }

repo/manifests/site.pp

Putting It Together
1 puppet --modulepath repo/modules repo/manifests/site.pp

You now have a "complete" Puppet repository, ready to extend.

Starting The Server


1 puppetmasterd --verbose --no-daemonize --modulepath $PWD/repo/modules \
2 --confdir /tmp/server --vardir /tmp/server \
3 --manifest $PWD/repo/manifests/site.pp --certdnsnames localhost

Produces:

1 info: Starting server for Puppet version 0.24.8


2 info: Creating a new certificate request for phage.local
3 info: Creating a new SSL key at /tmp/server/ssl/private_keys/phage.local.pem
4 info: Autosign is enabled but /tmp/server/autosign.conf is missing
5 info: Signing certificate for CA server
6 info: Signing certificate for phage.local
7 info: Listening on port 8140
8 notice: Starting Puppet server version 0.24.8

Usually runs as 'puppet' but doesn't have to.

Server Arguments
--verbose: Provide extra logging
--no-daemonize: Do not background
--modulepath $PWD/repo/modules: Specify where to find our modules
--confdir /tmp/server: Use a non-standard configuration directory
--vardir /tmp/server: Use a non-standard state/var directory
--manifest $PWD/repo/manifests/site.pp: Specify the starting manifest to parse
--certdnsnames localhost: Configure localhost as an alias in the SSL Certificate

Default Server Arguments


1 puppetmasterd --configprint modulepath
2 puppetmasterd --configprint confdir
3 puppetmasterd --configprint vardir

examples/default_server_arguments.sh

Produces:

1 /opt/rl/dist/apps/puppet/modules:/usr/share/puppet/modules
2 /etc/puppet
3 /var/puppet

Running The Agent


1 sudo puppetd --test --confdir /tmp/server --vardir /tmp/server --server localhost

Produces:

1 info: Caching catalog at /tmp/server/state/localconfig.yaml


2 notice: Starting catalog run
3 notice: //Node[default]/foo/File[/tmp/foo]/ensure: created
4 notice: Finished catalog run in 0.01 seconds

Note that we're running as root

Agent Arguments
--test: Very helpful argument rollup
--confdir /tmp/server: Use a non-standard configuration directory
--vardir /tmp/server: Use a non-standard state/var directory
--server localhost: Specify the server to contact

Certificates
This is just Standard SSL(tm).

1. Generate Certificate Signing Request (CSR)


2. Send CSR to server
3. Server signs CSR and produces Certificate
4. Client retrieves Certificate

Welcome to the Certificate Authority


1 puppetca --confdir /tmp/server/ --vardir /tmp/server --list

Produces:

1 No certificates to sign

Try puppetca --print <hostname>

Signing Client Certificates


Note the switch to /tmp/client:

1 sudo puppetd --test --confdir /tmp/client --vardir /tmp/client \


2 --server localhost --certname other.madstop.com

On the server:

1 notice: Host other.madstop.com has a waiting certificate request

1 puppetca --confdir /tmp/server/ --vardir /tmp/server --list


2 puppetca --confdir /tmp/server/ --vardir /tmp/server --sign other.madstop.com

Now run the client again.

Doing Something Useful


I always start with sudo.

In repo/modules/sudo/manifests/init.pp:

1
2 class sudo {
3 file { "/usr/bin/sudo":
4 owner => root,
5 group => wheel,
6 mode => 4111
7 }
8 }

Add sudo to the default node in site.pp.

Managing Files
Create your sudoers file at repo/modules/sudo/files/sudoers, then add this to your
init.pp:

1 file { "/etc/sudoers":
2 owner => root,
3 group => wheel,
4 mode => 440,
5 source => "puppet:///sudo/sudoers"
6 }

Managing Heterogeneity
1 file { sudo:
2 path => $operatingsystem ? {
3 darwin => "/usr/bin/sudo",
4 default => "/usr/sbin/sudo",
5 },
6 owner => root,
7 group => 0,
8 mode => 4111
9 }

Facter
1 $ facter | wc -l
2 55
3 $ facter | grep name
4 hostname => phage
5 macosx_productname => Mac OS X
6 sp_local_host_name => phage
7 sp_machine_name => MacBook
8 sp_user_name => Luke Kanies (luke)
9 $

Other Language Functions


In general, rely on the tutorial on the wiki, not me

Relationships
1 class rels {
2 file { "/tmp/reltest": ensure => present }
3 exec { "/bin/echo got notified":
4 subscribe => File["/tmp/reltest"],
5 refreshonly => true
6 }
7 }

repo/modules/rels/manifests/init.pp

Produces:

1 notice: //rels/File[/tmp/reltest]/ensure: created


2 notice: //rels/Exec[/bin/echo got notified]: Triggering 'refresh' from 1 dependencies

Definitions
Can be considered a 'composite resource'
A simple way to model resources within Puppet's language

Apache Virtual Hosts


1 define apache::vhost($docroot, $ensure = present) {
2 file { "/tmp/apache/sites/$name":
3 content => template("apache/vhost.erb"),
4 ensure => $ensure
5 }
6 }

repo/modules/apache/manifests/vhost.pp

Note the qualified definition name. This is required for correct autoloading.

Using Definitions
1 class apache {
2 apache::vhost { 'reductivelabs.com':
3 docroot => "/var/www/reductivelabs.com"
4 }
5 apache::vhost { 'foo.com':
6 docroot => "/var/www/foo.com",
7 ensure => absent
8 }
9 }

repo/modules/apache/manifests/init.pp

Complicated Virtual Host


1 define apache::vhost2($docroot, $ensure = present) {
2 $available => $ensure ? { enabled => present, default => $ensure }
3 $enabled => $ensure ? { enabled => symlink, default => absent }
4 file { "/tmp/apache/sites-available/$name":
5 content => template("apache/vhost.erb"),
6 ensure => $available
7 }
8 file { "/tmp/apache/sites-enabled/$name":
9 target => "/tmp/apache/sites-available/$name",
10 ensure => $enabled
11 }
12 }

repo/modules/apache/manifests/vhost2.pp

Things We Skipped
Reporting
Queueing
Inheritance
Storeconfigs
Export/Collect
Everything else we didn't cover

Obligatory Pitch
Reductive Labs provides support contracts, training, and custom development, and we use all of the
revenue to fund development, this kind of talk, and eating. Well, almost all.

Conclusion
luke@reductivelabs.com

You might also like