Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

CIS 527

Using Puppet

Puppet

Image Credit: Puppet Labs

Learning Puppet

Much of this lecture's content is adapted from the Learning Puppet series on https://learn.puppetlabs.com/

Learning Puppet VM

Follow along using the
Learning Puppet VM
http://puppetlabs.com/download-learning-vm
It can also be made available on my
CS people page

Abstraction

3 big insights

  • Similar resources can be grouped into types
  • Description can be separate from implementation
  • It is possible to declare a desired state for a resource

Resources

$> puppet resource package

Resources

$> puppet resource package
package { 'ubuntu-keyring':
  ensure => '2012.05.19',
}
package { 'ubuntu-minimal':
  ensure => '1.325',
}
package { 'ubuntu-mono':
  ensure => '14.04.+14.04.20140410-0ubuntu1',
}
...

Resources

  • A system is a collection of many resources
  • Each resource represents a small unit
  • Resources have a type, title and attributes

Resources Example

user { 'dave':
  ensure     => present,
  uid        => '507',
  gid        => 'admin',
  shell      => '/bin/zsh',
  home       => '/home/dave',
  managehome => true,
}

Find the type, title, attributes, and values

Resource Types

  • Package
  • File
  • Service
  • Notify
  • User / Group
  • Exec
  • Cron

Modifying a Resource

$> puppet resource user russfeld
ensure=present shell="/bin/zsh"
home="/home/russfeld"
managehome=true


Modifying a Resource

$> puppet resource user russfeld
ensure=present shell="/bin/zsh"
home="/home/russfeld"
managehome=true


notice: /User[russfeld]/ensure: created
user { 'russfeld':
  ensure => 'present',
  home   => '/home/russfeld',
  shell  => '/bin/zsh'
}

Try to create your own user account

Manifest File

  • Defines a desired state for resources using a resource declaration
  • Can be applied repeatedly to the system
  • Can also contain logic and structural elements (next lecture)

First Manifest File

# /root/user-absent.pp
user {'russfeld':
  ensure => absent,
}

First Manifest File

# /root/user-absent.pp
user {'russfeld':
  ensure => absent,
}


$> puppet apply /root/user-absent.pp

First Manifest File

# /root/user-absent.pp
user {'russfeld':
  ensure => absent,
}


$> puppet apply /root/user-absent.pp
notice: /Stage[main]//User[russfeld]/
    ensure: removed notice: Finished catalog run in
    0.44 seconds

Resource Declaration

file {'testfile':
  path    => '/tmp/testfile',
  ensure  => present,
  mode    => 0640,
  content => "I'm a test file.",
}


  • Type - file {
    • Title - 'testfile' :
    • Attribute/value pairs -
      ensure => present,
  • } (end of declaration)

Testing Resources

  • Run the manifest again
  • Delete /tmp/testfile
  • Change rights on /tmp/testfile
  • Change contents of /tmp/testfile

Manifest Compilation

Image Credit: Puppet Labs

Resource Ordering

# /root/training-manifests/2.file.pp

file {'/tmp/test1':
  ensure  => present,
  content => "Hi.",
}

file {'/tmp/test2':
  ensure => directory,
  mode   => 644,
}

file {'/tmp/test3':
  ensure => link,
  target => '/tmp/test1',
}

notify {"I'm notifying you.":}
notify {"So am I!":}

Resource Ordering

$ puppet apply /root/examples/file-2.pp
notice: /Stage[main]//File[/tmp/test1]/
    ensure: created notice: /Stage[main]//File[/tmp/test3]/
    ensure: created notice: /Stage[main]//File[/tmp/test2]/
    ensure: created notice: So am I! notice: /Stage[main]//Notify[So am I!]/
    message: defined 'message' as 'So am I!' notice: I'm notifying you. notice: /Stage[main]//Notify[I'm notifying you.]/
    message: defined 'message' as 'I'm notifying you.' notice: Finished catalog run in 0.05 seconds

Resource Ordering

  • Puppet assumes resource declaraions are atomic
  • Therefore, it applies them in any order
  • You must define relationships between resources

Require

file {'/tmp/test1':
  ensure  => present,
  content => "Hi.",
}

notify {'/tmp/test1 has already been synced.':
  require => File['/tmp/test1'],
}

Before

file {'/tmp/test1':
  ensure  => present,
  content => "Hi.",
  before  => Notify['/tmp/test1 has
    already been synced.'], } notify {'/tmp/test1 has already been synced.':}

Subscribe

file { '/etc/ssh/sshd_config':
  ensure => file,
  mode   => 600,
  source => 'puppet:///modules/ssh/sshd_config',
}
service { 'sshd':
  ensure    => running,
  enable    => true,
  subscribe => File['/etc/ssh/sshd_config'],
}

Chaining Arrows

file {'/tmp/test1':
  ensure  => present,
  content => "Hi.",
}

notify {'after':
  message => '/tmp/test1 has already
    been synced.', } File['/tmp/test1'] -> Notify['after']

Chaining Arrows

file {'/tmp/test1':
  ensure  => present,
  content => "Hi.",
}
->
notify {'after':
  message => '/tmp/test1 has already
    been synced.', }

Package/File/Service

package { 'openssh-server':
  ensure => present,
  before => File['/etc/ssh/sshd_config'],
}
file { '/etc/ssh/sshd_config':
  ensure => file,
  mode   => 600,
  source => '/root/examples/sshd_config',
}
service { 'sshd':
  ensure     => running,
  enable     => true,
  subscribe  => File['/etc/ssh/sshd_config'],
}

Day 2

Much of this lecture's content is adapted from the Learning Puppet series on https://learn.puppetlabs.com/

Variables

$my_variable = "A bunch of text"
notify {$my_variable:}

Variable Notes

  • Always starts with a dollar sign $
  • Assign with an equals sign =
  • Can hold strings, numbers, arrays, booleans, etc.
  • Can use variables as any value inside a resource declaration, including the title

Variable Notes

  • Variables are interpolated in double-quoted strings
    $username = "russfeld"
    notify {"Your home directory is /home/${username}": }
  • Variables can only be assigned once

Facts

  • Puppet uses Facter to learn about systems
  • Facter "facts" are stored as variables
  • Facts can be used in manifest files

Facter

#> facter -p

Facter

#> facter -p

architecture => i386
bios_version => 6.00
block_devices => sda
domain => localdomain
id => root
...

Facter

List of facts

Conditionals

if <boolean> {
    <code>
}
elsif <boolean> {
    <code>
}
else {
    <code>
}

Booleans

$boolean = "false"
if $boolean {
    notify{"This is true":}
}
else {
    notify{"This is false":}
}

Booleans

$boolean = "false"
if $boolean {
    notify{"This is true":}
}
else {
    notify{"This is false":}
}

Notify: This is true

Booleans

  • All facts are strings
  • All non-empty strings are true
  • Use str2bool(<string>)

  • puppet module install puppetlabs-stdlib

Booleans

include stdlib
$boolean = "false"
if str2bool("$boolean") {
    notify{"This is true":}
}
else {
    notify{"This is false":}
}

Booleans

include stdlib
$boolean = "false"
if str2bool("$boolean") {
    notify{"This is true":}
}
else {
    notify{"This is false":}
}
Notify: This is false

Case Statement

case $operatingsystem {
  centos: { $apache = "httpd" }
  # Note that these matches
  # are case-insensitive.
  redhat: { $apache = "httpd" }
  debian: { $apache = "apache2" }
  ubuntu: { $apache = "apache2" }
  default: { fail("Unrecognized OS") }
}

Case Statement

case $operatingsystem {
  centos, redhat: { $apache = "httpd" }
  debian, ubuntu: { $apache = "apache2" }
  default: { fail("Unrecognized OS") }
}

Can also use Regular Expressions

Case Statement

$apache = $operatingsystem ? {
  centos                => 'httpd',
  redhat                => 'httpd',
  /(?i)(ubuntu|debian)/ => 'apache2',
  default               => undef,
}

Classes

class my_class {
  notify {"This does something":}
}

include my_class

Classes

  • Classes can contain any Puppet code
  • Names must be all lowercase, with numbers and underscores allowed
  • Classes are defined to make them available, and declared to be evaluated

Variable Scope

  • Classes create a new variable scope
  • Use $<class_name>::<var_name> to access
  • They cannot be assigned outside the declaring class

Modules

  • You can separate classes into modules for organization
  • Each module has a specific file structure
  • Modules are automatically loaded by Puppet from certain folders
  • /etc/puppetlabs/puppet/puppet.conf

Module Structure

/etc/puppetlabs/code/modules/
  module_name/
    manifests/
      init.pp
    files/
    templates/
    lib/

Module Structure

  • init.pp must contain a single class definition with the same name as the module
  • Modules can contain other classes, files, and templates

Site Manifest

/etc/puppetlabs/code/environments/
production/manifests/site.pp

  • Global manifest file for client/server
  • Includes class / module declarations
  • Can have many environments
include ntp
include apache
include mysql

Puppet Forge

Day 3

Much of this lecture's content is adapted from the Learning Puppet series on https://learn.puppetlabs.com/

Single Puppet

Image Credit: Puppet Labs

Agent/Master Mode

Image Credit: Puppet Labs

Today's Plan

  1. Set up the Puppet Learning VM
  2. Load 2 agents in Docker
  3. Get the VMs to communicate
  4. Install a module on the server and apply it on the client

Puppet Agent

Puppet agent command runs in 2 modes:

  • Daemon mode
  • Run and quit

First Try

Let's try it by running:

puppet agent -t

First Try

Let's try it by running:

puppet agent -t

[root@agent1 ~]# puppet agent -t
info: Creating a new SSL key for agent1.localdomain
warning: peer certificate won't be verified in this SSL session
info: Caching certificate for ca
info: Creating a new SSL certificate request for agent1.localdomain
info: Certificate Request fingerprint (md5):
    FD:E7:41:C9:2C:B7:5C:27:11:0C:8F:9C:1D:F6:F9:46
Exiting; no certificate found and waitforcert is disabled

What Happened?

  • Puppet secures communications between the master and agents with SSL
  • Since our agent doesn't have a valid certificate, it won't work
  • We must sign our certificate to continue

Signing SSL Certificates

On the Master VM:

puppet cert list

Signing SSL Certificates

On the Master VM:

puppet cert list
agent1.localdomain (FD:E7:41:C9:2C:B7:5C:27:11:0C:8F:9C:1D:F6:F9:46)

Signing SSL Certificates

On the Master VM:

puppet cert list
agent1.localdomain (FD:E7:41:C9:2C:B7:5C:27:11:0C:8F:9C:1D:F6:F9:46)

puppet cert sign agent1.localdomain

Signing SSL Certificates

On the Master VM:

puppet cert list
agent1.localdomain (FD:E7:41:C9:2C:B7:5C:27:11:0C:8F:9C:1D:F6:F9:46)

puppet cert sign agent1.localdomain
notice: Signed certificate request for agent1.localdomain
notice: Removing file Puppet::SSL::CertificateRequest ...

Try Again

puppet agent -t

[root@agent1 ~]# puppet agent -t
warning: peer certificate won't be verified in this SSL session
info: Caching certificate for agent1.localdomain
info: Retrieving plugin
info: Caching certificate_revocation_list for ca
info: Loading facts in facter_dot_d
info: Caching catalog for agent1.localdomain
info: Applying configuration version '1326210629'
notice: Finished catalog run in 0.11 seconds

Configuring the site.pp file

  • Install the NTP module from Puppet Forge:
    puppet module install puppetlabs-ntp
  • /etc/puppetlabs/code/environments/
    production/manifests/site.pp:
    node 'agent1.localdomain' {
    # Note the quotes around the name!
      class {'ntp':
        servers => [ "ntp-1.ksu.edu dynamic",
          "ntp-2.ksu.edu dynamic", ],
      }
    }

Apply on Agent

puppet agent --test

[root@agent1 ~]# puppet agent --test
info: Retrieving plugin
info: Loading facts in facter_dot_d
notice: /Stage[main]/Ntp/Package[ntp]/ensure: created
+# Managed by puppet class { "ntp": servers => [ ... ] }
info: ntp.conf: Scheduling refresh of Service[ntp]
notice: /Stage[main]/Ntp/Service[ntp]: Triggered 'refresh' from 1 events
notice: Finished catalog run in 32.74 seconds

What's Next?

  • Add more modules
  • Add more agents
  • Customize configuration for different types of agents
  • Test, test, test
  • Enjoy your new stress-free life!

Assignments

  • Lab 2 - Configuration Management with Puppet: Due Monday Feb 13th by 10:30 AM