PuppetCamp Ghent - What Not to Do with Puppet
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

PuppetCamp Ghent - What Not to Do with Puppet

on

  • 1,209 views

An interactive journey through the ugly side of Puppet by Walter Heck, founder & CEO of OlinData.

An interactive journey through the ugly side of Puppet by Walter Heck, founder & CEO of OlinData.

Statistics

Views

Total Views
1,209
Views on SlideShare
866
Embed Views
343

Actions

Likes
0
Downloads
3
Comments
0

1 Embed 343

http://olindata.com 343

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

PuppetCamp Ghent - What Not to Do with Puppet Presentation Transcript

  • 1. Puppet: What_not_ to do? An interactive journey through the ugly sideof Puppet
  • 2. •Walter Heck, Founder of OlinData•2,5 years experience with Puppet in 5+different environments•Experienced Puppet Fundamentals trainer•Had my eyes bleed many times with uglyPuppet code
  • 3. • Design mistakes might not be glaringly obvious or even wrong at first, but will cause trouble later• Language mistakes Puppet provides functionality that shouldnt be used, but is there for edge- cases or historical purposes
  • 4. Quiz time! Wake up...
  • 5. == File: modules/ssh/manifests/ssh.ppclass ssh_install { package { ssh: ensure => present }}class ssh_configure { file { /etc/ssh/sshd_config: ensure => present }}
  • 6. == File: modules/ssh/manifests/ssh.ppclass ssh($state = ‘present’ { package { ssh: ensure => $state } file { /etc/ssh/sshd_config: ensure => $state }}# problem: classnames wont be autoloaded, classnames shouldnt have verbs in them,classes should be combined, dont put multiple classes in a file
  • 7. ==schedule { maint: range => 2 - 4, period => daily, repeat => 1,}exec { /usr/bin/apt-get update: schedule => maint,}
  • 8. ==schedule { maint: range => 2 - 4, period => daily, repeat => 1,}exec { /usr/bin/apt-get update: schedule => maint,}# problem: schedule doesnt mean something will execute, a common pitfall.If there is no puppet run between these hours, the apt-get exec will not be run
  • 9. ==$myvar = ‘false’if ($myvar) { notice(‘this is true’)} else { notice(‘This is false’)}
  • 10. ==$myvar = ‘false’if ($myvar) { notice(‘this is true’)} else { notice(‘This is false’)}#problem: false evaluates totrue
  • 11. ==exec { /etc/init.d/apache start: onlyif => ‘ps aux | grep apache | grep -v grep |wc -l’}
  • 12. ==exec { /etc/init.d/apache start: onlyif => ‘ps aux | grep apache | grep -v grep |wc -l’}# problem: this shouldnt be an exec, but aservice
  • 13. ==package { ssh: ensure => present, name => $::operatingsystem ? { Ubuntu => openssh-server, default => ssh, },}
  • 14. ==$sshpkgname = $::operatingsystem ? { Ubuntu => openssh-server, default => undef,}if ($sshpkgname == undef) { fail(‘unsupported OS’)} else { package { ssh: ensure => present, name => $sshpkgname, }}#problem: they encourage behaviour that is not scalable, using default options toassume things, etc.
  • 15. ==case $::operatingsystem { RedHat, CentOS: { file { ‘/etc/httpd/http.conf’: ensure => ‘present’, } } default: { file { ‘/etc/apache2/apache2.conf’: ensure => ‘present’, } }}
  • 16. ==case $::operatingsystem { RedHat, CentOS: { file { ‘/etc/httpd/http.conf’: ensure => ‘present’, } } default: { file { ‘/etc/apache2/apache2.conf’: ensure => ‘present’, } }}#problem: case without default that fails, instead it assumes
  • 17. ==class wordpress { $wordpress_archive = wordpress-3.4.1.zip $apache = $::operatingsystem ? { Ubuntu => apache2, CentOS => httpd, Debian => apache2, default => httpd } $phpmysql = $::operatingsystem ? { Ubuntu => php5-mysql, CentOS => php-mysql, Debian => php5-mysql, default => php-mysql } $php = $::operatingsystem ? { Ubuntu => libapache2-mod-php5, CentOS => php, Debian => libapache2-mod-php5, default => php } package { [unzip,$apache,$php,$phpmysql]: ensure => latest }}
  • 18. ==class wordpress { $wordpress_archive = wordpress-3.4.1.zip $apache = $::operatingsystem ? { Ubuntu => apache2, CentOS => httpd, Debian => apache2, default => httpd } $phpmysql = $::operatingsystem ? { Ubuntu => php5-mysql, CentOS => php-mysql, Debian => php5-mysql, default => php-mysql } $php = $::operatingsystem ? { Ubuntu => libapache2-mod-php5, CentOS => php, Debian => libapache2-mod-php5, default => php } package { [unzip,$apache,$php,$phpmysql]: ensure => latest }}#wordpress class shouldnt touch apache, should be a different module
  • 19. ==$files = [ /etc/mysql, /var/log/mysql,/var/run/mysql ]file { $files: ensure => present, user => mysql, group => mysql, mode => 0755,}
  • 20. ==#arrays of resources are not wrong, but dangerous.file { /etc/mysql: ensure => present, user => mysql, group => mysql, mode => 0700, <=== careful with this!}file { /var/log/mysql: ensure => present, user => mysql, group => mysql, mode => 0755,}file { /var/run/mysql: ensure => present, user => mysql, group => mysql, mode => 0755,}
  • 21. ==if defined(File[/tmp/foo]) { notify(This configuration includes the /tmp/foo file.)} else { file {/tmp/foo: ensure => present, }}
  • 22. ==class test { if defined(File[/tmp/foo]) { notice(This configuration includes the /tmp/foo file.) } else { file {/tmp/foo: ensure => present, group => root } } if defined(File[/tmp/foo]) { notice(This configuration includes the /tmp/foo file.) } else { file {/tmp/foo: ensure => present, group => puppet } }}include testdefined() is (usually) the wrong solution to a resource defined in two locations. It isdangerous, because it only checks if the resource has been defined elsewhere, not withwhat attributes.
  • 23. ==class apache2 {file { /etc/apache2: ensure => directory, require => Service[apache2]}file { /etc/apache2/apache2.conf: ensure => present, require => File[/etc/apache2], notify => Service[apache2],}package { apache2: ensure => present, allowcdrom => true, before => File[/etc/apache2/apache2.conf]}service { apache2: ensure => running, subscribe => File[/etc/apache2/apache2.conf]}}include apache2
  • 24. ==# dependency loopclass apache2 {file { /etc/apache2: ensure => directory, require => Service[apache2]}file { /etc/apache2/apache2.conf: ensure => present, require => File[/etc/apache2], notify => Service[apache2], # <=== The notify metaparameter implies before.}package { apache2: ensure => present, allowcdrom => true, before => File[/etc/apache2/apache2.conf]}service { apache2: ensure => running, subscribe => File[/etc/apache2/apache2.conf] # <=== The subscribe metaparameter impliesrequire.
  • 25. class test { file { /tmp/somefile.txt: ensure => file, mode => 0600, owner => root, group => root, source => /etc/puppet/modules/test/somefile.txt }}include test
  • 26. ==# use puppet:///modules/ instead of the full path on the puppet masterclass test { file { /tmp/somefile.txt: ensure => file, mode => 0600, owner => root, group => root, source => puppet:///modules/test/somefile.txt }}include test
  • 27. ==class test { file {‘/tmp/large/dir/with/many/subdirs/and/many/files’: ensure => present, owner => root, group => root, recurse => true }}include test
  • 28. ==# do not use recurse => true on a dir with over 100+ filesclass test { file {‘/tmp/large/dir/with/many/files’: ensure => present, owner => root, group => root, recurse => true }}include test# alternative :’(class test { exec {/bin/chown -R root:root /tmp/large/dir/with/many/files: }}
  • 29. Walter Heck - OlinData Email: walterheck@olindata.com Twitter: @walterheck / @olindata Web: http://olindata.comQuestions? Feel free to get in touch!