Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Puppet Modules: Apps for Ops

Puppet Modules: Apps for Ops

Justin Bronn

April 11, 2014
Tweet

Other Decks in Programming

Transcript

  1. Don’t Repeat Yourself • Even a “simple” web application has

    a large number of components • You don’t want to configure them manually
  2. Why Puppet? • Mature (in Licensing & Security) • “Explicit

    is better than Implicit” • Wide OS support: • Linux (of course), Windows, Mac • OpenBSD, Solaris, AIX,HP-UX
  3. Ubuntu 12.04 $ sudo gem install \! --bindir /usr/local/bin! puppet

    $ sudo apt-get -y install \! libruby libshadow-ruby1.8 rubygems Packages also available: apt.puppetlabs.com
  4. OS X $ sudo gem install \! --bindir /usr/local/bin! puppet

    Package also available: https://downloads.puppetlabs.com/mac/
  5. Overview • Puppet, the language, is a Ruby DSL •

    Puppet code lives in files called “manifests”; files end with “.pp” suffix
  6. Overview • Catalog: compiled Puppet code, describes relationships between “resources”

    • Catalog is a an directed acyclic graph • Puppet applies catalog, bringing system into state declared in manifests
  7. $ssh_dir = '/etc/ssh'! file { $ssh_dir:! ensure => directory,! owner

    => 'root',! group => 'root',! mode => '0755',! }! $ssh_dir = '/foo/ssh'!
  8. $ssh_dir = '/etc/ssh'! file { $ssh_dir:! ensure => directory,! owner

    => 'root',! group => 'root',! mode => '0644',! }!
  9. $array = ['foo', 'bar']! ! $hash = {'key' => 'value'}!

    $value = $hash['key']! ! $py_versions = split('2.7,3.4', ',')! Data Structures / Function Call
  10. if $python_version == '3.4' {! notice('You have asyncio!')! } !

    ! case $python_version {! /^(2.6|2.7)$/: {! }! '3.4': {! }! default: {! fail('Unsupported version!')! }! }! Flow Control
  11. $ facter | less! ! $ facter fqdn ipaddress osfamily!

    fqdn => puppet.local! ipaddress => 10.0.2.15! osfamily => Debian!
  12. if $::osfamily == 'RedHat' {! $py_dev_pkg = 'python-devel'! } elsif

    $::osfamily == 'Debian'{! $py_dev_pkg = 'python-dev'! }! ! ! $:: gives you facts in Puppet
  13. if $::osfamily == 'RedHat' {! $py_dev_pkg = 'python-devel'! } elsif

    $::osfamily == 'Debian'{! $py_dev_pkg = 'python-dev'! }! ! ! $:: gives you facts in Puppet
  14. $sshd_config = "${ssh_dir}/sshd_config"! ! file {$sshd_config:! ensure => file,! owner

    => 'root',! group => 'root',! mode => '0644',! content => template('sshd_config.erb'),! require => Package['openssh-server'],! }
 Require Metaparameter
  15. $sshd_config = "${ssh_dir}/sshd_config"! ! file {$sshd_config:! ensure => file,! owner

    => 'root',! group => 'root',! mode => '0644',! content => template('sshd_config.erb'),! require => Package['openssh-server'],! }
 Require Metaparameter
  16. service {'ssh':! ensure => running,! enable => true,! subscribe =>

    File[$sshd_config],! }
 Subscribe Metaparameter
  17. service {'ssh':! ensure => running,! enable => true,! subscribe =>

    File[$sshd_config],! }
 Subscribe Metaparameter
  18. file { $sshd_config:! ...! notify => Service['ssh'],! ...! }
 service

    {'ssh':! ensure => running,! enable => true,! } Notify Metaparameter
  19. file { $sshd_config:! ...! notify => Service['ssh'],! ...! }
 service

    {'ssh':! ensure => running,! enable => true,! } Notify Metaparameter
  20. Modules • Containers for Puppet code • Analogous to Python

    Packages • May be installed from a Puppet “Forge”
  21. $ puppet module install counsyl-python Notice: Preparing to install into

    /Users/justin/.puppet/modules ...! Notice: Downloading from https://forge.puppetlabs.com ...! Notice: Installing -- do not interrupt ...! /Users/justin/.puppet/modules! !"# counsyl-python (v0.9.3)! !"# counsyl-sys (v0.9.13)! !"" puppetlabs-stdlib (v4.1.0)! !
  22. file { ‘/path/to/settings.py':! ensure => file,! owner => 'root',! group

    => 'root',! mode => '0644',! content => template('pyapp/settings.py.erb'),! } Puppet Templates
  23. file { ‘/path/to/settings.py':! ensure => file,! owner => 'root',! group

    => 'root',! mode => '0644',! content => template('pyapp/settings.py.erb'),! } Puppet Templates pyapp/templates/settings.py.erb
  24. file { '/path/to/foo.js':! ensure => file,! owner => 'root',! group

    => 'root',! mode => '0644',! source => 'puppet:///modules/pyapp/foo.js'! } Puppet Files
  25. file { '/path/to/foo.js':! ensure => file,! owner => 'root',! group

    => 'root',! mode => '0644',! source => 'puppet:///modules/pyapp/foo.js'! } Puppet Files pyapp/files/foo.js
  26. package {'Django':! ensure => '1.6.2',! provider => 'pipx',! install_options =>

    [! {'--index-url' => ! 'https://pypi.mycorp.com'}! ]! }
 pipx provider
  27. package {'Django':! ensure => '1.6.2',! provider => 'pipx',! install_options =>

    [! {'--index-url' => ! 'https://pypi.mycorp.com'}! ]! }
 pipx provider
  28. package {'Django':! ensure => '1.6.2',! provider => 'pipx',! install_options =>

    [! {'--index-url' => ! 'https://pypi.mycorp.com'}! ]! }
 pipx provider
  29. class pyapp(! $venv = '/srv/pyapp',! $package = 'pyapp',! $source =

    'git+https://...',! $version = '0.1.0',! ){! ...! venv { $venv: }! venv_package { "${package}@${venv}":! ensure => $version,! source => $source,! }! ...! }
  30. class pyapp(! $venv = '/srv/pyapp'! $package = 'pyapp',! $source =

    'git+https://...' ! $version = '0.1.0',! ){! ...! venv { $venv: }! venv_package { "${package}@${venv}":! ensure => $version,! source => $source,! }! ...! }
  31. ERB

  32. ERB: Ruby Templates • This time, it’s Ruby • Great

    for when you need dynamic content in a configuration file (e.g., ServerName)
  33. DATABASES = {! 'NAME': '<%= @db %>',! }! ! NGINX_CONFIG

    = '<%= scope['nginx::config_file'] %>'! SERVER_NAME = '<%= scope['::fqdn'] %>'! ! <% ! db_folder = File.dirname(@db_name)! -%>! DB_FOLDER = '<%= db_folder %>'! ERB
  34. DATABASES = {! 'NAME': '<%= @db %>',! }! ! NGINX_CONFIG

    = '<%= scope['nginx::config_file'] %>'! SERVER_NAME = '<%= scope['::fqdn'] %>'! ! <% ! db_folder = File.dirname(@db_name)! -%>! DB_FOLDER = '<%= db_folder %>'! ERB
  35. DATABASES = {! 'NAME': '<%= @db %>',! }! ! NGINX_CONFIG

    = '<%= scope['nginx::config_file'] %>'! SERVER_NAME = '<%= scope['::fqdn'] %>'! ! <% ! db_folder = File.dirname(@db_name)! -%>! DB_FOLDER = '<%= db_folder %>'! ERB
  36. DATABASES = {! 'NAME': '<%= @db %>',! }! ! NGINX_CONFIG

    = '<%= scope['nginx::config_file'] %>'! SERVER_NAME = '<%= scope['::fqdn'] %>'! ! <% ! db_folder = File.dirname(@db_name)! -%>! DB_FOLDER = '<%= db_folder %>'! ERB
  37. The Puppetmaster • Centralized server for housing modules and configurations

    for nodes (servers) • Secured with HTTPS Client Certificates • Nodes must have certificate signed to receive configuration
  38. Node Master node$ sudo puppet agent —test! Info: Creating a

    new SSL key for node.local! Exiting; no certificate found
  39. Node Master node$ sudo puppet agent —test! info: Caching certificate

    for node.local! info: Retrieving plugin! info: Caching catalog for node.local! info: Applying configuration version '1326210629'! notice: Finished catalog run in 0.11 seconds /etc/puppet/modules /etc/puppet/manifests
  40. Vagrant • A must-have for DevOps development in general, not

    just Puppet • Also supports Ansible, Salt, Chef • You may think you can do better…
  41. Vagrantfile • Tells Vagrant what to do • An API

    for provisioning a VM (actually Ruby + magic) • Forward ports, change memory, multiple provisioners, multiple VMs, multiple NICs…
  42. Puppet Provisioner Vagrant.configure('2') do |config|! ...! config.vm.provision "puppet" do |puppet|!

    puppet.facter = { "vagrant" => "1" }! puppet.module_path = "modules"! end! ...! end
  43. Puppet Provisioner Vagrant.configure('2') do |config|! ...! config.vm.provision "puppet" do |puppet|!

    puppet.facter = { "vagrant" => "1" }! puppet.module_path = "modules"! end! ...! end Looks for manifests/default.pp
  44. Another Ruby DSL? • Yeah… • Tremendous workflow benefits •

    Much easier to share your snowflake environments
  45. vagrant up • All end user has to do is

    type this command • No waiting for a server/sysadmin • Can get to work
  46. Packer • Virtual Machine image creation tool • Written in

    Go, uses JSON templates • See my sample for creating a base box: • https://github.com/jbronn/packer-vagrant