Among the various configuration management frameworks available today, Opscode's Chef is a relative newcomer. But as the double-digit version number would suggest, Chef has been making strides toward adding new features and appears to be gaining some ground against its older and more mature competitors.
For any shop considering Chef for configuration management, the main question will be the level of familiarity and comfort with the Ruby programming language, which Chef relies on for driving all configuration changes.
[ Review: Puppet Enterprise 3.0 pulls more strings | Puppet or Chef: The configuration management dilemma | 12 clever cloud tools for devs and ops | Subscribe to InfoWorld's Data Center newsletter to stay on top of the latest developments. ]
Chef is available in a variety of different flavors. Opscode offers Hosted Chef, which is a hosted service that Opscode runs in the cloud and allows you to implement Chef without running your own local Chef server. Then there's Opscode's Private Chef, a commercial product that installs locally and offers an extended selection of features such as high availability and an enhanced Web UI. Lastly, there's the open source Chef, which is free but lacking in enterprise-grade features and somewhat more challenging to set up and deploy. For this review, I'll focus on Private Chef.
Next up, the Chef workstation needs to be configured. This is accomplished by pulling down an omnibus installer script from Opscode that determines the distribution and installs the requisite workstation packages. From there, the knife utility is used to configure the workstation and user. This requires pulling several configuration files and certificates from the Chef server to the workstation and placing them in specific locations. Once this is done and the installation questions (such as the URL for the Chef server) have been answered, the workstation should now be able to communicate with and control the Chef server.
At this point, we have a fully functional Chef installation, and we can start adding nodes. We can also log into the Web UI on the Chef server using the username and password created during the installation procedure.
Adding nodes in Chef is simple. On the workstation, the
knife bootstrap command is used to log into the target system via SSH and deploy the Chef client. It will also configure the client and server. Thus, adding a node to Chef is a scriptable one-liner, driven from the workstation. Chef does support Windows, but the Windows installer needs to be run on the client, as it obviously cannot be run through SSH by default. There are some community Cookbooks for Windows management and a Ruby gem for bootstrapping Windows clients, but they are not part of the default installation.
Once several nodes have been added, we can begin to install and modify configuration elements for those nodes. Chef makes use of Git to handle configurations. On the workstation, you use Git to clone the chef-repo repository, and from there, you download and create configuration elements for the deployment. All configuration is handled within the purview of Git repositories.
Using Chef Cookbooks
Cookbooks are Chef's configuration modules. They are used to craft configuration management elements to be deployed to nodes connected to the Chef server. Cookbooks are downloaded through Git on the workstation and wrapped by the
knife command, which is the general Chef management tool. All Cookbooks are built in Ruby, as Chef uses Ruby for all Cookbook functions. This means that administrators of a Chef environment must be well versed in Ruby to build their own Cookbooks, though modifying existing Cookbooks will be somewhat less challenging. This dependence on Ruby is both a positive and negative aspect of Chef, as Ruby is not necessarily a common language for sys admins, and it can present quite a learning curve for nonprogrammers.
As an example, we may want to install a Cookbook to ensure that the NTP service is installed and configured for our environment on all of our nodes. To do this, we would use the
knife command to download the NTP Cookbook:
knife cookbook site install ntp
This will place the NTP Cookbook in our chef-repo/cookbooks directory and set it up. From there, we need to dig into the Cookbook to make sure our preferred configuration settings are present.
Cookbooks have a specific file layout consisting of several directories such as "files," to store whole files that may need to be copied to the node; "templates," to house templates for the creation of new files with specific parameters; "attributes," to contain files that are parameter definitions; and "recipes," to store the Ruby scripts that are run to combine all of the above into a functioning Cookbook.
Applying node configuration
Because there's no functional push command available in Chef, we need to make sure that each node runs the chef-client executable on a scheduled basis. Although most configuration management tools set this up automatically, Chef does not. Thus, we need to add a cronjob on each node to have that node check in with the server periodically. If this isn't done, then even after a node has been bootstrapped, it will not check in with the server again. We can automate check-ins by using the chef-client Cookbook that adds a cronjob, but it's not done by default.
Assuming we have our nodes set up to run chef-client every half an hour, once our NTP Cookbook has been applied to the node, it will run, and our NTP service will soon be configured.
Opscode provides a large collection of ready-to-mix recipes in its GitHub repository, and chances are you'll find existing Cookbooks to match a significant number of common configuration tasks, but you'll need to bust out your Ruby skills to make your own from scratch.
Alongside Cookbooks, Chef has the concept of a data bag -- essentially a JSON object containing any number of global variables. These variables can be accessed by Cookbooks to use when running recipes. You can create data bags with the
knife command or manually or through the Web UI, though you will likely find that creating the JSON objects manually, then using
knife data bag from file mybag filename.json is easiest when working with large numbers of variables.
Once you have data bags in place, your recipes can use them to populate variables during runtime -- for instance, ensuring that certain user accounts are created on a new system with specific passwords and so forth. Data bags can be encrypted using a shared secret for protection of sensitive information.