On Github catalyst-training / puppet-intermediate
Presented by Evan Giles / Alex Lawn
http://PRESENTER_IP/files/puppet_int_lab_nodes.ova
You can view these slides at http://catalyst-training.github.io/puppet-intermediate/
There'll be quite a lot of copy/pasting coming up, so take the time to load them up now...
puppet# rpm -ivh http://yum.puppetlabs.com/puppetlabs-release-el-6.noarch.rpm puppet# yum install puppet-server
node-a# rpm -ivh http://yum.puppetlabs.com/puppetlabs-release-el-6.noarch.rpm node-a# yum install puppet
node-b# rpm -ivh http://yum.puppetlabs.com/puppetlabs-release-el-6.noarch.rpm node-b# yum install puppet
node-d# wget https://apt.puppetlabs.com/puppetlabs-release-trusty.deb node-d# dpkg -i puppetlabs-release-trusty.deb node-d# apt-get update node-d# apt-get install puppet node-d# service puppet stop
puppet# chkconfig puppetmaster on puppet# /etc/init.d/puppetmaster start
Repeat for all nodes:
node-x# puppet agent -tv --waitforcert=300 puppet# puppet cert --list puppet# puppet cert --sign node-x.localdomain node-x# puppet agent -tv
/etc/puppet/manifests/site.pp:
import 'nodes.pp'
/etc/puppet/manifests/nodes.pp:
node 'node-a.localdomain' {
}
node 'node-b.localdomain' {
}
node 'node-d.localdomain' {
}
<html>
<head>
<title>Test Page</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
package { 'httpd':
ensure => 'installed',
}
user { 'web':
ensure => present,
managehome => true,
}
file { "/var/www/index.html":
ensure => present,
owner => "www",
group => "apache",
mode => "444",
source => "puppet:///modules/web/var/www/index.html",
require => [ User["web"], Package['httpd'], ],
}
service { 'httpd':
enable => true,
ensure => 'running',
require => [ Package["httpd"], File["/etc/httpd/conf/httpd.conf"] ],
}
file { "/etc/httpd/conf/httpd.conf":
ensure => present,
owner => "www",
group => "apache",
mode => "444",
source => "puppet:///modules/web/etc/httpd/conf/httpd.conf",
require => User["web"],
notify => Service["httpd"],
}
if $osfamily == 'RedHat' {
$http_pkg = 'httpd'
} elsif $osfamily == 'Debian' {
$http_pkg = 'apache2'
} else {
warning( 'OS not supported.' )
}
$http_pkg = $osfamily ? {
'RedHat' => 'httpd',
'Debian' => 'apache2',
}
notify { 'Whassup my homies.': }
notify { "http_pkg is $http_pkg": }
source => [ "puppet:///modules/web/etc/httpd/conf/httpd.conf-$osfamily", "puppet:///modules/web/etc/httpd/conf/httpd.conf", ],
We must ensure that one option ALWAYS matches otherwise the catalogue compilation will fail.
unless $fqdn == 'node-d.localdomain' {
package { 'tree':
ensure => 'installed',
}
}
/etc/puppet/puppet.conf
[master] environmentpath = $confdir/environments
A new directory structure:
mkdir /etc/puppet/environments/{production,dev}
mv /etc/puppet/manifests /etc/puppet/environments/production/
mv /etc/puppet/modules /etc/puppet/environments/production/
- This 'production' is the default...Place node-b in the dev environment: /etc/puppet/puppet.conf (on node-b)
[agent]
environment = dev
$http_port = $environment ? {
'production' => '80',
'dev' => '8080',
}
content => template("httpd/httpd.conf.erb"),
Listen <%= @http_port %>
class web {
. . .
}
class web::infrastructure {
. . .
}
class web::application {
. . .
}
include web::infrastructure include web::application
include web::infrastructure
class { 'web::application':
require => Class['web::infrastructure'],
}
<%= scope['web::http_port'] %>
node-a# puppet-agent -tv --tags web node-a# puppet-agent -tv --tags note
class 'web::application' {
tag 'app'
}
node-a# puppet-agent -tv --tags app
$hour = fqdn_rand( max - min ) + min
<% if @osfamily == 'Debian' %> I'm a bit different to the others. <% end %>
(Because we are diligent at indenting.)
<%- if @osfamily == 'Debian' %> I'm a bit different to the others. <% end %>
$colours = [ 'red', 'yellow', 'pink', 'green', 'purple', 'orange', 'blue', ]
I can sing a rainbow: <% @colours.each do |c| %> Colour: <%= c %> <% end %>
I can sing a rainbow:
<% @colours.each do |c| -%> Colour: <%= c %> <% end -%>
<%
# Establish an empty array.
@cmd = []
# Push a string onto the array.
@cmd << 'mk.rainbow'
# Add my commandline parameters for colours (interpolate quotes).
@colours.each do |c|
cmd << --include
cmd << "'#{c}'"
end
-%>
<%= @cmd.join(' ') %>
erb -P -x -T '-' mytemplate.erb | ruby -c
environments/XXX/modules/web/lib/facter/pkg_count.rb
Facter.add( 'pkg_count' ) do setcode 'rpm -qa | wc -l' end- This magically deploys the fact to the nodes - you need to run facter -p to see it
environments/dev/web/lib/facter/pkg_count.rb
Facter.add( 'pkg_count' ) do confine :kernel => "Linux" setcode 'rpm -qa | wc -l' end
environments/dev/web/lib/facter/pkg_count.rb
Facter.add( 'pkg_count' ) do
confine :kernel => "Linux"
setcode do
osfamily = Facter.value(:osfamily)
case osfamily
when 'RedHat'
Facter::Core::Resolution.exec('rpm -qa | wc -l')
when 'Debian'
Facter::Core::Resolution.exec('dpkg -l | wc -l')
end
end
On the client node: /etc/facter/facts.d/lab_facts.txt
product_key=DIndiwnsklIndk thingee=mawhatsit
facter --debug
class web::infrastructure (
$http_port = '80',
$server_name,
) {
. . .
}
node 'node-a.localdomain' {
class { web::infrastructure:
server_name => "I am node A.",
}
}
node 'node-a.localdomain' {
class { web::infrastructure:
server_name => "I am node B.",
}
}
node 'node-a.localdomain' {
class { web::infrastructure:
server_name => "I am node A.",
}
class { web::application:
require => Class['web::infrastructure'],
}
}
node 'node-a.localdomain' {
class { web::infrastructure:
server_name => "I am node B.",
}
class { web::application:
require => Class['web::infrastructure'],
}
}
class web (
$http_port = '80',
$server_name,
) {
class { 'web::infrastructure':
server_name => $server_name,
http_port => $http_port,
}
class { 'web::application':
require => Class['web::infrastructure'],
}
}
class web::infrastructure (
$http_port = '80',
$server_name,
) {
. . .
}
class web::infrastructure::params {
$http_port = '80'
$server_name = $::fqdn
# Could include package selection logic here.
}
class web::infrastructure (
$http_port = $web::infrastructure::params::http_port,
$server_name = $web::infrastructure::params::server_name,
) inherits web::infrastructure::params {
. . .
}
node 'node-a.localdomain':
class { 'web::infrastructure::params':
server_name = "I am node A."
}
class { 'web': }
}
class dudes {
define dude (
$ensure,
$dude_meter = true,
) {
user { $name:
ensure => $ensure,
managehome => true,
}
$ensure_dude_meter = $dude_meter ? {
true => 'present',
false => 'absent',
}
file { "/home/$name/dude_level.txt":
ensure => $ensure_dude_meter,
owner => $name,
group => 'root',
mode => '444',
content => fqdn_rand(10, $name),
}
}
dude { 'dude1':
ensure => 'present',
}
dude { 'dude2':
ensure => 'present',
}
dude { 'dude3':
ensure => 'present',
dude_meter => false,
}
}
puppet# yum -y install httpd mod_ssl mod_passenger
puppet# chkconfig puppetmaster off
puppet# /etc/init.d/puppetmaster stop
puppet# mkdir -p /srv/rack/puppetmasterd/{tmp,public}
puppet# cp /usr/share/puppet/ext/rack/config.ru /srv/rack/puppetmasterd
puppet# chown -R puppet:puppet /srv/rack/puppetmasterd
/etc/httpd/conf.d/passenger.conf:
# And the passenger performance tuning settings: PassengerHighPerformance On # Set this to about 1.5 times the number of CPU cores in your master: PassengerMaxPoolSize 12 # Recycle master processes after they service 1000 requests PassengerMaxRequests 1000 # Stop processes if they sit idle for 10 minutes PassengerPoolIdleTime 600
/etc/httpd/conf.d/puppetmasterd.conf:
Listen 8140
<VirtualHost *:8140>
SSLEngine On
SSLProtocol All -SSLv2
SSLCipherSuite HIGH:!ADH:RC4+RSA:-MEDIUM:-LOW:-EXP
SSLCertificateFile /var/lib/puppet/ssl/certs/puppet.<domain>.pem
SSLCertificateKeyFile /var/lib/puppet/ssl/private_keys/puppet.<domain>.pem
SSLCertificateChainFile /var/lib/puppet/ssl/ca/ca_crt.pem
SSLCACertificateFile /var/lib/puppet/ssl/ca/ca_crt.pem
SSLCARevocationFile /var/lib/puppet/ssl/ca/ca_crl.pem
SSLVerifyClient optional
SSLVerifyDepth 1
SSLOptions +StdEnvVars +ExportCertData
# These request headers are used to pass the client certificate
# authentication information on to the puppet master process.
RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e
RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e
RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e
DocumentRoot /srv/rack/puppetmasterd/public
<Directory /srv/rack/puppetmasterd/>
Options None
AllowOverride None
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
puppet# /etc/init.d/httpd start puppet# chkconfig httpd on node-a# puppet agent -tv
yum -y install http://yum.theforeman.org/releases/1.1/el6/x86_64/foreman-release.rpm yum -y install foreman-installer ruby /usr/share/foreman-installer/generate_answers.rb
open source technologists