puppet troubleshooting
Thomas Uphill
<thomas@narrabilis.com>
https://goo.gl/8LyZzN
Mastering Puppet / Puppet Cookbook
Packt Pub
https://goo.gl/8LyZzN
LOPSA / SASAG / PUGS
https://goo.gl/8LyZzN
When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth
Sir Arthur Conan Doyle
4
Troubleshooting 101
5
1 une uno um unis odin jeden jedward yksi 一 एक واحد אחד
https://goo.gl/8LyZzN
Troubleshooting 101
6
https://goo.gl/8LyZzN
TAKE HOME
puppet is an HTTPS service
7
https://goo.gl/8LyZzN
problems
connection
certificate�catalog compilation�catalog application�scope�pry
8
can't find puppet
9
$ puppet config print server
yourface
$ puppet config print confdir
/home/thomas/.puppetlabs/etc/puppet
# puppet config print server
puppet
# puppet config print ca_server
puppet
# puppet config print confdir
/etc/puppetlabs/puppet
https://goo.gl/8LyZzN
puppet agent Runs as root…
puppetserver Runs as puppet.
10
Basic UNIX permissions
11
https://goo.gl/8LyZzN
can't find puppet
12
dns
files
/etc/hosts
nsswitch.conf
# host puppet
Host puppet not found: 3(NXDOMAIN)
# nslookup puppet
Server: 10.0.2.3
Address: 10.0.2.3#53
** server can't find puppet: NXDOMAIN
# dig puppet
# getent hosts puppet
127.0.0.1 puppet.example.com puppet localhost localhost.localdomain localhost4 localhost4.localdomain4
# ping puppet
PING puppet.example.com (127.0.0.1) 56(84) bytes of data.
64 bytes from puppet.example.com (127.0.0.1): icmp_seq=1 ttl=64 time=0.035 ms
https://goo.gl/8LyZzN
can't connect to puppet
13
node
puppet
server
network
pixies
8140
server
masterport
https://goo.gl/8LyZzN
can't connect to puppet
Verify you can connect:
# nc -v puppet.example.com 8140
Ncat: Version 7.12 ( https://nmap.org/ncat )�Ncat: Connected to 192.168.1.1:8140
14
https://goo.gl/8LyZzN
can't connect to puppet
Q: How can you know you are talking to puppet?
A: Use the REST API
15
https://goo.gl/8LyZzN
can't connect to puppet
$ curl -k https://puppet.example.com:8140/puppet-ca/v1/certificate/ca?environment=production
-----BEGIN CERTIFICATE-----�MIIFhDCCA2ygAwIBAgIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB1QdXBw�ZXQgQ0E6IHB1cHBldC5leGFtcGxlLmNvbTAeFw0xNjEwMDgyMDEyNDRaFw0yMTEw�…�qsHOzPEQwJS5q1yPciBQ5jsKCB5vXJEdnPMhA5GBx9rp91hBsiWURlyWt0DMqMTq�VqcUEGNc267LrCzKJsFBHCNO53e8z2I0�-----END CERTIFICATE-----
16
masterport
ca_server
puppet or
puppet-ca
api endpoint
key
environment
https://goo.gl/8LyZzN
can't connect to puppet
$ gnutls-cli --port 8140 puppet.example.com� --x509cafile=ca.pem
$ openssl s_client -connect puppet.example.com:8140
GET /path/to/thing/you/want
Accept: PSON/YAML/Text/???
17
puppet
master
(puppetserver)
node
HTTPS/8140
lsof -i :8140
mtr
traceroute
ping
https://goo.gl/8LyZzN
in order to authenticate...
you must first authenticate.
18
https://goo.gl/8LyZzN
can't connect to puppet
$ curl --cert certs/cottage.pem --key private_keys/cottage.pem.orig --cacert certs/ca.pem https://puppet.example.com:8140/puppet/v3/environments | jq
…� "environments": {� "production": {� "settings": {� "modulepath": [� "/etc/puppetlabs/code/environments/production/modules",� "/etc/puppetlabs/code/modules",� "/opt/puppetlabs/puppet/modules"� ],� "manifest": "/etc/puppetlabs/code/environments/production/manifests",� "environment_timeout": 0,� "config_version": ""
19
https://goo.gl/8LyZzN
API FTW
$ curl --cacert certs/ca.pem \
--cert certs/cottage.pem \
--key private_keys/cottage.pem \
-H 'Accept: pson' \
https://puppet.example.com:8140/puppet/v3/catalog/cottage?environment=production \
> cottage.pson
20
catalog
https://goo.gl/8LyZzN
PSON
Puppet JSON → PSON
$ jq <pson>
$ curl … | jq
sed for JSON
$ jq .environment catalog.pson
$ jq .classes catalog.pson
$ jq '.resources | length' catalog.pson
$ jq '.resources[] | select(.type == "Stage")' catalog.pson
21
JQ?
https://goo.gl/8LyZzN
PSON
Puppet JSON → PSON
$ jq <pson>
$ curl … | jq
sed for JSON
$ jq .environment catalog.pson
$ jq .classes catalog.pson
$ jq '.resources | length' catalog.pson
$ jq '.resources[] | select(.type == "Stage")' catalog.pson
22
JQ?
Sometimes it's good to go...
https://goo.gl/8LyZzN
problems
connection
certificate
catalog compilation�catalog application�scope�pry
23
can't get certificate
24
openssl x509 -in cert.pem -text
puppet cert fingerprint host.example.com
puppet cert print host.example.com
puppet cert clean host.example.com
ntpq -p
chronyc sources
rm /etc/puppetlabs/puppet/ssl/*/hostname*
https://goo.gl/8LyZzN
Intermission
25
x.509
the
crash
course
x.509
PKI
CA
SSL
TLS
CRL
REQ
RSA
DSA
DH
PKCS7
PKCS8
PKCS12
MD2
MD5
SHA1
SHA256
SHA384
SHA512
PEM
DER
OID
RFC
KS
TS
BOB
ALICE
26
"ENCRYPTION"
"ENCRYPTION"
https://goo.gl/8LyZzN
x.509
PKI
CA
SSL
TLS
CRL
REQ
RSA
DSA
DH
PKCS7
PKCS8
PKCS12
MD2
MD5
SHA1
SHA256
SHA384
SHA512
PEM
DER
OID
RFC
KS
TS
BOB
ALICE
27
https://goo.gl/8LyZzN
x.509
Public Key Infrastructure
Certificate Authority
Trust
28
https://www.flickr.com/photos/genvessel/431100596
https://goo.gl/8LyZzN
x.509
29
ca.pem
puppet
master
CERTIFICATE
node
CA?
ca.pem
server
ca_server
https://goo.gl/8LyZzN
x.509
30
node.crt
ca.crt
puppet
master
CERTIFICATE
node
node.csr
node.crt
server
ca_server
cert me pls?
https://goo.gl/8LyZzN
x.509
31
puppet.pem
ca.pem
puppet
master
CERTIFICATE
node
server
ca_server
https://goo.gl/8LyZzN
OpenSSL
View Certificate:
openssl x509 -in ca.pem -text -noout |less
View Fingerprint:
openssl x509 -in ca.pem -fingerprint -noout
openssl x509 -in ca.pem -fingerprint -noout -sha256
Verify Certificate:
openssl verify -CAfile ca.pem puppet.pem
32
Validity
X509v3 Key Usage
SHA1 (default)
https://goo.gl/8LyZzN
OpenSSL (Puppet shortcuts)
View Certificate:
puppet cert print ca
View Fingerprint:
puppet cert fingerprint ca
List Certificates:
puppet cert list -a
33
https://goo.gl/8LyZzN
CRL
34
node.crt
ca.crt
puppet
master
CERTIFICATE
node
crl?
crl
crl
https://goo.gl/8LyZzN
CRL
# openssl crl -in crl.pem -text -noout |grep Serial
Serial Number: 02
# openssl x509 -in cert.pem -text -noout |grep Serial
Serial Number: 3 (0x3)
35
https://goo.gl/8LyZzN
CRL
# cat ca_crt.pem ca_crl.pem >combined.pem
# openssl verify -CAfile combined.pem -crl_check cottage.pem
cottage.pem: OK
# puppet cert clean cottage
Notice: Revoked certificate with serial 3�Notice: Removing file Puppet::SSL::Certificate cottage at 'puppet/ssl/ca/signed/cottage.pem'�Notice: Removing file Puppet::SSL::Certificate cottage at 'puppet/ssl/certs/cottage.pem'
# cat ca_crl.pem ca_crt.pem >combined.pem
36
again?
# openssl verify -CAfile combined.pem -crl_check cottage.pem
cottage.pem: CN = cottage�error 23 at 0 depth lookup:certificate revoked
https://goo.gl/8LyZzN
OpenSSL
# openssl rsa -noout -modulus -in ca_key.pem |sha256sum�69578e29c08c130d37c7c0141134f1cc4778445c7b7d1d96d253b86d6bf4ca38
# openssl x509 -noout -modulus -in ca_crt.pem |sha256sum�69578e29c08c130d37c7c0141134f1cc4778445c7b7d1d96d253b86d6bf4ca38
# [ $(openssl rsa …) == [ $(openssl x509) ]
37
Modulus
n = pq
BIG *RSE PRIME
https://goo.gl/8LyZzN
OpenSSL
# openssl rsa -noout -modulus -in ca_key.pem |sha256sum�69578e29c08c130d37c7c0141134f1cc4778445c7b7d1d96d253b86d6bf4ca38
# openssl x509 -noout -modulus -in ca_crt.pem |sha256sum�69578e29c08c130d37c7c0141134f1cc4778445c7b7d1d96d253b86d6bf4ca38
38
Modulus
n = pq
BIG *RSE PRIME
$ puppet agent -t
Error: Could not request certificate: The certificate retrieved from the master does not match the agent's private key.
Certificate fingerprint: D4:D3:76:F1:6B:51:83:3C:4B:72:69:BF:BC:B0:80:94:79:75:1A:3B:D8:29:F5:EF:81:2C:44:35:21:93:CE:FD
To fix this, remove the certificate from both the master and the agent and then start a puppet run, which will automatically regenerate a certificate.
On the master:
puppet cert clean cottage
On the agent:
1a. On most platforms: find /home/thomas/.puppetlabs/etc/puppet/ssl -name cottage.pem -delete
1b. On Windows: del "\home\thomas\.puppetlabs\etc\puppet\ssl\certs\cottage.pem" /f
2. puppet agent -t
The certificate retrieved from the master does not match the agent's private key.
https://goo.gl/8LyZzN
OpenSSL recap
39
https://goo.gl/8LyZzN
Problem workers
40
node
puppet
server
puppet
server
load
balancer
devel
problem
puppet
server
problem
production
mod_proxy_balancer
https://goo.gl/8LyZzN
Problem workers
41
puppet
server
--logdest /var/log/puppetlabs/puppetserver/problem.log
--debug
--profile
logrotate
https://goo.gl/8LyZzN
problem/bugfixes environments
configure r10k to make environments automatically
environment.conf
42
https://goo.gl/8LyZzN
Compiling
43
$ sudo puppet master \
--compile problem.example.com \
--debug --trace \
--logdest /tmp/problem.puppet.log \
--environment sandbox
{� "data": {� "resources": [� {� "title": "main",� "exported": false,� "tags": ["stage"],� "type": "Stage",� "parameters": {� "before": "Stage[post]",
JSON
Thu Oct 23 14:34:24 -0700 2014 Puppet (debug): Using settings: adding file resource 'bucketdir': 'File[/var/lib/puppet/bucket]{:loglevel=>:debug, :group=>"puppet", :ensure=>:directory, :links=>:follow, :owner=>"puppet", :backup=>false, :mode=>"750", :path=>"/var/lib/puppet/bucket"}'�Thu Oct 23 14:34:24 -0700 2014 Puppet (debug): Using settings: adding file resource 'publickeydir': 'File[/var/lib/puppet/ssl/public_keys]{:loglevel=>:debug, :group=>"puppet", :ensure=>:directory, :links=>:follow, :owner=>"puppet", :backup=>false, :mode=>"755", :path=>"/var/lib/puppet/ssl/public_keys"}'�Thu Oct 23 14:34:24 -0700 2014 Puppet (debug): Using settings: adding file resource 'plugindest': 'File[/var/lib/puppet/lib]{:loglevel=>:debug, :ensure=>:directory, :links=>:follow, :backup=>false, :path=>"/var/lib/puppet/lib"}'�Thu Oct 23 14:34:24 -0700 2014 Puppet (debug): Using settings: adding file resource 'fileserverconfig': 'File[/etc/puppet/fileserver.conf]{:loglevel=>:debug, :ensure=>:file, :links=>:follow, :backup=>false, :path=>"/etc/puppet/fileserver.conf"}'�
https://goo.gl/8LyZzN
Apply
44
$ sudo puppet apply \
--debug --trace \
--environment sandbox code.pp
$date = "+%S"
exec {'epoch':
command => "echo \$((`date $date` / 86400))",
path => '/bin:/usr/bin:/sbin:/usr/sbin',
}
Info: Applying configuration version '1415729233'
Debug: Exec[epoch](provider=posix): Executing 'echo $((`date +%S` / 86400))'
Debug: Executing 'echo $((`date +%S` / 86400))'
Notice: /Stage[main]/Main/Exec[epoch]/returns: executed successfully
https://goo.gl/8LyZzN
problems
connection
certificate
catalog compilation
catalog application�scope�pry
45
catalogs
46
https://goo.gl/8LyZzN
catalog
fails to compile
fails to apply
47
fails to compile
48
https://goo.gl/8LyZzN
help yourself
function verb() {� erb -P -x -T '-' $1 | ruby -c� is_ok $?�}
function vyaml() {� ruby -ryaml -e "YAML.load_file '$1'"� is_ok $?�}
function ppv() {� puppet parser validate $*� is_ok $?�}
function vepp() {
puppet epp validate $*
is_ok $?�}
49
function is_ok() {
if [ $1 == 0 ]; then
if [[ "$TERM" == *"xterm"* ]] || \
[[ "$TERM" == *"vt100"* ]]; then
echo -e "\033[1mSyntax \033[32;1mOk!\033[0m"
else
echo "Syntax Ok!"
fi
else
return $1
fi
}
https://goo.gl/8LyZzN
duplicate resource
separate into subclass ( package {'httpd'} )
virtual resources ( @user, @package, @service)
modulepath
puppet config print modulepath
50
root@puppet:~# puppet config print modulepath --environment production
/etc/puppet/environments/production/public:/etc/puppet/environments/production/modules
root@puppet:~# puppet config print modulepath --environment master
/etc/puppet/modules:/usr/share/puppet/modules
https://goo.gl/8LyZzN
problems
connection
certificate
catalog compilation
catalog application
scope�pry
51
fails to apply
52
https://goo.gl/8LyZzN
Unpredictable exec
#!/bin/bash
echo $JAVA_HOME
53
/home/javadev/.bashrc
JAVA_HOME=/your/face
It works for me!
puppet runs as
puppet
https://goo.gl/8LyZzN
Broken Service
service provider
hasstatus => true
54
/sbin/service $service status
/etc/init.d/$service status
/usr/bin/systemctl is-active $service
https://goo.gl/8LyZzN
Bad/Missing Variable
$one = "1"
file {"pcone":
path => "/tmp/pc$one",
ensure => 'directory',
}
file {"pc1":
path => "/tmp/pc1",
ensure => 'file',
}
55
Info: Caching catalog for puppet.example.com
Error: Evaluation Error: Error while evaluating a Resource Statement, Cannot alias File[pc1] to ["/tmp/pc1"] at /root/pc.pp:6; resource ["File", "/tmp/pc1"] already declared at /root/pc.pp:2 at /root/pc.pp:6:3 on node puppet.example.com
https://goo.gl/8LyZzN
Bad/Missing Variable
$PC = 'puppetconf'
pc {'one':� place => "/tmp/$PC",� type => "directory",� }
pc {'two':� place => "/tmp/$PC",� type => "file",� }
56
define pc (
String $place,
String $type,
) {
file {"$title":
path => $place,
ensure => $type,
}
}
Info: Caching catalog for puppet.example.com
Error: Evaluation Error: Error while evaluating a Resource Statement, Evaluation Error: Error while evaluating a Resource Statement, Cannot alias File[two] to ["/tmp/puppetconf"] at /root/define.pp:5; resource ["File", "/tmp/puppetconf"] already declared at /root/define.pp:5 at /root/define.pp:5:2 at /root/define.pp:15 on node puppet.example.com
https://goo.gl/8LyZzN
Printing - Notify
notify {"$variable": }
57
https://goo.gl/8LyZzN
chaining
notify {'something':
}->exec{'thingthatfails':
}->notify{'after': }
58
https://goo.gl/8LyZzN
Checking
exec{'before resolv.conf': � command => '/usr/local/bin/puppet-debug before resolv.conf',� require => Class['debug']�} -> file { '/etc/resolv.conf':� source => template("dns/resolv.conf"),� noop => true,�}
59
class debug { � file {'puppet-debug':� path => '/usr/local/bin/puppet-debug',� source => 'puppet:///modules/debug/puppet-debug',� mode => 0755,� }�}�
https://goo.gl/8LyZzN
Debug Script… just an example
#!/bin/bash
LOG=$(mktemp /tmp/puppet-debug.XXXXXX)
echo Puppet Debug -- $@ -- $(date) | tee $LOG
echo "-- Disk --" | tee -a $LOG
df -h |tee -a $LOG
df -i |tee -a $LOG
echo "-- Mem --" | tee -a $LOG
free | tee -a $LOG
echo "-- Files --" | tee -a $LOG
PUPPET=$(pgrep puppet)
for proc in $PUPPET
do
lsof -p $proc |tee -a $LOG
done
60
Puppet Debug -- before resolv.conf -- Fri Oct 24 01:13:34 EDT 2014
-- Disk --
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root
6.7G 2.5G 3.9G 39% /
tmpfs 246M 0 246M 0% /dev/shm
/dev/vda1 485M 80M 380M 18% /boot
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/VolGroup-lv_root
440640 79253 361387 18% /
tmpfs 62783 1 62782 1% /dev/shm
/dev/vda1 128016 50 127966 1% /boot
-- Mem --
total used free shared buffers cached
Mem: 502268 415488 86780 0 22176 172036
-/+ buffers/cache: 221276 280992
Swap: 835580 0 835580
-- Files --
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
puppet 2058 root cwd DIR 253,0 4096 14 /root
puppet 2058 root rtd DIR 253,0 4096 2 /
puppet 2058 root txt REG 253,0 10600 36617 /usr/bin/ruby
puppet 2058 root mem REG 253,0 156928 4134 /lib64/ld-2.12.so
puppet 2058 root mem REG 253,0 1926680 6282 /lib64/libc-2.12.so
https://goo.gl/8LyZzN
Printing - Template
61
file { "/tmp/puppet-debug.txt":� content => inline_template("<% vars = scope.to_hash.reject { |k,v| !( k.is_a?(String) && v.is_a?(String) ) }; vars.sort.each do |k,v| %><%= k %>=<%= v %>\n<% end %>"),� }�
vars = scope.to_hash.reject
{ |k,v| !( k.is_a?(String) &&
v.is_a?(String) ) };
vars.sort.each do |k,v|
k=v\n
end
https://goo.gl/8LyZzN
Printing - Template
62
_timestamp=2014-10-23 22:29:52 -0700
architecture=x86_64
augeasversion=1.0.0
bios_release_date=01/01/2011
bios_vendor=Bochs
bios_version=Bochs
blockdevice_vda_size=8589934592
blockdevice_vda_vendor=6900
blockdevices=vda
caller_module_name=
clientcert=cookbook.example.com
clientnoop=false
clientversion=3.7.1
concat_basedir=/var/lib/puppet/concat
domain=example.com
environment=production
facterversion=2.2.0
filesystems=ext4,iso9660
fqdn=cookbook.example.com
gid=root
hardwareisa=x86_64
hardwaremodel=x86_64
hostname=cookbook
id=root
interfaces=eth0,lo
https://goo.gl/8LyZzN
problems
connection
certificate�catalog compilation�catalog application�scope
pry
63
Scope
The scene:
64
class role::ntp {
include ntp
}
class ntp {
include ntp::server
}
https://goo.gl/8LyZzN
Scope
The solution:
65
class role::ntp {
include ::ntp
}
class ntp {
include ntp::server
}
https://goo.gl/8LyZzN
problems
connection
certificate�catalog compilation�catalog application�scope
pry
66
pry
IRB replacement
REPL
available at runtime
67
require 'pry'
…
# amazing code here
# wow, much amaze
…
binding.pry
…
https://goo.gl/8LyZzN
pry demo
68
module Puppet::Parser::Functions
newfunction(:pry) do |args|
require 'pry'
binding.pry
end
end
modules/pry/lib/puppet/parser/functions/pry.rb
node default {
…
pry()
…
}
manifests/site.pp
https://goo.gl/8LyZzN
pry demo
#
#
69
… �From:�/etc/puppetlabs/code/environments/production/modules/pry/lib/puppet/parser/functions/pry.rb @ line 4�#<Module:0xfb588d1>#real_function_pry:� 2: newfunction(:pry) do |args|� 3: require 'pry'� => 4: binding.pry� 5: end�[1] pry(#<Puppet::Parser::Scope>)>
puppet agent -t
puppetserver foreground
… �Puppet Server has successfully started and is now ready to handle requests
exit
… �Puppet Compiled Catalog for xxx.example.com in y.z seconds
Info: Caching catalog for xxx.example.com�Info: Applying configuration version 'XXX'
https://goo.gl/8LyZzN
where to go for help
70
https://goo.gl/8LyZzN
Summary
Puppet is an HTTPS service
End-to-end (gethostbyname, nc mtr)
OpenSSL is your friend (x509,crl, verify, s_client
make a debug class
remember scope
71
basic UNIX permissions
https://goo.gl/8LyZzN
72