Setting up r10k

Last time, we walked through setting up Puppet Server and PuppetDB using Puppet. This time, we will be adding r10k to the mix.

What is r10k?

r10k is a tool created by Puppet, Inc to manage configuration environments and code deployments to the Puppet Master. It is extremely simple to initially setup and get working, but also a bit difficult to master.

I won’t be going over the basic install and setup of r10k today, you can find that in the r10k documentation. If you are using Puppet 5.x, follow the directions for installing on Puppet 4.

We will be installing, setting up, and managing r10k using the puppet-r10k module and Puppet code. The puppet-r10k module not only will setup r10k, but can also install a Sinatra-based Web Server for recieving webhooks from your github/gitlab/git server to trigger deployments of environments and modules.

I strongly suggest reading about Puppet Environments before using r10k as the tool loses about half its usefulness without environments.

Installing puppet-r10k

Since we are still working without r10k on our Puppet Server, we will still have to manually deploy the puppet-r10k module to the Puppet Server:

puppet module install puppet-r10k

Now that you have r10k installed, we need to create a puppet-control git repository. The puppet-control repository is a git repo where code managment stores code and data to deploy to your puppet environments.

Unlike normal git repositories, you don’t have a master branch in an r10k control repo as each branch is dynamically mapped as a puppet environment. You will need create a production branch:

git checkout -b production

You will probably want to set production as the default branch on your git server, then delete master. See the docs for your specific tool on how to do this.

Now you will want to take all everything from the /etc/puppetlabs/code/environments/production directory and copy it to your new git repo, then commit and push to your server.

Now that the initial commit is out of the way, add the following code to your puppetserver node definition in the site.pp file from the last post:

node "puppetserver.local" {
  ...
  class { "::r10k":
    sources => {
      "r10k" => { # Arbitrary name of the r10k source
        "remote"  => "https://github.com/user/puppet-control", # Url of the git repository
        "basedir" => "/etc/puppetlabs/code/environments", # Directory to deploy environments to.
      }
    }
  }  
}

node "puppetdb.local" {
  ...
}

node default {}

The sources parameter from puppet-r10k is a hash of sources to deploy to the r10k environments.

The r10k key is an arbitrary name to identify each source. This key can be whatever name you’d like, but should probably descriptive of the environment or purpose of the source.

remote is the url to the Git repository. This can be https or ssh. If using ssh, be sure that ssh keys are created if required to give the root user read access into the puppet-control repository.

basedir is the directory to deploy the source control repo to. You can put whatever you like or require in there, I just put the default /etc/puppetlabs/code/environments directory there.

Now, we are going to add the webhook configuration to the same site.pp file. One very important note: You will HAVE to setup SSL certs for the Webhook service to use. Please see an OpenSSL Tutorial for more information. There are a LOT of them out there, I just linked a tutorial from the Linux Foundation.

Code to add to the site.pp under you Puppet Server node:

node "puppetserver.local" {
  ...
  ...

  class { "::r10k::webhook":
    user  => "root", # If using mcollective, set this to the mco user
    group => "root", # If using mcollective, set this to the mco group
  }

  class { "::r10k::webhook::config":
    use_mcollective  => false, # Defaults to true
    public_key_path  => "/etc/pki/tls/certs/puppetserver.local.public.pem",
    private_key_path => "/etc/pki/tls/private/puppetserver.local.pem",
  }
}

...

The code you added is setting the user that the Webhook will run as and is setting some configuration parameters for the webhook to run with.

Now commit your code and push it to the puppet-control repository. You will probably want to add this code to your Puppet Server’s site.pp as well since r10k hasn’t been installed and configured on the Puppet Server yet. Don’t worry about duplication, once r10k is setup it will replace the old code we had with the contents of the puppet-control repo’s production branch.

IMPORTANT NOTE: Make sure your Puppet Server has read access to the puppet-control repo’s git url

The final site.pp file should look like this:

node "puppetserver.local" {
  class { "::puppetdb::master::config":
    puppetdb_server => "puppetdb.local",
  }

  class { "::r10k":
    sources => {
      "r10k" => {
        "remote"  => "https://github.com/user/puppet-control",
        "basedir" => "/etc/puppetlabs/code/environments",
      },
    },
  }

  class { "::r10k::webhook":
    user  => "root",
    group => "root",
  }

  class { "::r10k::webhook::config":
    use_mcollective  => false,
    public_key_path  => "/etc/pki/tls/certs/puppetserver.local.public.pem",
    private_key_path => "/etc/pki/tls/private/puppetserver.local.pem",
  }
}

node "puppetdb.local" {
  class { "::puppetdb":
    ssl_listen_address   => "puppetdb.local",
    open_ssl_listen_port => true,
    postgres_version     => "9.6",
  }
}

node default {}

Now, run the puppet agent command to apply the new r10k configuration to your Puppet Server:

puppet agent -t

Awesome! Now we have r10k setup on the Puppet Server, but it’s still not working. We need to make sure the puppet-control repo is finished and the Puppet Server has read access to it.

We need to create a Puppetfile in the root of the puppet-control repo’s directory. This will contain a list of all the dependent Puppet Forge modules you use and your internal modules git urls. We will be only adding the Forge modules today.

Run the following command on your Puppet Server to get a list of installed modules:

puppet module list

Now, in your newly created Puppetfile, add the modules you see listed to the file using the following format:

mod "username-modulename", "version"

Example:

mod "puppet-r10k", "6.1.0

Repeat that for all the listed modules. Use only the versions you see in the puppet module list output.

NOTE: You won’t need puppetlabs-apt on a CentOS/RHEL system, despite a couple of modules listing it as a required dependency

Finally, commit to your git repository and push to the remote.

Your final puppet-control repo directory structure show now look like this:

production_branch
├── manifests
│   └── site.pp
└── Puppetfile

1 directory, 2 files

Puppetfile:

forge "https://forgeapi.puppet.com"

mod "gentoo-portage", "2.3.0"
mod "puppet-make", "1.1.0"
mod "pupept-r10k", "6.1.0"
mod "puppetlabs-concat", "4.0.1"
mod "puppetlabs-firewall", "1.9.0"
mod "puppetlabs-gcc", "0.3.0"
mod "puppetlabs-git", "0.5.0"
mod "puppetlabs-inifile", "1.6.0"
mod "puppetlabs-postgresql", "5.1.0"
mod "puppetlabs-puppetdb", "6.0.1"
mod "puppetlabs-ruby", "1.0.0"
mod "puppetlabs-stdlib", "4.17.1"
mod "puppetlabs-vcsrepo", "1.5.0"

site.pp:

node "puppetserver.local" {
  class { "::puppetdb::master::config":
    puppetdb_server => "puppetdb.local",
  }

  class { "::r10k":
    sources => {
      "r10k" => {
        "remote"  => "https://github.com/user/puppet-control",
        "basedir" => "/etc/puppetlabs/code/environments",
      },
    },
  }

  class { "::r10k::webhook":
    user  => "root",
    group => "root",
  }

  class { "::r10k::webhook::config":
    use_mcollective  => false,
    public_key_path  => "/etc/pki/tls/certs/puppetserver.local.public.pem",
    private_key_path => "/etc/pki/tls/private/puppetserver.local.pem",
  }
}

node "puppetdb.local" {
  class { "::puppetdb":
    ssl_listen_address   => "puppetdb.local",
    open_ssl_listen_port => true,
    postgres_version     => "9.6",
  }
}

node default {}

Now, back on your Puppet Server, run the follow command to deploy the puppet-control repo to your production environment:

r10k deploy environment production -v

The above will deploy everything in the production environment and print out verbose output for user feedback. Again, I can’t stress this enough, make sure your Puppet Server has access to the repository before trying the command, otherwise it will error out. The error is entirely dependent on the tool being used.

That’s it for setting it up, you’re done.

Next Steps:

  • Add a webhook from your git server/service to the Puppet Server to trigger deployments on pushes, CI jobs, etc. See the Webhook Documentation for puppet-r10k for more information about this. The Git tool MUST have access to the Puppet Server for this to work.
  • Setup Hiera to make changing settings simpler without having to edit and deploy code releases (next post).

Resources

Contact

Did this post help you? Was it confusing? I’d love Feedback!

Contact me if you have any questions or feedback: