So here are some chef notes. I watched some videos, read some documentation and then I wrote some notes. I should probably find a new hobby.
The Chef-client run process
This page provides a good starting point and diagram. I extracted the high-level steps as follows:
- Get configuration data – Node gets process configuration data from it’s own
client.rb
and fromohai
- authentication – client authenticates to the chef server using RSA keys and node name. On first run, the chef-validator will be used to generate the RSA private key.
- get, rebuild node object – client pulls down node object from server and rebuilds it.
- expand the run-list – chef client expands the full run-list from the latest node object that should be applied and in what order.
- sync cookbooks – asks the chef for required cookbook files and pulls down any changed and new files (compared to whats in cache from last run)
- Reset node attributes – attributes in rebuilt node object are reset and refilled with attributes from files, environments, roles, and
ohai
. - Compile resource collection – determine all resources that will be needed to process the run-list
- Converge the node – client configures the system based on info collected
- Update the node object, process exception and report handlers – client updates node object on server and will go through any exception and report handling as necessary.
Authentication and Authorization
Communication done via Chef Server API via REST. The server requires authentication via public keys. Public keys stored on chef server, private keys on nodes. The chef-client
and knife
tools all use the Chef Server API and will sign a special group of HTTP headers with the private key.
During the first chef-client
run, there is no private key so the chef-client will try the private key assigned to the chef-validator. Assuming that goes successfully, the chef-client will obtain a client.pem
private key for future authentication.
The chef-client authentication workflow:
- Look in
/etc/chef/client.pem
for a node private key - If that doesn’t work, check the validator in
/etc/chef/validation.pem
During an initial knife bootstrap, knife will copy the validation pem over to the node to do an initial chef-client run.
Compile and Execute
This stage iterating through our run list resources, collecting that into a list, and then iterating over that on the client to determine next action. Chef client will compare to see if the resource is in the appropriate state. If it is already there, no action is taken. Otherwise, the client will work to put it in the desired state.
Node Object
- Any machine configured to be maintained by Chef
- Node object is always available to you from within a recipe
Each node must have a unique name within an organization. Chef defaults to the FQDN.
Nodes are made up of attributes
- Many are discovered automatically (
ohai
) - Other objects in Chef can add Node attributes (cookbooks, roles/environments, recipes, attribute files)
- Nodes are stored and indexed on the Chef server
- Many are discovered automatically (
You can quickly get various attribute data from your node through knife
or ohai
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
Knife searches are based on Apache Solr and are in the format:
1
|
|
- Key = field name found
- search pattern = what will be searched for
Examples:
1 2 3 4 5 |
|
Templates and Cross platform
You can utilize Ruby within the recipe which can help to create dynamic run-lists. Combining variables, loops, case statements, etc. can make for some powerful conditional recipes.
Variable usage:
1 2 3 4 5 6 7 8 9 |
|
Case usage:
1 2 3 4 5 6 7 8 9 10 11 |
|
Array iteration:
1 2 3 |
|
We can utilize an Embedded Ruby template instead of static files that will be dynamically modified when copied down to our node. These are commonly named with a .erb
suffix and can contain ruby code within text. In order to embed ruby we will need to utilize the <%= %>
tag:
1 2 3 4 5 |
|
We can feed in a template file with the template
resource like this:
1 2 3 4 5 6 7 8 9 10 |
|
The sudoers.erb file referenced above will need to go into the templates/default/sudoers.erb
instead of a typical file path at files/default/sudoers.erb
. Chef will try to match up the most specific file by the client platform though and will look in this order:
templates/
1. host-node[:fqdn]/
2. node[:platform]-node[:platform_version]/
3. node[:platform]-version_components/
4. node[:platform]/
5. default/
For example, you could store the file in templates/ubuntu-12.04/sudoers.erb
.
Attributes
Attributes
are specific details about a node and can be assigned from one of the following locations:
- Nodes (collected by Ohai at the start of each chef-client run)
- Attribute files (in cookbooks)
- Recipes (in cookbooks)
- Environments
- Roles
The precedence level that determines which attribute is applied is as follows :
- A default attribute located in a cookbook attribute file
- A default attribute located in a recipe
- A default attribute located in an environment
- A default attribute located in role
- A force_default attribute located in a cookbook attribute file
- A force_default attribute located in a recipe
- A normal attribute located in a cookbook attribute file
- A normal attribute located in a recipe
- An override attribute located in a cookbook attribute file
- An override attribute located in a recipe
- An override attribute located in a role
- An override attribute located in an environment
- A force_override attribute located in a cookbook attribute file
- A force_override attribute located in a recipe
- An automatic attribute identified by Ohai at the start of the chef-client run
You can more directly influence precedence by taking advantage of attribute types when getting and setting. The types available are (in order of precedence, lowest to highest):
default
– lowest precedence, should be used in cookbooks when possibleforce_default
– force attribute in cookbook to take over default set in an environment or rolenormal
– not reset during chef-client run and has higher precedence than defaultoverride
– reset at start of each client runforce_override
– ensure override in cookbook takes over for an override attribute in a role or environmentautomatic
– discovered byohai
and has highest precedence
To store attributes in a cookbook, we can place them in attributes/default.rb
:
1 2 3 4 5 6 7 |
|
Roles
A good way to bridge together cookbooks and attributes for re-use. To start a role, start by creating an .rb
file in your roles/
folder in the chef repository. Here is an example of the three required attributes:
1 2 3 4 |
|
Common role tasks in knife:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Environments
A way to logically break up workflow and reflect organizational patterns.
Every node can be assigned to a single environment. By default, all nodes
are part of the _default
environment. You can create a new environment by creating a *.rb file in the environments
folder of the chef-repo. This process is very similar to creating a new role. Your environment file needs
a name
, cookbook
, description
(default_attributes
and override_attributes
are optional):
1 2 3 4 5 |
|
Here are some environment management commands from knife:
1 2 3 4 5 6 7 8 |
|
It appears you’ll have to use a plugin to knife to modify environments but otherwise it is a very trivial task to perform from the chef server web interface.
Community Cookbooks
There is a great online resource for interacting with cookbooks from others online at http://community.opscode.com/cookbooks. Once you find a good looking cookbook you’d like to pull into your own environment (after proper vetting of course), you can use knife to assist here:
1 2 3 4 5 6 7 8 9 10 11 |
|
From what I can tell, using the site install
command is against chef best practices. You really should be vetting third-party code before pulling it down and committing it to your environment. There is a great community of chef tools and knife plugins out there. The Opscode folks have singled out some of the most common in the Chef Development Kit.
Okay! Great notes everyone!