Chef

Inspired by one of the other challengers I started to experiment with Chef. fvan is using Puppet to provision his Raspberry Pi's. To get more knowledge on the several tools out there we decided to both try one. So that's why I started using Chef.

 

Chef vs Puppet

Both tools are open source projects built for automatically provisioning nodes with software and configuration. They both have a fairly similar setup using a server and clients on all nodes. The biggest difference is in how you manage your configuration. Puppet uses a Ruby-based DSL which is similar to JSON, Chef uses pure Ruby. This makes Chef a bit more powerful out-of-the-box. As Rich Morrow said in his report:

Whereas Chef tries to provide more power to the user, Puppet puts safety rails around them.

Some noteworthy differences:

ChefPuppet
LanguageRubyDSL
ExecutionOrder enforcedModel driven
ApproachProgrammer's approachSysadmin friendly
Used by a.o.Facebook & AdobeTwitter & Intel

 

To learn more about Puppet I refer you to Frederick's posts, here more about Chef!

 

The basics

A typical setup consists of three elements: your workstation, a server, and nodes.

Chef setup

The server is the central repository for all code and it also keeps knowledge about every node it manages. From your workstation you write and verify the configuration policy and then upload it to the server. When you run chef-client on a node the latest code is downloaded from the server and the node's configuration is brought up-to-date.

 

Preparation

To start you need a set up workstation and server. You can install a server locally or use a hosted version. Hosted Chef is free up to 5 nodes, so that's how we'll start.

  1. Install the Chef Development Kit
  2. Sign up for the trial of Hosted Chef
  3. Create an Organization at https://manage.chef.io/
  4. Go to the Administration tab, selection your new organization and click Generate Knife Config
  5. Save knife.rb to ~/.chef
  6. Copy your private key (created during signup) to ~/.chef as well
  7. Test the connection between your workstation and the server with knife ssl check

 

Your first cookbook & recipe

A cookbook is a set of configuration describing a service or node. It consists of recipes, template files and attributes. A recipe describes everything that is required to configure part of a system, for example which software packages to install, how to configure them or execute other recipes.

 

For this example we'll create a simple cookbook which creates a file, just like in Fredericks example. Start with generating the cookbook:

chef generate cookbook test-chef

 

You now have the following directory structure:

.
└── test-chef
    ├── Berksfile
    ├── chefignore
    ├── metadata.rb
    ├── README.md
    ├── recipes
    │   └── default.rb
    ├── spec
    │   ├── spec_helper.rb
    │   └── unit
    │       └── recipes
    │           └── default_spec.rb
    └── test
        └── integration
            ├── default
            │   └── serverspec
            │       └── default_spec.rb
            └── helpers
                └── serverspec
                    └── spec_helper.rb

 

As you can see there is already a default recipe created. Let's edit that to contain the following:

file '/tmp/testfile' do
  content 'test content'
  mode '0444'
end

 

Now upload it to your server:

knife cookbook upload test-chef

 

And bootstrap a node:

knife bootstrap ADDRESS --ssh-user USER --ssh-password 'PASSWORD' --sudo --use-sudo-password --node-name node1 --run-list 'recipe[test-chef]'

 

You'll see that Chef is installed on the node and in the end the file is created according to the recipe. When you run <code>chef-client</code> from the node it will check if there is a new version and if the file is still there. If something is not according to the recipe – it will fix it.

 

Supermarket

Of course there are already lots of cookbooks created by others, they are shared in the Supermarket. You can easily add a dependency to one of these cookbooks. There are several ways to override attributes used in the cookbook, or even override complete files to make sure it does exactly what you want.

 

You should have a basic understanding of Chef now, there is however much more. To let you get more familiar with Chef they have some excellent tutorials. In upcoming blogposts I'll show my cookbooks as well.

 

The ugly: Chef on a Raspberry Pi

Now the bad news: Chef doesn't support the Raspberry Pi out-of-the-box, so you can't bootstrap it as easily as on other platforms. It also needs a fairly recent version of Ruby, which is not available in the Jessie repository. Luckily you can overcome this by using a custom bootstrap script and using the Stretch (the upcoming version of Debian/Raspbian) repository.

 

A good starting point is the Raspbian-Bootstrap by Dayne. It's made for Wheezy, so we'll have to update it a bit. It took some experimenting, but at some point I found a working solution. We can skip the custom Ruby build (which takes a long time) by using the ruby2.3 package from the Stretch repository and I've updated the syntax of the configuration part to the one from the default Chef bootstrap.

 

This brings us to the following steps:

  1. Take a Raspberry Pi with a clean Raspbian install (I use raspbian-ua-netinst, as it gives a minimal install)
  2. Download my version of Raspbian-Bootstrap
  3. Use knife to bootstrap with a custom template:
    knife bootstrap PI_IP_ADDRESS -t raspbian-jessie-chef.erb --ssh-user root --ssh-password 'raspbian' --node-name 'NODE_NAME' --run-list 'recipe[thuis-base::default]'
    
    This will do the following:
    • Add the Raspbian Stretch repository to Apt and update the Apt index
    • Remove any existing versions of Ruby
    • Install Ruby 2.3 plus build tools from the Stretch repository
    • Install gems needed for Chef + Chef itself
    • Add basic configuration for Chef
    • Start chef-client for the first time running in this case my base cookbook thuis-base
  4. Start using Chef on your Raspberry!