Microsoft's Internet Explorer browser has no built-in vector graphics machinery required for "loss-free" gradient background themes.

Please upgrade to a better browser such as Firefox, Opera, Chrome, Safari or others with built-in vector graphics machinery and much more. (Learn more or post questions or comments at the Slide Show (S9) project site. Thanks!)

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

Introduction to Puppet

Getting Help

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

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:

   1   

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

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

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

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

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

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

The Villain

luke@reductivelabs.com