Creating environments

A classic organization has a minimum of two environments in which the infrastructure is run: development and production. Very often, a lot of environments are seen, such as staging, testing, alpha or beta. It's entirely up to the organization to model the infrastructure according to its needs, and the complexity can grow very quickly. The good news is that Chef helps a lot in mapping this model to the infrastructure. There's a set of information that will be different in two distinct environments, such as cookbook versions or attributes, and Chef makes it as easy as possible to manage these environments. By default, nodes without an environment set will run in a _default environment.

In this section, we'll see how to create different environments, how to set nodes (both existing and new) in a dedicated environment, how to set cookbook constraints, and finally how to override the attributes in each environment.

Getting ready

To step through this recipe, you will need:

  • A working Chef DK installation on the workstation
  • A working Vagrant installation on the workstation
  • The Chef code (optionally) from Chapter 6, Fundamentals of Managing Servers with Chef and Puppet, Chapter 7, Testing and Writing Better Infrastructure Code with Chef and Puppet, or any custom Chef code

How to do it…

Chef environments live in a folder named environments at the root of chef-repo. If the folder doesn't exist, create it:

$ mkdir environments

Creating a production environment

To create a production environment, follow these steps:

  1. Let's start by creating a production environment in a production.rb file:
    name 'production'
    description 'The production environment'
  2. This is the simplest environment possible; it does nothing. Upload it to the Chef server:
    $ knife environment from file environments/production.rb
    Updated Environment production
    
  3. List the available remote environments:
    $ knife environment list
    _default
    production
    

We see we have two environments available: production and _default.

Setting an environment to a node

To set an already existing node to this new production environment, execute the following command:

$ knife node environment set my_node_name production
my_node_name:
  chef_environment: production

Bootstrapping a node with an environment

If we're bootstrapping a node with the knife bootstrap command, we can start in the required environment right from the beginning (using an user named vagrant like the previous examples):

$ knife bootstrap a.b.c.d -N vagrant -x vagrant --sudo --environment production --run-list 'recipe[mysite]'

Fixing cookbook versions for an environment

Let's say our production systems are running a perfectly stable mysite cookbook in version 0.3.1, but we want to try a new feature in the development infrastructure in the 0.4.0 version of the same cookbook. As every cookbook version can live together, each environment can call its own version. The production.rb file would contain the following for the production environment:

cookbook_versions  'mysite' => '= 0.3.1'

The development.rb file would contain the following for the development environment:

cookbook_versions  'mysite' => '= 0.4.0'

A Chef environment file may contain many cookbook constraints, as follows:

cookbook_versions: {
    'mysite': '= 0.4.0',
    'apache': '= 0.6.0'
}

Overriding attributes for an environment

Each environment can override any value, and, in Chef, it's the highest level of override. Nothing else can override a value set for an environment. So, if we simply want to override the value of the sitename attribute to production.rb, it will look like this:

override_attributes 'sitename' => 'mysite_production'

Accessing the environment from a recipe

The node's environment is available from any recipe through the node.chef_environment attribute.

So if our wish is to create a file that would display the environment inside which the node is running, we would need to create a template like this:

Running in <%= @node.chef_environment %> mode.

There's more...

With Puppet, environments are located in distinct directories on the Puppet server. You probably noticed this in Chapter 6, Fundamentals of Managing Servers with Chef and Puppet; we created the code in the /etc/puppetlabs/code/environments/production directory.

This is because the default Puppet environment is production. Other environments, for example test, should be created under /etc/puppetlabs/code/environments/.

Manual environment creation in the Puppet server

Let's start with samples from Chapter 6, Fundamentals of Managing Servers with Chef and Puppet, and try creating a new environment, namely test. On the Puppet server, we just need to do this:

$ sudo -s
# cd /etc/puppetlabs/code/environments/
# cp -a production test

Node environment selection

On the node side, the environment to use can be controlled using --environment:

# puppet agent --test --environment test

To use this environment as the default one, without using --environment, we can configure it in /etc/puppetlabs/puppet/puppet.conf with the following:

[agent]
environment = test

Getting the environment from manifests

As for Chef, we can get the name of the running environment from any manifest. This is done by using the $environment variable, which is set by the Puppet server.

To illustrate this, let's modify our index.php file (manifests/site.pp), both in production and test:

file {"${docroot}/index.php":
    ensure  => present,
    owner   => 'www-data',
    group   => 'www-data',
    mode    => '0644',
    content => "<?php echo "Running from ${environment}" ?>"
}

We can now switch between test and production and see the changes:

# puppet agent --test
Info: Using configured environment 'production' 
…
@@ -1 +1 @@
-<?php echo "Running from test" ?>
+<?php echo "Running from production" ?>
…
# puppet agent --test --environment test
Info: Using configured environment 'test'
@@ -1 +1 @@
-<?php echo "Running from production" ?>
+<?php echo "Running from test" ?>

The dynamic way – r10k

We edited the environments and code directly in the Puppet master, which is not recommended. Fortunately, r10k (which we already used in Chapter 6, Fundamentals of Managing Servers with Chef and Puppet, to install modules) can be used to create environments from a Git repository. Each branch from the Git repository will be checked out into a distinct directory and will be available as an environment. This feature is dynamic: each new branch added to the Git repository will be deployed by r10k.

Let's try it from our workstation. Until now, the job of the shared folder of our Vagrant setup was to map the relative directory puppetcode to /etc/puppetlabs/code/environments/production in the puppet.pomes.pro box. We are about to use multiple environments, so we need to change the mapping to /etc/puppetlabs/code/.

We need a Git repository with two branches, production and test, with all of the previous code. An example is available at https://github.com/ppomes/r10k_sample.git.

The r10k tool needs a global configuration file, which must be created at the same level as our Vagrantfile, with the following content:

:sources:
  :my-repos:
    remote: 'https://github.com/ppomes/r10k_sample.git'
    basedir: 'puppetcode/environments'

Now let's use r10k:

$ r10k -c ./r10k.yaml deploy environment -p
$ ls -l puppetcode/environments/
total 0
drwxr-xr-x  8 ppomes  staff   272B 26 Nov 16:40 production/
drwxr-xr-x  8 ppomes  staff   272B 26 Nov 16:40 test/

Both branches from the Git repository have been deployed, and we can now fire up Vagrant and play with our boxes and branches.

Note

The r10k tool also takes care of the Puppetfile file in each branch, as we already saw in Chapter 6, Fundamentals of Managing Servers with Chef and Puppet, and deploys external modules, if any.

See also

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

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