Chef and OpenStack Part 3 – Create a Cookbook

Production clouds likely require some customization, which often means writing custom Chef cookbooks. This third and final post of the series “Chef and OpenStack” will help you understand the key elements of a cookbook and show a simple example using nginx, an open source web server.

Note that this post assumes that you have read the previous post, “Chef and OpenStack Part 2 – Install a Chef server, workstation and client”, and have already built a Chef environment.

About Cookbooks

Chef cookbooks specify the configuration and state of a cloud instances. They typically handle one specific service, application or function. We can write cookbooks using the Ruby language. All cookbooks are organized into a self-contained cookbooks directory, e.g. ~/chef-repo/cookbooks/, on a Chef workstation.

Download a Cookbook

A large number of already written cookbooks can be downloaded. One way to get them is to download them from the Chef Supermarket using the knife command. For example, follow the steps below to download a cookbook named “apt”, whose default recipe runs “apt-get update” to update packages.

– Download the apt cookbook, from the Chef workstation

knife cookbook site download apt

– Extract the downloaded file in to cookbooks directory

tar xzvf .tar.gz –C cookbooks

– Upload the cookbook to the Chef server

knife cookbook upload apt

Elements of a Cookbook

As we get started with cookbooks, it is important to understand the elements that make up a cookbook. These include recipes, attributes and templates. If we look at the apt cookbook, we can see important components represented in the directory structure. For example:

– List the the apt cookbook directory

cd ~/chef-repo/cookbooks/apt
ls

– Output

attributes CHANGELOG.md definitions files libraries metadata.rb providers README.md recipes resources templates

Recipes

Cookbooks can contain one or more recipes. Recipes provide the main logic for a cookbook. For example, a MySQL cookbook might contain two recipes, one for a client and one for a server. A recipe describes the state of different resources. Examples of resource types are templates, services and packages. For details about resources, see http://docs.getchef.com/resource.html.

Attributes

An attribute can be defined to provide values for configuration options. One of the most powerful parts of Chef is that attributes will be available to all configuration file templates. For more information about attributes, see https://docs.getchef.com/chef_overview_attributes.html

Templates

Chef templates allow us to dynamically create configuration files on cloud instances. Templates leverage ERB, a feature of Ruby that makes it easy to generate any kind of text. For more information, see https://docs.getchef.com/essentials_cookbook_templates.html

Create a Simple Nginx Recipe

Here is a basic example of the workflow to create a recipe.

– Go to the ~/chef-repo directory of the Chef workstation

cd ~/chef-repo

– Create a cookbook

knife cookbook create nginx

– Go to the recipes subdirectory

cd cookbooks/nginx/recipes

– Open the default recipe with a text editor and edit it as described below

vi default.rb
# Cookbook Name:: nginx
# Recipe:: default
#
# run “sudo apt-get update” prior to running package commands
# note that the apt cookbook was downloaded earlier in this blog
  include_recipe "apt"

# Define the package resource
  # Install the nginx package if it has not been installed yet
  package 'nginx' do
   action :install
  end

# Define the service resource
  # Start the service immediately and when the instance is restarted
  service 'nginx' do
   action [ :enable, :start ]
  end

# Define a cookbook_file resource for the web page
  # This will move a file called “index.html” to the node
  cookbook_file "/usr/share/nginx/www/index.html" do
   source "index.html"
   mode "0644"
  end

– Edit metadata.rb. The metadata.rb file includes dependency information. In this example, we need to add the dependency on the apt cookbook.

vi ~/chef-repo/cookbooks/nginx/metadata.rb

– Add a line to the bottom to add the dependency “apt”.

name             'nginx'
  maintainer       'YOUR_COMPANY_NAME'
  maintainer_email 'YOUR_EMAIL'
  license         'All rights reserved'
  description     'Installs/Configures nginx'
  long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
  version         '0.1.0'
 depends "apt"

Upload the cookbooks to the Chef Server

After creating the nginx cookbook, we need to upload it to the Chef server along with the apt cookbook it has a dependency on.

knife cookbook upload apt
 knife cookbook upload nginx

or, one could also uppload everything by typing

knife cookbook upload -a

Add the Cookbook to Run List of a Bootstrapped Instance

Now that the ngnix cookbook is on the server, we can add it to a cloud instance. For example, let’s assume we have an instance called “webserver1”.

– Edit the instance (or Chef node) and add the recipe nginx to the run list.

Knife node edit webserver1
{
   "name": "chef_bootstrap",
   "chef_environment": "_default",
   "normal": {
   "tags": [
      ]
   },
   "run_list": [
        "recipe[nginx]"
    ]
 }

You might need to set the EDITOR environmental variable, e.g.

export EDITOR=vi

Run the Chef client on the cloud instance

The nginx cookbook will now configure the cloud instance webserver1 each time the chef client is run.

– Example of running the Chef client

ssh ubuntu@ipadddress -i mycredentials.pem sudo chef-client

Verify it Works

Use a web browser and enter the cloud instance’s IP address or domain name, e.g. type in http://.

Remember to Create an Index.html File for This Example

Note, we need to create the index.html file and can do that in the cookbook’s “files/default” subdirectory.

cd ~/chef-repo/cookbooks/nginx/files/default

– Create index.html. In this example, the HTML is for a basic web page.

vi index.html
  
    My Web Site
   
  

More Advanced Cookbooks

The example nginx cookbook is very simple and Chef is capable of much more. For more advanced examples, consider reading the post “How to write a good Chef cookbook”.

Post in this Blog Series

1. CHEF AND OPENSTACK PART 1 – KEY CONCEPTS

2. CHEF AND OPENSTACK PART 2A – INSTALL A (Version 11) CHEF SERVER, WORKSTATION AND CLIENT

3. CHEF AND OPENSTACK PART 3 – CREATE A COOKBOOK

4. CHEF AND OPENSTACK PART 2B – INSTALL A (Version 12) CHEF SERVER, WORKSTATION AND CLIENT

2 comments

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s