Try Chef Infra
1. Install Docker and Docker Compose
The installation is a set of containers orchestrated with Docker Compose, a tool for defining and running multi-container Docker applications.
You'll need a Windows, macOS, or 64-bit Linux system.
If you're new to Docker, you can read this overview to get a better understanding of how Docker works.
- Install on Windows
Install Docker for Windows or Docker Toolbox.
- Install on macOS
Install Docker for Mac.
- Install on Linux
See the Docker Compose installation guide or if in Ubuntu simply type:
Terminal: ~
$ |
|
2. Set up your environment
In this module, you'll use a set of Docker images that we've created for you.
The setup includes four systems – one that acts as your workstation and a three that act as the targets, or the system you want to configure.
The Docker images are based on Ubuntu 16.04. The workstation image comes with Chef Workstation
Chef Workstation gives you everything you need to get started with the Chef tools. Ad-hoc remote execution, scans and configuration tasks, cookbook creation tools, as well as robust dependency and testing software all in one easy-to-install package.
Start by creating a working directory. We recommend ~/try-chef
.
Terminal: ~
$ |
|
Next, move to your working directory.
Terminal: ~
$ |
|
Next, get the Docker Compose file. Run the command that matches your system to download a file named docker-compose.yml
.
Windows:
Windows PowerShell: ~/try-chef
PS > |
|
macOS:
Terminal: ~/try-chef
$ |
|
Linux:
Terminal: ~/try-chef
$ |
|
Next, run the following docker-compose
command to retrieve the latest workstation images. Docker must be running in order to use this command.
Terminal: ~/try-chef
$ |
|
Next, run the following docker-compose
command to start the containers. The -d
argument starts the containers in the background.
Terminal: ~/try-chef
$ |
|
If you get an error like this -- Cannot
create container for service workstation: Conflict. The container name
"/workstation" is already in use by container
"58bb327f4cbead2241399daaf9a6843e82...". You have to remove (or rename)
that container to be able to reuse that name
-- it may due to a previous Docker setup that was not cleaned up.
You can resolve such an error by running this command: sudo docker system prune -a
. Then run sudo docker-compose pull
and sudo docker-compose up -d
again. You could also refer to this documentation for more details about removing Docker containers.
Now that your containers are running in the background, run this command to start an interactive Bash session on the workstation container.
Terminal: ~/try-chef
$ |
|
3. Basic ingredients
Chef
Infra is driven by the concept of Resources, a single item that can be
configured on your system. Normally you would collect these together in
Chef recipes, but we are going to demonstrate them as simply as possible
using the chef-run
command to create a file on one of our target systems.
On this first invocation of the |
Terminal: /root
# |
|
Let's break that down a little. First, the command is chef-run
.
This is a utility to run adhoc Chef Infra commands on a remote server.
It provides a good way to get started with Chef Infra, without requiring
any infrastructure beyond SSH.
Next is the host name of the machine we are going to be configuring--web1.
Finally we have file hello.txt
. This refers to the Chef Infra file
resource and passes it the name hello.txt
. This has the effect of creating a file called hello.txt
on the machine. We don't need to provide any credentials because we have provisioned these test machines with SSH keys.
We can see that chef-run
connected to our target machine, ensured Chef Infra Client is
installed, and then ran it with our resource. We are able to test what
has happened by running a command over ssh. Note we have specified a
path here of the root (/
) directory. This is the default working directory for chef if you don't specify anything else.
Terminal: /root
# |
|
Well, that wasn't very interesting, we didn't get any output. Although there weren't any errors, let's run a different command to ensure the file really is there.
Terminal: /root
# |
|
Ah, definitely a file, so it clearly doesn't have any content. What has happened is we have asked Chef to create a file, but not actually specified anything else. Let's try again, but this time with some content.
Terminal: /root
# |
|
Here we have added to the chef-run
command, by providing a property
to the file
resource. This property is content
and specifies the content of the file. This is a primitive way to
create a file, and we shall see more flexible ways later. Let's prove it
has worked by looking at the file again.
Terminal: /root
# |
|
Note that we didn't add a new line, so our prompt is appended to the end of the file output, but we can see the file has been created with content.
We can also ask Chef Infra to remove the file by defining an action, overriding the default of create
.
Terminal: /root
# |
|
If we try and look at the file again we can see it has been removed:
Terminal: /root
# |
|
4. Recipes for success
If you want to configure more than a single item on your system, you will need to collect your resources together in a recipe. With a recipe, Chef Infra will process the resources in the order they appear.
We have included a basic recipe for you to try. It will install a utility, FIGlet, and use it to create a file with a hello world message. Let's take a look at the file and talk through it.
Terminal: /root
# |
|
There is a lot going on here, but we will work through it in stages.
The first line, apt_update, invokes a Chef Infra resource designed for Debian and Ubuntu systems which ensures that the package repository is up-to-date and that the packages we install will be the latest version. The documentation gives more details if you wish to understand further.
The next line, package 'figlet'
,
will install the package. We don't have to tell Chef how to install the
package, we just said that we wanted it installed. This is part of the
power of Chef: it allows us to work cross-platform. We simply state how
we wish a system to look, and when Chef Infra converges, it uses the
correct commands for the system it is running on to bring it into the
state we desire.
Next, we ensure our temporary directory exists with directory '/tmp'
.
One of the great powers of Chef Infra is that we can safely include
this line, even if this directory already exists. The Chef Infra Client
will only take action if it needs to. This is known as test & repair.
By including it we ensure that the next lines will not fail if the
directory does not exist, but not cause problems if it does.
The next four lines are more complex: they are all related to one resource, the execute
resource. This time, however, we need to give it more information.
Unlike the previous commands, the name does not get used by the resource
to direct the action, so instead we just provide a descriptive name.
We finish the line off with the keyword do
. This indicates to Chef Infra that we want to give more arguments to the resource.
The next two lines (indented above for clarity) are again parameters
. This is how we give resources extra information like in the file example above.
- First we have
command
. This is the shell command that is to be executed by the resource. Here we are going to runfiglet
and direct the output to a file. - Next we have
not_if
. This parameter is known as a guard. We use guards to provide the test part of test & repair for more generic resources. In this case, we test for the existence of the file we want to create, and if it exists, Chef Infra will not run the resource.
This is not a perfect test, as it doesn't check that the contents of the file is correct, but will serve our purposes for now.
Finally the keyword end
indicates we are finished giving the resource parameters.
Let's run it on our test machine again, and see the results.
Terminal: /root
# |
|
This command is similar to the previous command, but instead of providing the resource and a parameter (package cowsay
) we just provide the name of the recipe recipe.rb
We can test what happened in a similar manner to the last time:
Terminal: /root
# |
|
5. Cooking up Awesome
As
we saw before, recipes are great for gathering together a selection of
resources but there are still some limitations. One in particular is
highlighted by the file
. You can use the file
resource to create a text file on disk, and use the content
property to add the text, as follows
Editor: Untitled
1 2 3 4 5 6 | file '/foo/bar' do content 'Hello World!' mode '0755' owner 'myuser' group 'mygroup' end |
This can quickly become complex and messy as we add more text over several lines, especially if that text contains special characters that would need to be escaped, like '\'.
Instead, we should be able to keep the content in separate files from the Chef Infra code. To do this, we need a way to package all the pieces of our recipe together. We call this package a cookbook.
We have included for you two cookbooks - one that will setup a webserver and one that will setup a load balancer. The load balancer will balance traffic to the two web server machines we have.
We are going to demonstrate an additional feature of chef-run
that allows you to quickly apply a cookbook to more than one server simultaneously.
First however, we should take a look at our webserver cookbook.
Terminal: /root
# |
|
This represents a basic cookbook with just the minimal of files.
- The
README.md
file gives description of the cookbook and how it should be used. While not mandatory, it is highly recommended that all cookbooks include a README. - The
metadata.rb
file is required for all cookbooks. It contains the name and version number of the cookbook and information about dependencies. You can lean more about the metadata.rb here.
Next we have two folders--recipes
and templates
.
recipes
contain the recipes. You may have as many as necessary including the default recipe,default.rb
, which is the recipe that is run if another is not specified.templates
directory contains templates for text files that are required by a recipe, for example for configuration files that need populated with realtime data
The recipes are similar to above, but you have a couple more resources available. If we look at the recipe we can see:
Terminal: /root
# |
|
This is very similar to our previous recipe. The part to highlight is the template
resource. As you can see we pass it a parameter of source
. This refers to a template in the templates directory we saw above. Let's take a look at it.
Terminal: /root
# |
|
For the most part, this is just some HTML. However there is one part that is unusual < %=node['hostname']% >
This is syntax in the templating language that will be replaced by the
hostname of the machine. This is explained in more detail in the Make your recipe more manageable module.
Let's run that on our test machines, this time using a slightly different chef-run
syntax to apply it to two machines at once, web1 and web2:
Terminal: /root
# |
|
We can test these by connecting to our new web servers:
Terminal: /root
# |
|
Terminal: /root
# |
|
Here you can see the power of Chef Infra. Very quickly we have provisioned two webservers, each configured the same, including the required local changes.
To wrap up, we'll setup a load balancer in front of those web servers. You can look at the recipe and template in the same way as before.
Terminal: /root
# |
|
The |
Terminal: /root
# |
|
The recipe is almost identical but using the haproxy
package and service in place of apache2
.
This is a common pattern of cookbooks, to install an application,
create a config file, and then start the service, so you will see it a
lot.
The haproxy configuration file looks daunting, but in this case it has nothing particular to Chef Infra in it, we have just hard coded the webservers to connect to at the bottom of the file.
Using Chef Infra server gives you the opportunity to create this configuration dynamically. You can learn more about Chef Infra Server here. |
Let's apply this configuration and see it all working.
Terminal: /root
# |
|
As we did previously, we just have to provide the name of the server lb
and the cookbook loadbalancer
.
Congratulations, you have setup a three node system with Chef Infra!
Terminal: /root
# |
|
Clean up
You can experiment more with your setup. When you're done experimenting, run exit
to leave your workstation container.
Terminal: /root
# |
|
You can run the following docker-compose down
command to destroy your setup.
Keep in mind that this command will destroy your setup and delete the Docker images from disk. Omit the |
Terminal: ~/try-chef
$ |
|
To bring up a fresh installation, run the docker-compose up -d
command as you did in step 2.