Book Image

Chef Essentials

By : John Ewart
Book Image

Chef Essentials

By: John Ewart

Overview of this book

<p>Chef is a configuration management tool that turns IT infrastructure into code. Chef provides tools to manage systems at scale. With this book, you will learn how to use the same tools that companies such as Facebook, Riot Games, and Ancestry.com use to manage and scale their infrastructure.</p> <p>This book takes you on a comprehensive tour of Chef's functionality, ranging from its core features to advanced development. You will be brought up to speed with what's new in Chef and how to set up your own Chef infrastructure for individuals, or small or large teams. Once you have the core components, you will get to grips with bootstrapping hosts to then develop and apply cookbooks. If you want to fully leverage Chef, this book will show you advanced recipes to help you handle new types of data providers and resources. By the end of this book, you will be confident in how to manage your infrastructure, scale using the cloud, and extend the built-in functionality of Chef itself.</p>
Table of Contents (15 chapters)
Chef Essentials
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Working with Chef


For single user setups, chef-solo is a version of the chef-client that allows you to use Chef without requiring access to a server. Chef-solo runs locally and requires that a cookbook and any of its dependencies be present on the node being managed. As a result, chef-solo provides a limited subset of the full chef server mode of operation. Most of the features that chef-solo is missing revolve around search and centralized data management, which are not critical for managing virtual machines or a small collection of nodes. The installation and maintenance is simple, but the feature set is smaller.

Installing the Chef server will give you access to the full set of Chef functionality. This mode requires access to a Linux-based host that is network-accessible by the nodes and workstations that will interact with the system. Thanks to the recent effort from the folks at Chef (formerly Opscode), the process of installing Chef has been greatly simplified. The benefits of this installation model are that you get centralized management, search, user authentication, and such, but at the cost of managing your own service.

If you need the features of Chef but do not want to maintain your own server, hosted Chef is a great option for you. Hosted Chef (https://manage.opscode.com/signup) gives you all the features of a self-hosted Chef but without having to worry about upgrades, extra hardware, or system availability. For a small infrastructure (up to five hosts), hosted Chef is free and a great way to get started. Beyond this, plans have a monthly fee, and the price will vary according to the number of hosts you want to manage.

Installing chef-solo

Chef-solo is designed for individuals who do not need a hosted installation for a large-scale infrastructure management. Typical use cases of chef-solo include developers managing virtual machines, test installations, or small-scale infrastructure management. The installation of chef-solo is as simple as installing a single Ruby gem.

The Ruby gem

For those who are not intimately familiar with Ruby, a Ruby gem is a mechanism to package, deliver, and manage Ruby code. These packages may be libraries that provide functionality for developers, or they may be composed only of scripts and tools. Chef-solo is, like many things in life, somewhere in the middle. The gem contains a set of libraries that make up the core functionality as well as a suite of scripts that are used by end users. Before you install Chef, you should consider installing Ruby Version Manager (RVM), rbenv, chruby, or another Ruby manager of your choice to keep your gem collections isolated.

Managing gems

A great tool to manage your gems is RVM. The simplest way to install RVM is to use the installation script provided by the development team on the RVM website (http://rvm.io). The following command will download the script and pipe it through bash:

curl -sSL https://get.rvm.io | bash -s stable

Once it is installed, you will initially need to include RVM's functionality in your shell:

source ~/.rvm/scripts/rvm

Additionally, you might need to add the previous command line to your shell's startup scripts (such as ~/.bashrc or ~/.zshrc, depending on which shell you use). Once RVM is installed, you will want to install a recent version of Ruby, for example, Ruby 1.9.3:

rvm install 1.9.3

Once Ruby 1.9 is installed, you will want to create a gemset. A gemset is RVM's way of isolating gems inside a container, and it will provide you with a place to install gems in such a way that they will not conflict with other gems. This has the benefit of allowing you to install anything you want, without requiring administrative privileges and keeping gems from conflicting with each other. A gemset can be created using the following command:

rvm use 1.9.3@chef --create

The previous command will simultaneously create the gemset named chef (if it does not exist) for your installation of Ruby 1.9.3 and then set it as the active gemset. Once you start using this new gemset, you will want to install the Chef gem—this contains chef-solo and all the command-line tools you need to work with Chef—using the gem command-line tool:

gem install chef

Verifying that chef-solo works

Now that the Chef gem is installed, it is time to verify that everything is working fine. In order to use chef-solo, you need to give the following information to it:

  • What recipes to apply by providing a run list in a file named node.json

  • What the recipes are—these are stored in cookbooks that are found in the cookbooks directory

  • How to find the cookbooks and the run list via a file named solo.rb

For simplicity, we will store all of these files inside of the chef directory in your home directory. You are free to put things where you see fit as you become more comfortable working with Chef.

In order to exercise our new tool, we will do something simple: we'll write a recipe that will create an example.txt file in your home directory. The recipe we create will be called create_file, and we'll put that recipe inside a cookbook, which will be named demo.

First, create the directory that will contain the demo cookbook's recipes (and any in between):

user@host:~ $ mkdir -p ~/chef/cookbooks/demo/recipes 

Next, add the following code to a file, create_file.rb, located in the demo cookbook directory you created at ~/chef/cookbooks/demo/recipes:

file "#{ENV['HOME']}/example.txt" do
  action :create
  content "Greetings #{ENV['USER']}!"
end

This tells Chef that we want to create a file, $HOME/example.txt. Its contents should be Greetings $USER, where $USER will be replaced with the value of $USER, typically the login name of whoever is executing the recipe.

Tip

For those unfamiliar, UNIX (and Windows as well) uses environment variables as a mechanism to exchange data between processes. Some environment variables are set when the user logs in to the system such as HOME, USER, and a variety of others. These variables are available in Ruby using the ENV hash, where the keys are the variable names. In a UNIX shell, these are accessed using the $ prefix. So, the user's home is referred to as $HOME in the shell and ENV['HOME'] inside Ruby.

Now we will need to create a JSON document that describes what chef-solo should execute. JSON is an acronym for JavaScript Object Notation, and Chef uses JSON extensively because it is easy to parse, human readable, and easy to generate from all sorts of tools and languages. Create a file, node.json, located in our work directory (~/chef/ in this case) and add the following content in order to tell Chef that we want to execute the newly created create_file recipe in the demo cookbook:

{   
   "run_list": [ 
       "recipe[demo::create_file]" 
   ] 
} 

Here, we are defining the node as having a run list, which is just an array of things to do, and that the run list contains one recipe, create_file, which it can find in the demo cookbook (the general form of a recipe being cookbook::recipe).

Finally, we'll tell Chef where to find the files we just created using a solo.rb file that we will store in our working directory (~/chef in our case):

CHEF_ROOT="#{ENV['HOME']}/chef"
file_cache_path "#{CHEF_ROOT}"
cookbook_path "#{CHEF_ROOT}/cookbooks"
json_attribs "#{CHEF_ROOT}/node.json" 

Now that you have populated the required configuration files, you can run chef-solo and execute the run list specified. In our case, the run list is defined as only one recipe, create_file, but can be as simple or as complex as needed. The previous configuration tells Chef to load the node configuration from the file node.json to look for cookbooks in ~/chef/cookbooks/ and to store any state data in ~/chef/. In order to execute these commands, you will want to run chef-solo:

chef-solo -c ~/chef/solo.rb 

The -c option tells chef-solo which script contains the configuration. Once you do this, you will see the actions that your recipe is performing:

Starting Chef Client, version 11.8.2
Compiling Cookbooks...
Converging 1 resources
Recipe: demo::create_file
  * file[/home/user/example.txt] action create
    - create new file /home/user/example.txt
    - update content in file /home/user/example.txt from none to b4a3cc
        --- /home/user/example.txt	2014-01-20 23:59:54.692819000 -0500
        +++ /tmp/.example.txt20140122-13411-1vxtg7v	2014-01-20 23:59:54.692819000 -0500
        @@ -1 +1,2 @@
        +Greetings user!

Chef Client finished, 1 resources updated

Once it is completed, you will see that ~/example.txt contains the greeting that you defined in the recipe. Now that you have successfully used chef-solo, let's move on to the Chef service.