Home Cloud & Networking Chef Cookbook - Third Edition

Chef Cookbook - Third Edition

By Matthias Marschall
books-svg-icon Book
eBook $39.99 $27.98
Print $48.99
Subscription $15.99 $10 p/m for three months
$10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
BUY NOW $10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
eBook $39.99 $27.98
Print $48.99
Subscription $15.99 $10 p/m for three months
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
  1. Free Chapter
    Chef Infrastructure
About this book
Chef is a configuration management tool that lets you automate your more cumbersome IT infrastructure processes and control a large network of computers (and virtual machines) from one master server. This book will help you solve everyday problems with your IT infrastructure with Chef. It will start with recipes that show you how to effectively manage your infrastructure and solve problems with users, applications, and automation. You will then come across a new testing framework, InSpec, to test any node in your infrastructure. Further on, you will learn to customize plugins and write cross-platform cookbooks depending on the platform. You will also install packages from a third-party repository and learn how to manage users and applications. Toward the end, you will build high-availability services and explore what Habitat is and how you can implement it.
Publication date:
February 2017
Publisher
Packt
Pages
268
ISBN
9781786465351

 

Chapter 1. Chef Infrastructure

"What made Manhattan Manhattan was the underground infrastructure, that engineering marvel."

Andrew Cuomo

A well-engineered infrastructure builds the basis for successful companies. In this chapter, we will see how to set up an infrastructure around Chef as the basis of your infrastructure as code. We'll cover the following recipes in this chapter:

  • Using version control

  • Installing the Chef Development Kit on your workstation

  • Using the hosted Chef platform

  • Managing virtual machines with Vagrant

  • Creating and using cookbooks

  • Inspecting files on your Chef server with knife

  • Defining cookbook dependencies

  • Managing cookbook dependencies with Berkshelf

  • Using custom knife plugins

  • Deleting a node from the Chef server

  • Developing recipes with local mode

  • Using roles

  • Using environments

  • Freezing cookbooks

  • Running the Chef client as a daemon

 

Introduction


This chapter will cover the basics of Chef, including common terminology, workflow practices, and various tools that work with Chef. We will explore version control using Git, walk through working with community cookbooks, and run those cookbooks on your own servers.

First, let's talk about some important terms used in the Chef universe.

A cookbook is a collection of all the components needed to change something on a server. Things such as installing MySQL or configuring SSH can be done by cookbooks. The most important parts of cookbooks are recipes, which tell Chef which resources you want to configure on your host.

You need to deploy cookbooks to the nodes that you want to change. Chef offers multiple methods for this task. Most probably, you'll use a central Chef server. You can either run your own server or sign up for hosted Chef.

The Chef server is the central registry, where each node needs to be registered. The Chef server distributes the cookbooks you uploaded to it, to your nodes.

Knife is Chef's command-line tool to interact with the Chef server. You run it on your local workstation and use it to upload cookbooks and manage other aspects of Chef.

On your nodes, you need to install Chef Client—the program that runs on your nodes, retrieving cookbooks from the Chef server and executing them on the node.

In this chapter, we'll see the basic infrastructure components of your Chef setup at work and learn how to use the basic tools. Let's get started by looking at how to use Git as a version control system for your cookbooks.

 

Using version control


Do you manually back up every file before you change it? And do you invent creative file name extensions such as _me and _you when you try to collaborate on a file? If you answer yes to any of these, it's time to rethink your processes.

A version control system (VCS) helps you stay sane when dealing with important files and collaborating on them.

Using version control is a fundamental part of any infrastructure automation. There are multiple solutions to manage source version control, including Git, SVN, Mercurial, and Perforce. Due to its popularity among the Chef community, we will be using Git. However, you could easily use any other version control system with Chef.

Note

Don't even think about building your infrastructure as code without using a version control system to manage it!

Getting ready

You'll need Git installed on your local workstation. Either use your operating system's package manager (such as Apt on Ubuntu or Homebrew on OS X, or simply download the installer from www.git-scm.org.

Git is a distributed version control system. This means that you don't necessarily need a central host to store your repositories. However, in practice, using GitHub as your central repository has proven to be very helpful. In this book, I'll assume that you're using GitHub. Therefore, you need to go to www.github.com and create an account (which is free) to follow the instructions given in this book. Make sure that you upload your Secure Shell (SSH) key by following the instructions at https://help.github.com/articles/generating-ssh-keys, so that you're able to use the SSH protocol to interact with your GitHub account.

As soon as you have created your GitHub account, you should create your repository by visiting https://github.com and using chef-repo as the repository name.

Make sure you have wget installed on your local workstation, to be able to download the required files from public servers.

How to do it…

Before you can write any cookbooks, you need to set up your initial Git repository on your development box. Chef Software, Inc. provides an empty Chef repository to get you started. Let's see how you can set up your own Chef repository with Git, using Chef's skeleton:

  1. Download Chef's skeleton repository as a tarball:

    mma@laptop $ wget http://github.com/chef/chef-repo/tarball/master
    ...TRUNCATED OUTPUT...
    2016-09-28 20:54:41 (9.26 MB/s) - 'master' saved [7332/7332]
    
  2. Extract the downloaded tarball:

    mma@laptop $ tar xzvf master
    
  3. Rename the directory:

    mma@laptop:~ $ mv chef-boneyard-chef-repo-* chef-repo
    
  4. Change to your newly created Chef repository:

    mma@laptop:~ $ cd chef-repo/
    
  5. Initialize a fresh Git repository:

    git init .
    Initialized empty Git repository in /Users/mma/work/chef-repo/.git/
    
  6. Connect your local repository to your remote repository on github.com. Make sure to replace mmarschall with your own GitHub username:

    mma@laptop:~/chef-repo $ git remote add origin git@github.com:mmarschall/chef-repo.git
    
  7. Configure Git with your user name and e-mail address:

    mma@laptop:~/chef-repo $ git config --global user.email "you@example.com"
    mma@laptop:~/chef-repo $ git config --global user.name "Your Name"
    
  8. Add and commit Chef's default directory structure:

    mma@laptop:~/chef-repo $ git add .
    mma@laptop:~/chef-repo $ git commit -m "initial commit"
    [master (root-commit) 6148b20] initial commit
     11 files changed, 545 insertions(+), 0 deletions(-)
     create mode 100644 .gitignore
    ...TRUNCATED OUTPUT...
    create mode 100644 roles/README.md
    
  9. Push your initialized repository to GitHub. This makes it available to all your co-workers to collaborate on:

    mma@laptop:~/chef-repo $ git push -u origin master
    ...TRUNCATED OUTPUT...
    To git@github.com:mmarschall/chef-repo.git
     * [new branch]      master -> master
    

How it works…

You have downloaded a tarball containing Chef's skeleton repository. Then, you initialized chef-repo and connected it to your own repository on GitHub.

After that, you added all the files from the tarball to your repository and committed them. This makes Git track your files and the changes you make later.

Finally, you pushed your repository to GitHub, so that your co-workers can use your code too.

There's more...

Let's assume you're working on the same chef-repo repository, together with your co-workers. They cloned the repository, added a new cookbook called other_cookbook, committed their changes locally, and pushed to GitHub. Now, it's time for you to get the new cookbook downloaded to your own laptop.

Pull your co-workers' changes from GitHub. This will merge their changes into your local copy of the repository. Use the pull subcommand:

mma@laptop:~/chef-repo $ git pull --rebase
From github.com:mmarschall/chef-repo
 * branch            master     -> FETCH_HEAD
...TRUNCATED OUTPUT...
create mode 100644 cookbooks/other_cookbook/recipes/default.rb

In the event of any conflicting changes, Git will help you merge and resolve them.

See also

 

Installing the Chef Development Kit on your workstation


If you want to use Chef, you'll need to install the Chef Development Kit (DK) on your local workstation first. You'll have to develop your configurations locally and use Chef to distribute them to your Chef server.

Chef provides a fully packaged version, which does not have any external prerequisites. This fully packaged Chef is called the omnibus installer. We'll see how to use it in this section.

How to do it…

Let's see how to install the Chef DK on your local workstation using Chef's omnibus installer:

  1. Download the Chef DK for your specific workstation platform from https://downloads.chef.io/chef-dk/ and run the installer.

  2. Verify that Chef installed all the required components:

    mma@laptop:~ $ chef verify
    ...TRUNCATED OUTPUT...
    Verification of component 'test-kitchen' succeeded.
    Verification of component 'chefspec' succeeded.
    Verification of component 'rubocop' succeeded.
    Verification of component 'knife-spork' succeeded.
    Verification of component 'openssl' succeeded.
    Verification of component 'delivery-cli' succeeded.
    Verification of component 'opscode-pushy-client' succeeded.
    Verification of component 'berkshelf' succeeded.
    Verification of component 'chef-dk' succeeded.
    Verification of component 'fauxhai' succeeded.
    Verification of component 'inspec' succeeded.
    Verification of component 'chef-sugar' succeeded.
    Verification of component 'tk-policyfile-provisioner' succeeded.
    Verification of component 'chef-provisioning' succeeded.
    Verification of component 'kitchen-vagrant' succeeded.
    Verification of component 'git' succeeded.
    Verification of component 'chef-client' succeeded.
    Verification of component 'generated-cookbooks-pass-chefspec' succeeded.
    Verification of component 'package installation' succeeded. 
    
  3. Add the newly installed Ruby to your path:

    mma@laptop:~ $ echo 'export PATH="/opt/chefdk/bin:/opt/chefdk/embedded/bin:$PATH"' >> ~/.bash_profile && source ~/.bash_profile
    

    Note

    You may not want to use (and don't have to use) ChefDK's Ruby, especially if you are a Rails Developer. If you're happily using your Ruby rvm or rbenv environment, you can continue to do so. Just ensure that ChefDK-provided applications appear first in your PATH, before any gem-installed versions, and you're good to go.

    .chef/encrypted_data_bag_secret
    

How it works…

The omnibus installer will download Ruby and all required Ruby gems into /opt/chefdk.

See also

 

Using the hosted Chef platform


If you want to get started with Chef right away (without the need to install your own Chef server) or want a third party to give you a Service Level Agreement (SLA) for your Chef server, you can sign up for hosted Chef by Chef Software, Inc. Chef Software, Inc. operates Chef as a cloud service. It's quick to set up and gives you full control, using users and groups to control access permissions to your Chef setup. We'll configure knife, Chef's command-line tool, to interact with hosted Chef, so that you can start managing your nodes.

Getting ready

Before being able to use hosted Chef, you need to sign up for the service. There is a free account for up to five nodes.

Visit http://manage.chef.io/signup and register for a free account.

I registered as the user webops with an organization short name of awo. An organization is the top-level entity for role-based access control in the Chef server.

After registering your account, it is time to prepare your organization to be used with your chef-repo repository.

How to do it…

Carry out the following steps to interact with the hosted Chef:

  1. Create the configuration directory for your Chef client on your local workstation:

    mma@laptop:~ $ cd ~/chef-repo
     mkdir .chef
    
  2. Generate the knife config and put the downloaded knife.rb into the .chef directory inside your chef-repo directory. Make sure you have your user's private key saved as .chef/<YOUR USERNAME>.pem, (in my case it is .chef/webops.pem). If needed, you can reset it at https://id.chef.io/id/profile. Replace webops with the username you chose for hosted Chef, and awo with the short name you chose for your organization in your knife.rb file:

    current_dir = File.dirname(__FILE__)
    log_level                :info
    log_location             STDOUT
    node_name                "webops"
    client_key               "#{current_dir}/webops.pem"
    chef_server_url          "https://api.chef.io/organizations/awo"
    cache_type               'BasicFile'
    cache_options( :path => "#{ENV['HOME']}/.chef/checksums" )
    cookbook_path            ["#{current_dir}/../cookbooks"]

    Note

    You should add the following code to your .gitingore file inside chef-repo to avoid your credentials ending up in your Git repository:

    .chef/*.pem
    
  3. Use knife to verify that you can connect to your hosted Chef organization. It should not have any clients, so far:

    mma@laptop:~/chef-repo $ knife client list
    

How it works…

The following line of code in your knife.rb file tells knife where to find your user's private key. It is used to authenticate you with the Chef server:

client_key               "#{current_dir}/webops.pem"

Also, the following line of code in your knife.rb file tells knife that you are using hosted Chef. You will find your organization name as the last part of the URL:

chef_server_url          "https://api.chef.io/organizations/awo"

Using the knife.rb file and your user's key, you can now connect to your organization hosted by Chef Software, Inc.

There's more…

This setup is good for you if you do not want to worry about running, scaling, and updating your own Chef server and if you're happy with saving all your configuration data in the Cloud (under the control of Chef Software, Inc.).

Note

If you need to have all your configuration data within your own network boundaries, you can install Chef server on premises by choosing ON PREMISES CHEF at https://www.chef.io/chef/choose-your-version/ or install the Open Source version of Chef server directly from GitHub at https://github.com/chef/chef.

See also

 

Managing virtual machines with Vagrant


Vagrant is a command-line tool that provides you with a configurable, reproducible, and portable development environment using VMs. It lets you define and use preconfigured disk images to create new VMs from. Also, you can configure Vagrant to use provisioners such as Shell scripts, Puppet, or Chef to bring your VM into the desired state.

Tip

Chef comes with Test Kitchen, which enables you to test your cookbooks on Vagrant without you needing to setup anything manually.

You only need to follow this section, if you want to learn how to use Vagrant and Chef for more advanced cases.

In this recipe, we will see how to use Vagrant to manage VMs using VirtualBox and Chef client as the provisioner.

Getting ready

  1. Download and install VirtualBox at https://www.virtualbox.org/wiki/Downloads.

  2. Download and install Vagrant at https://www.vagrantup.com/downloads.html.

  3. Install the Omnibus Vagrant plugin to enable Vagrant to install the Chef client on your VM by running the following command:

    mma@laptop:~/chef-repo $ vagrant plugin install vagrant-omnibus
    Installing the 'vagrant-omnibus' plugin. This can take a few minutes...
    Installed the plugin 'vagrant-omnibus (1.5.0)'!
    

How to do it…

Let's create and boot a virtual node by using Vagrant:

  1. Visit https://github.com/chef/bento and choose a Vagrant box to base your VMs on. We'll use the amd64 image of ubuntu-16.04 in this example.

  2. The URL of that box is http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-16.04_chef-provisionerless.box.

  3. Create a new Vagrantfile. Make sure that you replace <YOUR-ORG> with the name of your organization on the Chef server. Use the name and URL of the box file you noted down in the first step as config.vm.box and config.vm.box_url:

    mma@laptop:~/chef-repo $ subl Vagrantfile
    Vagrant.configure("2") do |config|
      config.vm.box = "opscode-ubuntu-16.04"
      config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-16.04_chef-provisionerless.box"
      config.omnibus.chef_version = :latest
    
      config.vm.provision :chef_client do |chef|
        chef.provisioning_path = "/etc/chef"
        chef.chef_server_url = "https://api.chef.io/organizations/<YOUR_ORG>"
        chef.validation_key_path = ".chef/<YOUR_USER>.pem"
        chef.validation_client_name = "<YOUR_USER> "
        chef.node_name = "server"
      end
    end
    
  4. Create your virtual node using Vagrant:

    mma@laptop:~/chef-repo $ vagrant up
    Bringing machine 'default' up with 'virtualbox' provider...
    ==> default: Box 'opscode-ubuntu-16.04' could not be found. Attempting to find and install...
    ...TRUNCATED OUTPUT...
    ==> default: Importing base box 'opscode-ubuntu-16.04'...
    ...TRUNCATED OUTPUT...
    ==> default: Installing Chef latest Omnibus package...
    ...TRUNCATED OUTPUT...
    ==> default: Running chef-client...
    ==> default: Starting Chef Client, version 12.14.89
    ...TRUNCATED OUTPUT...
    
  5. Log in to your virtual node using SSH:

    mma@laptop:~/chef-repo $ vagrant ssh
    Welcome to Ubuntu 16.04.1 LTS (GNU/Linux 4.4.0-31-generic x86_64)
    ...TRUNCATED OUTPUT...
    vagrant@server:~$
    
  6. Log out of your virtual node:

    vagrant@server:~$ exit
    logout
    Connection to 127.0.0.1 closed.
    mma@laptop:~/chef-repo $
    
  7. Validate that the Chef server knows your new virtual machine as a client called server:

    mma@laptop:~/chef-repo $ knife client list
    awo-validator
    server
    
  8. Go to https://manage.chef.io/organizations/<YOUR ORGANIZATION>/nodes and validate that your new virtual machine shows up as a registered node:

How it works…

The Vagrantfile is written in a Ruby Domain Specific Language (DSL) to configure the Vagrant virtual machines. We want to boot a simple Ubuntu VM. Let's go through the Vagrantfile step by step.

First, we create a config object. Vagrant will use this config object to configure the VM:

Vagrant.configure("2") do |config|
...
end

Inside the config block, we tell Vagrant which VM image to use, in order to boot the node:

config.vm.box = "opscode-ubuntu-16.04"
config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-16.04_chef-provisionerless.box"

We want to boot our VM using a so-called Bento Box, provided by Chef. We use Ubuntu Version 16.04 here.

Note

If you have never used the box before, Vagrant will download the image file (a few hundred megabytes) when you run vagrant up for the first time.

As we want our VM to have the Chef client installed, we tell the omnibus vagrant plugin to use the latest version of the Chef client:

  config.omnibus.chef_version = :latest

After selecting the VM image to boot, we configure how to provision the box by using Chef. The Chef configuration happens in a nested Ruby block:

  config.vm.provision :chef_client do |chef|
  ...
  end

Inside this chef block, we need to instruct Vagrant on how to hook up our virtual node to the Chef server. First, we need to tell Vagrant where to store all the Chef stuff on your node:

    chef.provisioning_path = "/etc/chef"

Vagrant needs to know the API endpoint of your Chef server. If you use hosted Chef, it is https://api.chef.io/organizations/<YOUR_ORG>. You need to replace <YOUR_ORG> with the name of the organization that you created in your account on hosted Chef. If you are using your own Chef server, change the URL accordingly:

    chef.chef_server_url = "https://api.chef.io/organizations/<YOUR_ORG>"

While creating your user on hosted Chef, you must have downloaded your private key. Tell Vagrant where to find this file:

    chef.validation_key_path = ".chef/<YOUR_USER>.pem"

Also, you need to tell Vagrant which client it should use to validate itself against in the Chef server:

    chef.validation_client_name = "<YOUR_USER>"

Finally, you should tell Vagrant how to name your node:

    chef.node_name = "server"

After configuring your Vagrantfile, all you need to do is run the basic Vagrant commands such as vagrant up, vagrant provision, and vagrant ssh. To stop your VM, just run the vagrant halt command.

There's more…

If you want to start from scratch again, you will have to destroy your VM and delete both the client and the node from your Chef server by running the following command:

mma@laptop:~/chef-repo $ vagrant destroy
mma@laptop:~/chef-repo $ knife node delete server -y && knife client delete server -y

Alternatively, you may use the Vagrant Butcher plugin found at https://github.com/cassianoleal/vagrant-butcher.

Tip

Don't blindly trust Vagrant boxes downloaded from the Web; you never know what they contain.

See also

 

Creating and using cookbooks


Cookbooks are an essential part of Chef. Basically, you describe the configurations you want to apply to your nodes in cookbooks. You can create them using the Chef executable installed by the Chef DK.

In this recipe, we'll create and apply a simple cookbook using the chef and knife command-line tools.

Getting ready

Make sure you have Chef DK installed and a node available for testing. Check out the installation instructions at http://learn.chef.io if you need help here.

Edit your knife.rb file (usually found in the hidden .chef directory) and add the following three lines to it, filling in your own values:

cookbook_copyright "your company"
cookbook_license "apachev2"
cookbook_email "your email address"

Note

The Apache 2 license is the most commonly license found in cookbooks, but you're free to choose whichever suits your needs. If you put none as cookbook_license, knife will put All rights reserved into your recipe's metadata file.

Chef will use the preceding values as the defaults whenever you create a new cookbook. We assume that you have a node called server registered with your Chef server, as described in the Managing virtual machines with Vagrant section in this chapter.

How to do it…

Carry out the following steps to create and use cookbooks:

  1. Create a cookbook named my_cookbook by running the following command:

    mma@laptop:~/chef-repo $ chef generate cookbook cookbooks/my_cookbook
    Generating cookbook my_cookbook
    - Ensuring correct cookbook file content
    - Ensuring delivery configuration
    - Ensuring correct delivery build cookbook content
    
    Your cookbook is ready. Type `cd cookbooks/my_cookbook` to enter it.
    ...TRUNCATED OUTPUT...
    
  2. Upload your new cookbook on the Chef server:

    mma@laptop:~/chef-repo $ knife cookbook upload my_cookbook
    Uploading my_cookbook    [0.1.0]
    Uploaded 1 cookbook.
    
  3. Add the cookbook to your node's run list. In this example, the name of the node is server:

    mma@laptop:~/chef-repo $ knife node run_list add server 'recipe[my_cookbook]'
    server:
      run_list: recipe[my_cookbook]
    
  4. Run the Chef client on your node:

    user@server:~$ sudo chef-client
    

Tip

If you're using a Vagrant VM as your server, you need to make sure to run vagrant up and vagrant ssh to be able to execute the Chef client on the node.

How it works…

The chef executable helps you to manage your local Chef Development environment. We used it here to generate the cookbook.

Knife is the command-line interface for the Chef server. It uses the RESTful API exposed by the Chef server to do its work and helps you to interact with the Chef server.

The knife command supports a host of commands structured as follows:

knife <subject> <command>

The <subject> used in this section is either cookbook or node. The commands we use are upload for the cookbook, and run_list add for the node.

There's more…

Before uploading your cookbook to the Chef server, it's a good idea to run it in Test Kitchen first. Test Kitchen will spin up a virtual machine, execute your cookbook, and destroy the virtual machine again. That way you can evaluate what your cookbook does before you upload it to the Chef server and run it on real nodes.

To run your cookbook with Test Kitchen on an Ubuntu 16.04 virtual machine, execute the following steps:

  1. Create a configuration file for Test Kitchen for executing the default recipe of my_cookbook:

    mma@laptop:~/chef-repo $ subl .kitchen.yml
    ---
    driver:
      name: vagrant
    
    provisioner:
      name: chef_zero
    
    platforms:
      - name: ubuntu-16.04
    
    suites:
      - name: default
        run_list:
          - recipe[my_cookbook::default]
     attributes:
    
  2. Run kitchen test to execute the default recipe of my_cookbook:

    mma@laptop:~/chef-repo $ kitchen test
    -----> Starting Kitchen (v1.13.2)
    ...TRUNCATED OUTPUT...
    -----> Kitchen is finished. (0m45.42s)
    

See also

  • Learn how to use Test Kitchen to evaluate your cookbooks before uploading them to the Chef server in the Integration-testing your Chef cookbooks with Test Kitchen recipe in Chapter 2, Evaluating and Troubleshooting Cookbooks and Chef Runs

  • Learn how to set up your Chef server in the Using the hosted Chef platform recipe in this chapter

 

Inspecting files on your Chef server with knife


Sometimes, you may want to peek into the files stored on your Chef server. You might not be sure about an implementation detail of the specific cookbook version currently installed on your Chef server, and need to look it up. Knife can help you out by letting you show various aspects of the files stored on your Chef server.

Getting ready

  1. Install the iptables community cookbook by executing the following command:

    mma@laptop:~/chef-repo $ knife cookbook site install iptables
    Installing iptables to /Users/mma/work/chef-repo/cookbooks
    ...TRUNCATED OUTPUT...
    

    Note

    Take a look at the following error:

    ERROR: IOError: Cannot open or read ../chef-repo/cookbooks/iptables/metadata.rb!

    If you get the preceding error, your cookbook only has a metadata.json file. Make sure that you delete it and create a valid metadata.rb, file instead.

  2. Upload the iptables cookbook on your Chef server by executing the following command:

    mma@laptop:~/chef-repo $ knife cookbook upload iptables --include-dependencies
    Uploading iptables       [3.0.0]
    Uploading compat_resource [12.14.7]
    Uploaded 2 cookbooks.
    
 

How to do it…


Let's find out how knife can help you to look into a cookbook stored in your Chef server:

  1. First, you want to find out the current version of the cookbook you're interested in. In our case, we're interested in the iptables cookbook:

    mma@laptop:~/work/chef_helpster $ knife cookbook show iptables
    iptables   3.0.0 0.14.1
    
  2. Then, you can look up the definitions of the iptables cookbook, using the version number that you found in the previous step:

    mma@laptop:~/chef-repo $ knife cookbook show iptables 0.14.1 definitions
      checksum:     45c0b77ff10d7177627694827ce47340
      name:         iptables_rule.rb
      path:         definitions/iptables_rule.rb
      specificity:  default
      url:          https://s3-external-1.amazonaws.com:443/opscode-platform...
    
  3. Now, you can even show the contents of the iptables_rule.rb definition file, as stored on the server:

    mma@laptop:~/chef-repo $ knife cookbook show iptables 0.14.1 definitions iptables_rule.rb
    #
    # Cookbook Name:: iptables
    # Definition:: iptables_rule
    #
    #
    define :iptables_rule, :enable => true, :source => nil, :variables => {}, :cookbook => nil do
    ...TRUNCATED OUTPUT...
    end
    
 

How it works…


The knife cookbook show subcommand helps you understand what exactly is stored on the Chef server. It lets you drill down into specific sections of your cookbooks and see the exact content of the files stored in your Chef server.

 

There's more…


You can pass patterns to the knife show command to tell it exactly what you want to see. Showing the attributes defined by the cookbook can be done as follows:

mma@laptop:~/work/chef_helpster $ knife show cookbooks/iptables/attributes/*
cookbooks/iptables/attributes/default.rb:
#
# Cookbook Name:: iptables
# Attribute:: default
...TRUNCATED OUTPUT...
 

See also


 

Defining cookbook dependencies


Quite often, you might want to use features of other cookbooks in your own cookbooks. For example, if you want to make sure that all packages required for compiling software written in C are installed, you might want to include the build-essential cookbook, which does just that. The Chef server needs to know about such dependencies in your cookbooks. You declare them in a cookbook's metadata.

Getting ready

Make sure you have a cookbook named my_cookbook, and the run_list of your node includes my_cookbook, as described in the Creating and using cookbooks recipe in this chapter.

How to do it…

Edit the metadata of your cookbook in the file cookbooks/my_cookbook/metadata.rb to add a dependency to the build-essential cookbook:

mma@laptop:~/chef-repo $ subl cookbooks/my_cookbook/metadata.rb
...
depends 'build-essential', '>= 7.0.3'

How it works…

If you want to use a feature of another cookbook inside your cookbook, you will need to include the other cookbook in your recipe using the include_recipe directive:

include_recipe 'build-essential'

To tell the Chef server that your cookbook requires the build-essential cookbook, you need to declare that dependency in the metadata.rb file. If you uploaded all the dependencies to your Chef server either using knife cookbook upload my_cookbook --include-dependencies or berks install and berks upload, as described in the Managing cookbook dependencies with Berkshelf recipe in this chapter, the Chef server will then send all the required cookbooks to the node.

The depends function call tells the Chef server that your cookbook depends on a version greater than or equal to 7.0.3 of the build-essential cookbook.

You may use any of these version constraints with depends calls:

  • < (less than)

  • <= (less than or equal to)

  • = (equal to)

  • >= (greater than or equal to)

  • ~> (approximately greater than)

  • > (greater than)

There's more…

If you include another recipe inside your recipe, without declaring the cookbook dependency in your metadata.rb file, Foodcritic will warn you:

mma@laptop:~/chef-repo $ foodcritic cookbooks/my_cookbook
FC007: Ensure recipe dependencies are reflected in cookbook metadata: cookbooks/my_cookbook/recipes/default.rb:9

Tip

Foodcritic will just return an empty line, if it doesn't find any issues.

Additionally, you can declare conflicting cookbooks through the conflicts call:

conflicts "nginx"

Of course, you can use version constraints exactly the same way you did with depends.

See also

  • Read more on how you can find out what is uploaded on your Chef server in the Inspecting files on your Chef server with knife recipe in this chapter

  • Find out how to use foodcritic in the Flagging problems in your Chef cookbooks recipe in Chapter 2, Evaluating and Troubleshooting Cookbooks and Chef Runs

 

Managing cookbook dependencies with Berkshelf


It's a pain to manually ensure that you have installed all the cookbooks that another cookbook depends on. You must download each and every one of them manually only to find out that, with each downloaded cookbook, you inherit another set of dependent cookbooks.

And even if you use knife cookbook site install, which installs all the dependencies locally for you, your cookbook directory and your repository get cluttered with all those cookbooks. Usually, you don't really care about all those cookbooks and don't want to see or manage them.

This is where Berkshelf comes into play. It works like Bundler for Ruby gems, managing cookbook dependencies for you. Berkshelf downloads all the dependencies you defined recursively and helps you to upload all cookbooks to your Chef server.

Instead of polluting your Chef repository, it stores all the cookbooks in a central location. You just commit your Berkshelf dependency file (called Berksfile) to your repository, and every colleague or build server can download and install all those dependent cookbooks based on it.

Let's see how to use Berkshelf to manage the dependencies of your cookbook.

Getting ready

Make sure you have a cookbook named my_cookbook and the run_list of your node includes my_cookbook, as described in the Creating and using cookbooks recipe.

How to do it…

Berkshelf helps you to keep those utility cookbooks out of your Chef repository. This makes it much easier to maintain the important cookbooks.

Let's see how to write a cookbook by running a bunch of utility recipes and manage the required cookbooks with Berkshelf:

  1. Edit your cookbook's metadata:

    mma@laptop:~/chef-repo $ subl cookbooks/my_cookbook/metadata.rb
    ...
    depends "chef-client"
    depends "apt"
    depends "ntp"
    
  2. Edit your cookbook's default recipe:

    mma@laptop:~/chef-repo $ subl cookbooks/my_cookbook/recipes/default.rb
    ...
    include_recipe "chef-client"
    include_recipe "apt"
    include_recipe "ntp"
    
  3. Run Berkshelf to install all the required cookbooks:

    mma@laptop:~/chef-repo $ cd cookbooks/my_cookbook
    mma@laptop:~/chef-repo/cookbooks/my_cookbook $ berks install
    Resolving cookbook dependencies...
    Fetching 'my_cookbook' from source at .
    Fetching cookbook index from https://supermarket.chef.io...
    Installing apt (4.0.2)
    ...TRUNCATED OUTPUT...
    
  4. Upload all the cookbooks on the Chef server:

    mma@laptop:~/chef-repo/cookbooks/my_cookbook $ berks upload
    Using my_cookbook (0.1.0)
    ...TRUNCATED OUTPUT...
    Uploaded windows (2.0.2) to: 'https://api.opscode.com:443/organizations/awo'
    

How it works...

Berkshelf comes with the Chef DK.

We edit our cookbook and tell it to use a few basic cookbooks.

Instead of making us manually install all the cookbooks using knife cookbook site install, Chef generates a Berksfile, besides the metadata.rb file.

The Berksfile is simple. It tells Berkshelf to use the Chef supermarket as the default source for all cookbooks:

source "https://supermarket.chef.io"

And the Berksfile tells Berkshelf to read the metadata.rb file to find all the required cookbooks. This is the simplest way when working inside a single cookbook. Please see the following There's more… section to find an example of a more advanced usage of the Berksfile.

After telling Berkshelf where to find all the required cookbook names, we use it to install all those cookbooks:

berks install

Berkshelf stores cookbooks in ~/.berkshelf/cookbooks, by default. This keeps your Chef repository clutter-free. Instead of having to manage all the required cookbooks inside your own Chef repository, Berkshelf takes care of them. You simply need to check in Berksfile with your cookbook, and everyone using your cookbook can download all the required cookbooks by using Berkshelf.

To make sure that there's no mix-up with different cookbook versions when sharing your cookbook, Berkshelf creates a file called Berksfile.lock alongside Berksfile.

Note

Don't commit the Berksfile.lock to version control. If you use berks generate it will auto populate the .gitignore for you. Otherwise, you need to add Berksfile.lock to your .gitignore manually.

Here, you'll find the exact versions of all the cookbooks that Berkshelf installed:

DEPENDENCIES
  my_cookbook
    path: .
    metadata: true

GRAPH
  apt (4.0.2)
    compat_resource (>= 12.10)
  chef-client (6.0.0)
    cron (>= 1.7.0)
    logrotate (>= 1.9.0)
    windows (>= 1.42.0)
  compat_resource (12.14.7)
  cron (2.0.0)
  logrotate (2.1.0)
    compat_resource (>= 0.0.0)
  my_cookbook (0.1.1)
    apt (>= 0.0.0)
    chef-client (>= 0.0.0)
    ntp (>= 0.0.0)
  ntp (3.2.0)
  windows (2.0.2)

Berkshelf will only use the exact versions specified in the Berksfile.lock file, if it finds this file.

Finally, we use Berkshelf to upload all the required cookbooks to the Chef server:

berks upload

There's more...

Berkshelf integrates tightly with Vagrant via the vagrant-berkshelf plugin. You can set up Berkshelf and Vagrant in such a way that Berkshelf installs and uploads all the required cookbooks on your Chef server whenever you execute vagrant up or vagrant provision. You'll save all the work of running berks install and berks upload manually before creating your node with Vagrant.

Let's see how you can integrate Berkshelf and Vagrant:

  1. First, you need to install the Berkshelf plugin for Vagrant:

    mma@laptop:~/work/chef-repo $ vagrant plugin install vagrant-berkshelf
    Installing the 'vagrant-berkshelf' plugin. This can take a few minutes...
    Installed the plugin 'vagrant-berkshelf (5.0.0)'!
    
  2. Then, you need to tell Vagrant that you want to use the plugin. You do this by enabling the plugin in Vagrantfile:

    mma@laptop:~/work/chef-repo $ subl Vagrantfile
    config.berkshelf.enabled = true
    
  3. Then, you need a Berksfile in the root directory of your Chef repository to tell Berkshelf which cookbooks to install on each Vagrant run:

    mma@laptop:~/work/chef-repo $ subl Berksfile
    source 'https://supermarket.chef.io'
    
    cookbook 'my_cookbook', path: 'cookbooks/my_cookbook'
    
  4. Eventually, you can start your VM using Vagrant. Berkshelf will first download and then install all the required cookbooks in the Berkshelf, and upload them to the Chef server. Only after all the cookbooks are made available on the Chef server by Berkshelf will Vagrant go on:

    mma@mma-mbp:~/work/chef-repo $ vagrant up
    Bringing machine 'server' up with 'virtualbox' provider...
    
    ==> default: Updating Vagrant's Berkshelf...
    ==> default: Resolving cookbook dependencies...
    ==> default: Fetching 'my_cookbook' from source at cookbooks/my_cookbook
    ==> default: Fetching cookbook index from https://supermarket.chef.io...
    ...TRUNCATED OUTPUT...
    
  5. This way, using Berkshelf together with Vagrant saves a lot of manual steps and gets faster cycle times for your cookbook development. if you're using your manual Vagrant setup instead of Test Kitchen.

See also

 

Using custom knife plugins


Knife comes with a set of commands out-of-the-box. The built-in commands deal with the basic elements of Chef-like cookbooks, roles, data bags, and so on. However, it would be nice to use knife for more than just the basic stuff. Fortunately, knife comes with a plugin API and there are already a host of useful knife plugins built by the makers of Chef and the Chef community.

Getting ready

Make sure you have an account at Amazon Web Services (AWS) if you want to follow along and try out the knife-ec2 plugin. There are knife plugins available for most Cloud providers. Go through the There's more… section of this recipe for a list.

How to do it…

Let's see which knife plugins are available, and try to use one to manage Amazon EC2 instances:

  1. List the knife plugins that are shipped as Ruby gems using the chef command-line tool:

    mma@laptop:~/chef-repo $ chef gem search -r knife-
    *** REMOTE GEMS ***
    ...TRUNCATED OUTPUT...
    
    knife-azure (1.6.0)
    ...TRUNCATED OUTPUT...
    knife-ec2 (0.13.0)
    ...TRUNCATED OUTPUT...
    
  2. Install the EC2 plugin to manage servers in the Amazon AWS Cloud:

    mma@laptop:~/chef-repo $ chef gem install knife-ec2
    Building native extensions. This could take a while...
    ...TRUNCATED OUTPUT...
    Fetching: knife-ec2-0.13.0.gem (100%)
    Successfully installed knife-ec2-0.13.0
    ...TRUNCATED OUTPUT...
    
    6 gems installed
    
  3. List all the available instance types in AWS using the knife ec2 plugin. Please use your own AWS credentials instead of XXX and YYYYY:

    mma@laptop:~/chef-repo $ knife ec2 flavor list --aws-access-key-id XXX --aws-secret-access-key YYYYY
    ID           Name                                 Arch    RAM     Disk     Cores      
    c1.medium    High-CPU Medium                          32-bit  1740.8  350 GB   5          
    …TRUNCATED OUTPUT…
    m2.xlarge    High-Memory Extra Large                  64-bit  17510.  420 GB   6.5        
    t1.micro     Micro Instance                           0-bit   613     0 GB     2
    

How it works…

Knife looks for plugins in various places.

First, it looks into the .chef directory, which is located inside your current Chef repository, to find plugins specific to this repository:

./.chef/plugins/knife/

Then, it looks into the .chef directory, which is located in your home directory, to find plugins that you want to use in all your Chef repositories:

~/.chef/plugins/knife/

Finally, it looks for installed gems. Knife will load all the code from any chef/knife/ directory found in your installed Ruby gems. This is the most common way of using plugins developed by Chef or the Chef community.

There's more...

There are hundreds of knife plugins, including plugins for most of the major Cloud providers, as well as the major virtualization technologies, such as VMware, vSphere, and OpenStack, among others.

See also

  • To learn how to write your own knife plugins, see the Creating custom knife plugins recipe in Chapter 2, Evaluating and Troubleshooting Cookbooks and Chef Runs

  • Find a list of supported Cloud providers at http://docs.chef.io/plugin_knife.html

 

Deleting a node from the Chef server


Every node managed by a Chef server has a corresponding client object on the Chef server. Running the Chef client on your node uses the client object to authenticate itself against the Chef server on each run.

Additionally, to register a client, a node object is created on the Chef server. The node object is the main data structure, which you can use to query node data inside your recipes.

Getting ready

Make sure you have at least one node registered on your Chef server that is safe to remove.

How to do it…

Let's delete the node and client object to completely remove a node from the Chef server.

  1. Delete the node object:

    mma@laptop:~/chef-repo $ knife node delete my_node
    Do you really want to delete my_node? (Y/N) y
    Deleted node[my_node]
    
  2. Delete the client object:

    mma@laptop:~/chef-repo $ knife client delete my_node
    Do you really want to delete my_node? (Y/N) y
    Deleted client[my_node]
    

How it works...

To keep your Chef server clean, it's important to not only manage your node objects but to also take care of your client objects, as well.

Knife connects to the Chef server and deletes the node object with a given name, using the Chef server RESTful API.

The same happens while deleting the client object on the Chef server.

After deleting both objects, your node is totally removed from the Chef server. Now you can reuse the same node name with a new box or virtual machine.

There's more…

Having to issue two commands is a bit tedious and error-prone. To simplify things, you can use a knife plugin called playground.

  1. Run the chef command-line tool to install the knife plugin:

    mma@laptop:~/chef-repo $ chef gem install knife-playground
    ...TRUNCATED OUTPUT...
    Installing knife-playground (0.2.2)
    
  2. Run the knife pg clientnode delete subcommand:

    mma@laptop:~/chef-repo $ knife pg clientnode delete my_node
    Deleting CLIENT my_node...
    Do you really want to delete my_node? (Y/N) y
    Deleted client[my_node]
    Deleting NODE my_node...
    Do you really want to delete my_node? (Y/N) y
    Deleted node[my_node]
    

See also

  • Read about how to do this when using Vagrant in the Managing virtual machines with Vagrant recipe in this recipe

  • Read about how to set up your Chef server and register your nodes in the Using the hosted Chef platform recipe in this chapter

 

Developing recipes with local mode


If running your own Chef server seems like overkill and you're not comfortable with using the hosted Chef, you can use local mode to execute cookbooks.

Getting ready

  1. Create a cookbook named my_cookbook by running the following command:

    mma@laptop:~/chef-repo $ chef generate cookbook cookbooks/my_cookbook
    Compiling Cookbooks...
    Recipe: code_generator::cookbook
    ...TRUNCATED OUTPUT...
    
  2. Edit the default recipe of my_cookbook so that it creates a temporary file:

    mma@laptop:~/chef-repo $ subl cookbooks/my_cookbook/recipes/default.rb
    file "/tmp/local_mode.txt" do
        content "created by chef client local mode"
        action :create
    end
    

How to do it…

Let's run my_cookbook on your local workstation using the Chef client's local mode:

  1. Run the Chef client locally with my_cookbook in the run list:

    mma@laptop:~/chef-repo $ chef-client --local-mode -o my_cookbook
    [2016-10-03T20:37:02+02:00] INFO: Started chef-zero at chefzero://localhost:8889 with repository at /Users/matthias.marschall/chef-repo
      One version per cookbook
    
    [2016-10-03T20:37:02+02:00] INFO: Forking chef instance to converge...
    Starting Chef Client, version 12.14.89
    [2016-10-03T20:37:02+02:00] INFO: *** Chef 12.14.89 ***
    [2016-10-03T20:37:02+02:00] INFO: Platform: x86_64-darwin13
    ...TRUNCATED OUTPUT...
    Chef Client finished, 1/1 resources updated in 04 seconds
    
  2. Validate that the Chef client run creates the desired temporary file on your local workstation:

    mma@laptop:~/chef-repo $ cat /tmp/local_mode.txt
    created by chef client local mode
    

How it works…

The --local-mode (short form: -z) parameter switches the Chef client into local mode. Local mode uses chef-zero—a simple, in-memory version of the Chef server provided by Chef DK—when converging the local workstation.

By providing the -o parameter, you override the run list of your local node so that the Chef client executes the default recipe from my_cookbook.

There's more…

Chef-zero saves all modifications made by your recipes to the local filesystem. It creates a JSON file containing all node attributes for your local workstation in the nodes directory. This way, the next time you run the Chef client in local mode, it will be aware of any changes your recipes made to the node.

Running knife in local mode

You can use knife in local mode, too. To set the run list of a node named laptop (instead of having to override it with -o), you can run the following command:

mma@laptop:~/chef-repo $ knife node run_list add -z laptop 'recipe[my_cookbook]'

Moving to hosted Chef or your own Chef server

When you're done editing and testing your cookbooks on your local workstation with chef-zero, you can seamlessly upload them to hosted Chef or your own Chef server:

Note

Make sure you bump the version number of modified cookbooks in their metadata.rb file and commit them to your version control system before uploading to the Chef Server.

mma@laptop:~/chef-repo $ berks upload
Uploaded ...

See also

 

Using roles


Roles group nodes with similar configurations. Typical cases are using roles for web servers, database servers, and so on.

You can set custom run lists for all the nodes in your roles and override attribute values from within your roles.

Let's see how to create a simple role.

Getting ready

For the following examples, I assume that you have a node named server and that you have at least one cookbook (I'll use the ntp cookbook) registered with your Chef server.

How to do it…

Let's create a role and see what we can do with it:

  1. Create a role:

    mma@laptop:~/chef-repo $ subl roles/web_servers.rb
    name "web_servers"
    description "This role contains nodes, which act as web servers"
    run_list "recipe[ntp]"
    default_attributes 'ntp' => {
      'ntpdate' => {
        'disable' => true
      }
    }
    
  2. Upload the role on the Chef server:

    mma@laptop:~/chef-repo $ knife role from file web_servers.rb
    Updated Role web_servers
    
  3. Assign the role to a node called server:

    mma@laptop:~/chef-repo $ knife node run_list add server 'role[web_servers]'
    server:
      run_list: role[web_servers]
    
  4. Log in to your node and run the Chef client:

    user@server:~$ sudo chef-client
    ...TRUNCATED OUTPUT...
    [2016-10-03T18:52:10+00:00] INFO: Run List is [role[web_servers]]
    [2016-10-03T18:52:10+00:00] INFO: Run List expands to [ntp]
    [2016-10-03T18:52:10+00:00] INFO: Starting Chef Run for server
    ...TRUNCATED OUTPUT...
    

How it works...

You define a role in a Ruby (or a JSON) file inside the roles folder of your Chef repository. A role consists of a name attribute and a description attribute. Additionally, a role usually contains a role-specific run list and role-specific attribute settings.

Every node with a role in its run list will have the role's run list expanded into its own. This means that all the recipes (and roles) that are in the role's run list will be executed on your nodes.

You need to upload your role to your Chef server by using the knife role from file command.

Only then should you add the role to your node's run list.

Running the Chef client on a node having your role in its run list will execute all the recipes listed in the role.

The attributes you define in your role will be merged with attributes from environments and cookbooks, according to the precedence rules described at https://docs.chef.io/roles.html#attribute-precedence.

See also

  • Find out how roles can help you find nodes in the Using search to find nodes recipe in Chapter 4, Writing Better Cookbooks

  • Learn more about in the Overriding attributes recipe in Chapter 4, Writing Better Cookbooks

  • Read everything about roles at https://docs.chef.io/roles.html

 

Using environments


Having separate environments for development, testing, and production is a good way to be able to develop and test cookbook updates, and other configuration changes in isolation. Chef enables you to group your nodes into separate environments so as to support an ordered development flow.

Getting ready

For the following examples, let's assume that you have a node named server in the _default environment and that you have at least one cookbook (I'll use the ntp cookbook) registered with your Chef server.

How to do it…

Let's see how to manipulate environments using knife:

Note

This is only a good idea if you want to play around. For serious work, please create files describing your environments and put them under version control as described in the There's more… section of this recipe.

  1. Create your environment on-the-fly using knife. The following command will open your shell's default editor so that you can modify the environment definition:

    Note

    Make sure you've set your EDITOR environment variable to your preferred one.

    mma@laptop:~/chef-repo $ knife environment create dev
    {
      "name": "dev",
      "description": "",
      "cookbook_versions": {
      },
      "json_class": "Chef::Environment",
      "chef_type": "environment",
      "default_attributes": {
      },
      "override_attributes": {
      }
    }
    Created dev
    
  2. List the available environments:

    mma@laptop:~/chef-repo $ knife environment list
    _default
    dev
    
  3. List the nodes for all the environments:

    mma@laptop:~/chef-repo $ knife node list
    server
    
  4. Verify that the node server is not in the dev environment yet by listing nodes in the dev environment only:

    mma@laptop:~/chef-repo $ knife node list -E dev
    mma@laptop:~/chef-repo $
    
  5. Change the environment of the server to dev using knife:

    mma@laptop:~/chef-repo $ knife node environment set server book
    server:
      chef_environment: dev
    
  6. List the nodes in the dev environment again:

    mma@laptop:~/chef-repo $ knife node list -E dev
    server
    
  7. Use specific cookbook versions and override certain attributes for the environment:

    mma@laptop:~/chef-repo $ knife environment edit dev
    {
      "name": "dev",
      "description": "",
      "cookbook_versions": {
        "ntp": "1.6.8"
      },
      "json_class": "Chef::Environment",
      "chef_type": "environment",
      "default_attributes": {
      },
      "override_attributes": {
        "ntp": {
          "servers": ["0.europe.pool.ntp.org", "1.europe.pool.ntp.org", "2.europe.pool.ntp.org", "3.europe.pool.ntp.org"]
        }
      }
    }
    Saved dev
    

How it works…

A common use of environments is to promote cookbook updates from development to staging and then into production. Additionally, they enable you to use different cookbook versions on separate sets of nodes and environment-specific attributes. You might have nodes with less memory in your staging environment as in your production environment. By using environment-specific default attributes, you can, for example, configure your MySQL service to consume less memory on staging than on production.

Note

The Chef server always has an environment called _default, which cannot be edited or deleted. All the nodes go in there if you don't specify any other environment.

Be aware that roles are not environment-specific. You may use environment-specific run lists, though.

The node's environment can be queried using the node.chef_environment method inside your cookbooks.

There's more…

If you want your environments to be under version control (and you should), a better way to create a new environment is to create a new Ruby file in the environments directory inside your Chef repository:

mma@laptop:~/chef-repo $ cd environments
mma@laptop:~/chef-repo $ subl dev.rb
name "dev"

You should add, commit, and push your new environment file to GitHub:

mma@laptop:~/chef-repo $ git add environments/dev.rb
mma@laptop:~/chef-repo $ git commit -a -m "the dev environment"
mma@laptop:~/chef-repo $ git push

Now, you can create the environment on the Chef server from the newly created file using knife:

mma@laptop:~/chef-repo $ knife environment from file dev.rb
Created environment dev

Tip

You have to deal with two artifact storages here. You have to use your version control system and knife / Berkshelf to sync your local changes to your Chef server. The Chef server is not aware of any changes that you do when using your version control system, and vice versa.

There is a way to migrate all the nodes from one environment to another by using knife exec:

mma@laptop:~/chef-repo $ knife exec -E 'nodes.transform("chef_environment:_default") { |n| n.chef_environment("dev")

You can limit your search for nodes in a specific environment:

mma@laptop:~/chef-repo $ knife search node "chef_environment:dev"
1 item found

See also

  • If you want to set up a virtual machine as a node, see the Managing virtual machines with Vagrant recipe in this chapter

  • Read more about environments at https://docs.chef.io/environments.html

 

Freezing cookbooks


Uploading broken cookbooks that override your working ones is a major pain and can result in widespread outages throughout your infrastructure. If you have a cookbook version, you tested successfully with Test Kitchen, it's a good idea to freeze this version so that no one can overwrite the same version with broken code. When used together with version constraints that are specified in your environment manifests, freezing cookbooks can keep your production servers safe from accidental changes.

Note

Berkshelf takes care of freezing cookbooks automatically.

Getting ready

Make sure you have at least one cookbook (I'll use the ntp cookbook) registered with your Chef server.

How to do it…

Let's see what happens if we freeze a cookbook.

  1. Upload a cookbook and freeze it:

    mma@laptop:~/chef-repo $ knife cookbook upload ntp --freeze
    Uploading ntp            [3.2.0]
    Uploaded 1 cookbook.
    
  2. Try to upload the same cookbook version again:

    mma@laptop:~/chef-repo $ knife cookbook upload ntp
    Uploading ntp            [3.2.0]
    ERROR: Version 3.2.0 of cookbook ntp is frozen. Use --force to override.
    WARNING: Not updating version constraints for ntp in the environment as the cookbook is frozen.
    ERROR: Failed to upload 1 cookbook.
    
  3. Change the cookbook version:

    mma@laptop:~/chef-repo $ subl cookbooks/ntp/metadata.rb
    
    version           "3.2.1"
    
  4. Upload the cookbook again:

    mma@laptop:~/chef-repo $ knife cookbook upload ntp
    Uploading ntp            [3.2.1]
    Uploaded 1 cookbook.
    

How it works…

By using the --freeze option when uploading a cookbook, you tell the Chef server that it should not accept any changes to the same version of the cookbook anymore. This is important if you're using environments and want to make sure that your production environment cannot be broken by uploading a corrupted cookbook.

By changing the version number of your cookbook, you can upload the new version. Then you can make, for example, your staging environment use that new cookbook version.

There's more…

To support a more elaborate workflow, you can use the knife-spork knife plugin, which comes pre-installed with the Chef DK. It helps multiple developers work on the same Chef server and repository without treading on each other's toes. You can find more information about it at https://docs.chef.io/plugin_knife_spork.html.

See also

 

Running the Chef client as a daemon


While you can run the Chef client on your nodes manually whenever you change something in your Chef repository, it's sometimes preferable to have the Chef client run automatically every so often. Letting the Chef client run automatically makes sure that no node misses out any updates.

Getting ready

You need to have a node registered with your Chef server. It needs to be able to run chef-client without any errors.

How to do it…

Let's see how to start the Chef client in daemon mode so that it runs automatically:

  1. Start the Chef client in daemon mode, running every 30 minutes:

    user@server:~$ sudo chef-client -i 1800
    
  2. Validate that the Chef client runs as a daemon:

    user@server:~$ ps auxw | grep chef-client
    

How it works…

The -i parameter will start the Chef client as a daemon. The given number is the seconds between each Chef client run. In the previous example, we specified 1,800 seconds, which results in the Chef client running every 30 minutes.

You can use the same command in a service startup script.

Tip

You can use the chef-client cookbook to install the Chef client as a service. See: https://supermarket.chef.io/cookbooks/chef-client for details.

There's more…

Instead of running the Chef client as a daemon, you can use a Cronjob to run it every so often:

user@server:~$ subl /etc/cron.d/chef_client
PATH=/usr/local/bin:/usr/bin:/bin
# m h dom mon dow user command
*/15 * * * * root chef-client -l warn | grep -v 'retrying [1234]/5 in'

This cronjob will run the Chef client every 15 minutes and swallow the first four retrying warning messages. This is important to avoid Cron sending out e-mails if the connection to the Chef server is a little slow and the Chef client needs a few retries.

Note

It is possible to initiate a Chef client run at any time by sending the SIGUSR1 signal to the Chef client daemon:

user@server:~$ sudo killall -USR1 chef-client
About the Author
  • Matthias Marschall

    Matthias Marschall is a Software Engineer "made in Germany". His four children make sure that he feels comfortable in lively environments, and stays in control of chaotic situations. A lean and agile engineering lead, he's passionate about continuous delivery, infrastructure automation, and all things DevOps. In recent years, Matthias has helped build several web-based businesses, first with Java and then with Ruby on Rails. He quickly grew into system administration, writing his own configuration management tool before migrating his whole infrastructure to Chef in its early days. In 2008, he started a blog (http://www.agileweboperations.com) together with Dan Ackerson. There, they have shared their ideas about DevOps since the early days of the continually emerging movement. You can find him on Twitter as @mmarschall. Matthias holds a Master's degree in Computer Science (Dipl.-Inf. (FH)) and teaches courses on Agile Software Development at the University of Augsburg. When not writing or coding, Matthias enjoys drawing cartoons and playing Go. He lives near Munich, Germany.

    Browse publications by this author
Latest Reviews (1 reviews total)
Ottimo testo per chi vuole conoscere alcune soluzioni
Chef Cookbook - Third Edition
Unlock this book and the full library FREE for 7 days
Start now