DevOps:Puppet,Docker,and Kubernetes
上QQ阅读APP看书,第一时间看更新

Creating a decentralized Puppet architecture

Puppet is a configuration management tool. You can use Puppet to configure and prevent configuration drift in a large number of client computers. If all your client computers are easily reached via a central location, you may choose to have a central Puppet server control all the client computers. In the centralized model, the Puppet server is known as the Puppet master. We will cover how to configure a central Puppet master in a few sections.

If your client computers are widely distributed or you cannot guarantee communication between the client computers and a central location, then a decentralized architecture may be a good fit for your deployment. In the next few sections, we will see how to configure a decentralized Puppet architecture.

As we have seen, we can run the puppet apply command directly on a manifest file to have Puppet apply it. The problem with this arrangement is that we need to have the manifests transferred to the client computers.

We can use the Git repository we created in the previous section to transfer our manifests to each new node we create.

Getting ready

Create a new test node, call this new node whatever you wish, I'll use testnode for mine. Install Puppet on the machine as we have previously done.

How to do it...

Create a bootstrap.pp manifest that will perform the following configuration steps on our new node:

  1. Install Git:
    package {'git':
      ensure => 'installed'
    }
  2. Install the ssh key to access git.example.com in the Puppet user's home directory (/var/lib/puppet/.ssh/id_rsa):
    File {
      owner => 'puppet',
      group => 'puppet',
    }
    file {'/var/lib/puppet/.ssh':
      ensure => 'directory',
    }
    file {'/var/lib/puppet/.ssh/id_rsa':
      content => "
    -----BEGIN RSA PRIVATE KEY-----
    …
    NIjTXmZUlOKefh4MBilqUU3KQG8GBHjzYl2TkFVGLNYGNA0U8VG8SUJq
    -----END RSA PRIVATE KEY-----
    ",
      mode    => 0600,
      require => File['/var/lib/puppet/.ssh']
    }
  3. Download the ssh host key from git.example.com (/var/lib/puppet/.ssh/known_hosts):
    exec {'download git.example.com host key': 
      command => 'sudo -u puppet ssh-keyscan git.example.com >> /var/lib/puppet/.ssh/known_hosts',
      path    => '/usr/bin:/usr/sbin:/bin:/sbin',
      unless  => 'grep git.example.com /var/lib/puppet/.ssh/known_hosts',
      require => File['/var/lib/puppet/.ssh'],
    }
  4. Create a directory to contain the Git repository (/etc/puppet/cookbook):
    file {'/etc/puppet/cookbook':
      ensure => 'directory',
    }
  5. Clone the Puppet repository onto the new machine:
    exec {'create cookbook':
      command => 'sudo -u puppet git clone git@git.example.com:repos/puppet.git /etc/puppet/cookbook',
      path    => '/usr/bin:/usr/sbin:/bin:/sbin',
      require => [Package['git'],File['/var/lib/puppet/.ssh/id_rsa'],Exec['download git.example.com host key']],
      unless  => 'test -f /etc/puppet/cookbook/.git/config',
    }
  6. Now when we run Puppet apply on the new machine, the ssh key will be installed for the Puppet user. The Puppet user will then clone the Git repository into /etc/puppet/cookbook:
    root@testnode /tmp# puppet apply bootstrap.pp 
    Notice: Compiled catalog for testnode.example.com in environment production in 0.40 seconds
    Notice: /Stage[main]/Main/File[/etc/puppet/cookbook]/ensure: created
    Notice: /Stage[main]/Main/File[/var/lib/puppet/.ssh]/ensure: created
    Notice: /Stage[main]/Main/Exec[download git.example.com host key]/returns: executed successfully
    Notice: /Stage[main]/Main/File[/var/lib/puppet/.ssh/id_rsa]/ensure: defined content as '{md5}da61ce6ccc79bc6937bd98c798bc9fd3'
    Notice: /Stage[main]/Main/Exec[create cookbook]/returns: executed successfully
    Notice: Finished catalog run in 0.82 seconds
    

    Note

    You may have to disable the tty requirement of sudo. Comment out the line Defaults requiretty at /etc/sudoers if you have this line.

    Alternatively, you can set user => Puppet within the 'create cookbook' exec type. Beware that using the user attribute will cause any error messages from the command to be lost.

  7. Now that your Puppet code is available on the new node, you can apply it using puppet apply, specifying that /etc/puppet/cookbook/modules will contain the modules:
    root@testnode ~# puppet apply --modulepath=/etc/puppet/cookbook/modules /etc/puppet/cookbook/manifests/site.pp 
    Notice: Compiled catalog for testnode.example.com in environment production in 0.12 seconds
    Notice: /Stage[main]/Base/File[/etc/motd]/content: content changed '{md5}86d28ff83a8d49d349ba56b5c64b79ee' to '{md5}4c4c3ab7591d940318279d78b9c51d4f'
    Notice: Finished catalog run in 0.11 seconds
    root@testnode /tmp# cat /etc/motd
    testnode.example.com
    Managed by puppet 3.6.2
    

How it works...

First, our bootstrap.pp manifest ensures that Git is installed. The manifest then goes on to ensure that the ssh key for the Git user on git.example.com is installed into the Puppet user's home directory (/var/lib/puppet by default). The manifest then ensures that the host key for git.example.com is trusted by the Puppet user. With ssh configured, the bootstrap ensures that /etc/puppet/cookbook exists and is a directory.

We then use an exec to have Git clone the repository into /etc/puppet/cookbook. With all the code in place, we then call puppet apply a final time to deploy the code from the repository. In a production setting, you would distribute the bootstrap.pp manifest to all your nodes, possibly via an internal web server, using a method similar to curl http://puppet/bootstrap.pp >bootstrap.pp && puppet apply bootstrap.pp