Using r10k

r10k is an automation tool for Puppet environments. It is hosted on GitHub at https://github.com/puppetlabs/r10k. The project is used to speed up deployments when there are many environments and many Git repositories in use. From what we've covered so far, we can think of it as librarian-puppet and Git hooks in a single package. r10k takes the Git repositories specified in /etc/puppetlabs/r10k/r10k.yaml and checks out each branch of the repositories into a subdirectory of the environment directory (the environment directory is also specified in /etc/puppetlabs/r10k/r10k.yaml). If there is a Puppetfile in the root of the branch, then r10k parses the file in the same way that librarian-puppet does and it installs the specified modules in a directory named modules under the environment directory.

To use r10k, we'll replace our post-receive Git hook from the previous chapter with a call to r10k and we'll move our librarian-puppet configuration to a place where r10k is expecting it. We'll be running r10k as the puppet user, so we'll set up the puppet user with a normal shell and login files, as shown here:

[root@stand ~]# chsh -s /bin/bash puppet
Changing shell for puppet.
Shell changed.
[root@stand ~]# cp /etc/skel/.bash* ~puppet/
[root@stand ~]# chown puppet ~puppet/.bash*
[root@stand ~]# sudo -iu puppet
[puppet@stand ~]$

Now, install the r10k gem as shown here:

[root@stand ~]# puppet resource package r10k ensure=present provider=gem
Notice: /Package[r10k]/ensure: created
package { 'r10k':
ensure => ['2.0.3'],
}

Next, we'll create a /etc/puppetlabs/r10k/r10k.yaml file to point to our local Git repository. We will also specify that our Puppet environments will reside in /etc/puppetlabs/code/environments, as shown in the following snippet:

---
cachedir: '/var/cache/r10k'
sources:
control:
remote: '/var/lib/git/control.git'
basedir: '/etc/puppetlabs/code/environments'

Now, we need to create the cache directory and make it owned by the puppet user. We will use the following commands to do so:

[root@stand ~]# mkdir /var/cache/r10k
[root@stand ~]# chown puppet:puppet /var/cache/r10k

Now, we need to check out our code and add a Puppetfile to the root of the checkout. In each environment, create a Puppetfile that contains which modules you want installed in that environment; we'll copy the previous Puppetfile as shown in the following code:

forge "http://forge.puppetlabs.com"
mod 'puppetlabs/puppetdb', '5.0.0'
mod 'puppetlabs/stdlib', '4.9.0'

We'll check the syntax of our Puppetfile using r10k as shown here:

[samdev@stand control]$ cat Puppetfile 
forge "http://forge.puppetlabs.com"
mod 'puppetlabs/puppetdb', '5.0.0'
mod 'puppetlabs/stdlib', '4.9.0'
[samdev@stand control]$ r10k puppetfile check
Syntax OK

Now, add the Puppetfile to the Git repository using the following commands:

[samdev@stand control]$ git add Puppetfile
[samdev@stand control]$ git commit -m "adding Puppetfile"
[production 17d53ad] adding Puppetfile
 1 file changed, 3 insertions(+)
create mode 100644 Puppetfile

Now, r10k expects that the modules specified in the Puppetfile will get installed in $environment/modules, but we already have modules in that location. Move the existing modules into another directory using the following commands; dist or local are commonly used:

[samdev@stand control]$ git mv modules dist
[samdev@stand control]$ git commit -m "moving modules to dist"
[production d3909a3] moving modules to dist
 6 files changed, 0 insertions(+), 0 deletions(-)
rename {modules => dist}/base/manifests/init.pp (100%)
rename {modules => dist}/hostname_problem/manifests/init.pp (100%)
rename {modules => dist}/resolver/manifests/init.pp (100%)
rename {modules => dist}/syslog/manifests/init.pp (100%)
rename {modules => dist}/virtual/manifests/init.pp (100%)
rename {modules => dist}/web/manifests/init.pp (100%)

Now that our modules are out of the way, we don't want a modules directory to be tracked by Git, so add modules to .gitignore using the following commands:

[samdev@stand control]$ echo "modules/" >>.gitignore
[samdev@stand control]$ git add .gitignore 
[samdev@stand control]$ git commit -m "adding .gitignore"
[production e6a5a4a] adding .gitignore
 1 file changed, 1 insertion(+)
create mode 100644 .gitignore

Ok, we are finally ready to test. Well almost. We want to test r10k, so we need to disable our post-receive hook; just disable the execute bit on the script using the following commands:

[root@stand ~]# sudo -u git bash
[git@stand ~]$ cd /var/lib/git/control.git/hooks
[git@stand hooks]$ chmod -x post-receive

Now we can finally add our changes to the Git repository, using the following commands:

[git@stand hooks]$ exit
exit
[root@stand ~]# sudo -iu samdev
[samdev@stand ~]$ cd control
[samdev@stand control]$ git push origin production
Counting objects: 9, done.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (8/8), 946 bytes | 0 bytes/s, done.
Total 8 (delta 2), reused 0 (delta 0)
remote: production
remote: production change for samdev
To /var/lib/git/control.git/
   0d5cf62..e6a5a4a  production -> production

Note that the only remote lines in the output are related to our pre-receive hook since we no longer have a post-receive hook running.

We will be running r10k as the puppet user, so we'll need to ensure that the puppet user can access files in the /var/lib/git directory; we'll use Filesystem Access Control Lists (FACLs) to achieve this access as shown here:

[root@stand ~]# setfacl -m 'g:puppet:rwx' -R /var/lib/git
[root@stand ~]# setfacl -m 'g:puppet:rwx' -R -d /var/lib/git

Before we can use r10k, we need to clean out the environments directory using the following commands:

[samdev@stand control]$ exit
logout
[root@stand ~]# sudo chown puppet /etc/puppetlabs/code 
[root@stand ~]# sudo -iu puppet
[puppet@stand ~]$ cd /etc/puppetlabs/code
[puppet@stand code]$ mv environments environments.b4-r10k
[puppet@stand code]$ mkdir environments

Now we can test r10k using r10k deploy as follows:

[puppet@stand code]$ r10k deploy environment -p
[puppet@stand code]$ ls environments
master  production  puppet_sync  quiet  thomas

As we can see, r10k did a Git checkout of our code in the master, thomas, quiet, and production branches. We added a Puppetfile to the production branch; so, when we look in /etc/puppetlabs/code/environments/production/modules, we will see the puppetdb and stdlib modules defined in the Puppetfile:

[puppet@stand code]$ ls environments/production/modules
puppetdb  stdlib

We have now used r10k to deploy not only our code but the puppetdb and stdlib modules as well. We'll now switch our workflow to use r10k and change our post-receive hook to use r10k. Our post-receive hook will be greatly simplified; we'll just call r10k with the name of the branch and exit. Alternatively, we can have r10k run on every environment if we choose to; this way, it will only update a specific branch each time. To make the hook work again, we'll first need to enable the execute bit on the file, using the following commands:

[root@stand ~]# sudo -u git bash
[git@stand root]$ cd /var/lib/git/control.git/hooks/
[git@stand hooks]$ chmod +x post-receive

Next, we'll replace the contents of post-receive with the following script:

logout
#!/bin/bash
r10k=/usr/local/bin/r10k
read oldrev newrev refname
branch=${refname#*/*/}
if [ -z "$branch" ]; then
  echo "ERROR: Branch undefined"
  exit 10
fi

exec sudo -u puppet $r10k deploy environment $branch –p

Now, we need to edit our sudoers file to allow Git to run r10k as puppet, as shown here:

Defaults !requiretty
git ALL = (puppet) NOPASSWD: /bin/git *, /usr/bin/puppet-sync *,/usr/local/bin/r10k *
%pupdevs ALL = (puppet) NOPASSWD: /bin/git *, /usr/bin/puppet-sync *, /usr/local/bin/r10k *

Now, to test whether everything is working, remove a module from the production environment using the following command:

[root@stand ~]# 
m -rf /etc/puppetlabs/code/environments/production/modules/stdlib

Now, make a change in production and push that change to the origin to trigger an r10k run, as shown here:

[root@stand ~]# sudo -iu samdev
[samdev@stand ~]$ cd control/
[samdev@stand control]$ echo "Using r10k in post-receive" >>README
[samdev@stand control]$ git add README
[samdev@stand control]$ git commit -m "triggering r10k rebuild"
[production bab33bd] triggering r10k rebuild
 1 file changed, 1 insertion(+)
[samdev@stand control]$ git push origin production
Counting objects: 5, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 295 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: production
remote: production change for samdev
To /var/lib/git/control.git/
   422de2d..bab33bd  production -> production

Finally, verify whether the stdlib module was recreated or not using the following command:

[samdev@stand control]$ ls /etc/puppetlabs/code/environments/production/modules/
puppetdb  stdlib

Keeping everything in r10k allows us to have mini labs for developers to work on a copy of our entire infrastructure with a few commands. They will only need a copy of our Git repository and our r10k.yaml file to recreate the configuration on a private Puppet master.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset