Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Chef Cookbook
Chef Cookbook

Chef Cookbook: Achieve powerful IT infrastructure management and automation , Third Edition

eBook
€20.98 €29.99
Paperback
€36.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Table of content icon View table of contents Preview book icon Preview Book

Chef Cookbook

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 to do it…

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
Left arrow icon Right arrow icon

Key benefits

  • Immediately apply Devops techniques and methods, then combine them with powerful Chef tools to manage and automate your infrastructure
  • Address the growing challenges of code management, cloud, and virtualization with Chef quickly
  • Explore and implement the important aspects of Chef Automate using this recipe-based guide

Description

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.

Who is this book for?

This book is for system engineers and administrators who have a fundamental understanding of information management systems and infrastructure. It is also for DevOps Engineers, IT professionals, and organizations who want to automate and gain greater control of their infrastructures with Chef. No experience with Chef is needed, but may help.

What you will learn

  • Test your cookbooks with Test Kitchen
  • Manage cookbook dependencies with Berkshelf
  • Use reporting to keep track of what happens during the execution of chef-client runs across all of the machines
  • Create custom Ohai and Knife plugins
  • Build a high-availability service using Heartbeat
  • Use a HAProxy to load-balance multiple web servers
Estimated delivery fee Deliver to Latvia

Premium delivery 7 - 10 business days

€25.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Feb 03, 2017
Length: 268 pages
Edition : 3rd
Language : English
ISBN-13 : 9781786465351
Vendor :
Chef
Languages :
Tools :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Estimated delivery fee Deliver to Latvia

Premium delivery 7 - 10 business days

€25.95
(Includes tracking information)

Product Details

Publication date : Feb 03, 2017
Length: 268 pages
Edition : 3rd
Language : English
ISBN-13 : 9781786465351
Vendor :
Chef
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 150.97
Chef: Powerful Infrastructure Automation
€80.99
Mastering Chef Provisioning
€32.99
Chef Cookbook
€36.99
Total 150.97 Stars icon

Table of Contents

8 Chapters
1. Chef Infrastructure Chevron down icon Chevron up icon
2. Evaluating and Troubleshooting Cookbooks and Chef Runs Chevron down icon Chevron up icon
3. Chef Language and Style Chevron down icon Chevron up icon
4. Writing Better Cookbooks Chevron down icon Chevron up icon
5. Working with Files and Packages Chevron down icon Chevron up icon
6. Users and Applications Chevron down icon Chevron up icon
7. Servers and Cloud Infrastructure Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela