Puppet has the concept of ‘environments’ where you can logically separate your modules and manifest (read: site.pp) into separate folders to allow for nodes to get entirely separate bits of code based on which ‘environment’ the node belongs to.
Puppet Environments are statically set in puppet.conf.
A Puppet master server can serve each environment with completely different main manifests and module paths.
This frees you to use different versions of the same modules for different populations of nodes, which is useful for testing changes to your Puppet code before implementing them on production machines. (You could also do this by running a separate Puppet master for testing, but using environments are often easier.)
Our Puppet Environments
One of the features offered by Puppet is the ability to break up infrastructure configuration into environments. With environments, you can use a single Puppet master to serve multiple isolated configurations. For instance, you can adopt the development, testing and production series of environments embraced by a number of software development life cycles and by application frameworks such as Ruby on Rails, so that new functionality can be added incrementally without interfering with production systems. Environments can also be used to isolate different sets of machines. A good example of this functionality would be using one environment for web servers and another for databases, so that changes made to the web server environment don’t get applied to machines that don’t need that configuration.
Mapping the Puppet code base against the environments shows the power of this method. People often use a version control system to manage the code, and create a set of branches that each map to an environment. Adopting the development, testing and production workflow, we can have a puppet.conf that looks something like this:
[main] server = puppet.example.com environment = production confdir = /etc/puppet [agent] report = true show_diff = true [production] manifest = /etc/puppet/environments/production/manifests/site.pp modulepath = /etc/puppet/environments/production/modules [testing] manifest = /etc/puppet/environments/testing/manifests/site.pp modulepath = /etc/puppet/environments/testing/modules [development] manifest = /etc/puppet/environments/development/manifests/site.pp modulepath = /etc/puppet/environments/development/modules
With this configuration, we could map three Git branches for these environments and set up a central Git repository with post receive hooks. When changes were pushed to this repository, they would be automatically deployed to the puppet master.
How Code Manager works
Under the hood, Code Manager uses r10k and the file sync service to stage, commit, and sync your code, automatically managing your directory environments and modules.
First, you’ll create a control repository with branches for each environment that you want to create (such as production, development, or testing). You’ll also create Puppet files for your environments, specifying exactly which modules to install in each environment. This allows r10k to create directory environments, based on the branches you’ve set up.
When you push code to your control repo, you’ll trigger Code Manager to pull that new code into a staging code directory (/etc/puppetlabs/code-staging). File sync, then picks up those changes, pauses Puppet Server to avoid conflicts, and then syncs the new code to the live code directories on your Puppet masters.
Code Manager is built into Puppet Enterprise. Set up a default configuration of Code Manager, and then, if you require a more customized solution, you can customize your configuration by using Hiera.
r10k is a code management tool that allows you to manage your environment configurations (such as production, testing, and development) in a source control repository. Based on the code in your control repo branches, r10k creates environments on your master and installs and updates the modules you want in each environment.
As of PE 2015.3, we encourage you to use Code Manager, which works with r10k to automate the deployment of your code. If you use Code Manager, you won’t manage or interact with r10k manually. Instead, go to the Code Manager page to begin setup. However, if you’re already using r10k and aren’t ready to switch to Code Manager, you can continue using r10k alone.
$ mco r10k synchronize
Your puppet system is now ready for automation. You have R10K configured and your system has MCollective ready to push R10K updates. If you have multiple puppet masters, simply install the same R10K plugins for all your puppet masters. Then running the synchronize MCollective command will update all your puppet masters at once from one location. Later, we will configure Jenkins as an MCollective client that will be able to update our modules and deploy them to our client system using our Jenkins script automation.
Puppet Environments Explained
Puppet has the ability to support different Environments. An environment is kind of like a Puppet virtual Host – it’s a completely different Puppet configuration set hosted under a single Puppet Master.
One cool trick that came out a few years ago was to map git branches to Puppet environments. This practice became known as as Dynamic Environments. The big benefit that Dynamic Environments introduced was the ability to create new and cheap Puppet environments just as you would with Git branches.
More people are beginning to work on the Puppet servers. In addition, some of the testing environments have slowly graduated to a sort of production environment where people quickly notice when something is broke. Finally, some of the Puppet servers that were deployed for specific projects might be able to be combined under a single Puppet Master.
A git-branch-per-environment scenario can assist with resolving these issues.
Configure R10K dynamic environments
We need to configure our R10K dynamic environments to represent our non-production and production networks. R10K makes this simple in that all we have to do is branch our control repository, push our changes to git and run R10K on our puppet master. To create our new branch, run the following command:
$ git checkout -b non-prod
To see all our branches:
$ git branch
Commit your changes back to the git server
$ git add .
$ git commit -m “adding new nonprod environment”
$ git push origin nonprod
Now, on your puppet master run R10K to deploy the two environments.
$ r10k deploy environment -pv
Our two environments now exist on our puppet master with all the modules specified in the Puppetfile for each environment and corresponding hiera data.
Connecting agents to our environments
The last step for configuring our puppet environment is to get our agents connected to their environments. We do this from the Puppet Enterprise Console. Go to Nodes then click on Classification. Click on Agent specified environment:
Here you can either configure a rule that will put matching nodes into the nonprod environment or you can pin specific nodes. We will create a rule that will match any nodes that have an non blank environment (so basically all nodes specify their own environment). Since the default is production, then we won’t have any issues.
Go to your agent and configure the puppet.conf to specify an environment of nonprod:
Finally, perform a puppet run and you will see that our agent is now pulling from the nonprod puppet environment.
Our production agent doesn’t need any special configuration because the default puppet environment is production. You now have your puppet environment ready for continuous delivery.
Ravindra Savaram is a Content Lead at Mindmajix.com. His passion lies in writing articles on the most popular IT platforms including Machine learning, DevOps, Data Science, Artificial Intelligence, RPA, Deep Learning, and so on. You can stay up to date on all these technologies by following him on LinkedIn and Twitter.