About Nodes

[edit on GitHub]

A node is any machine—physical, virtual, cloud, network device, etc.—that is under management by Chef.

The types of nodes that can be managed by Chef include, but are not limited to, the following:

Node Type Description
A physical node is typically a server or a virtual machine, but it can be any active device attached to a network that is capable of sending, receiving, and forwarding information over a communications channel. In other words, a physical node is any active device attached to a network that can run a chef-client and also allow that chef-client to communicate with a Chef server.
A cloud-based node is hosted in an external cloud-based service, such as Amazon Web Services (AWS), OpenStack, Rackspace, Google Compute Engine, or Microsoft Azure. Plugins are available for knife that provide support for external cloud-based services. knife can use these plugins to create instances on cloud-based services. Once created, the chef-client can be used to deploy, configure, and maintain those instances.
A virtual node is a machine that runs only as a software implementation, but otherwise behaves much like a physical machine.
A network node is any networking device—a switch, a router—that is being managed by a chef-client, such as networking devices by Juniper Networks, Arista, Cisco, and F5. Use Chef to automate common network configurations, such as physical and logical Ethernet link properties and VLANs, on these devices.
Containers are an approach to virtualization that allows a single operating system to host many working configurations, where each working configuration—a container—is assigned a single responsibility that is isolated from all other responsibilities. Containers are popular as a way to manage distributed and scalable applications and services.

The key components of nodes that are under management by Chef include:

Component Description

A chef-client is an agent that runs locally on every node that is under management by Chef. When a chef-client is run, it will perform all of the steps that are required to bring the node into the expected state, including:

  • Registering and authenticating the node with the Chef server
  • Building the node object
  • Synchronizing cookbooks
  • Compiling the resource collection by loading each of the required cookbooks, including recipes, attributes, and all other dependencies
  • Taking the appropriate and required actions to configure the node
  • Looking for exceptions and notifications, handling each as required

RSA public key-pairs are used to authenticate the chef-client with the Chef server every time a chef-client needs access to data that is stored on the Chef server. This prevents any node from accessing data that it shouldn’t and it ensures that only nodes that are properly registered with the Chef server can be managed.

Ohai is a tool that is used to detect attributes on a node, and then provide these attributes to the chef-client at the start of every chef-client run. Ohai is required by the chef-client and must be present on a node. (Ohai is installed on a node as part of the chef-client install process.)

The types of attributes Ohai collects include (but are not limited to):

  • Platform details
  • Network usage
  • Memory usage
  • CPU data
  • Kernel data
  • Host names
  • Fully qualified domain names
  • Virtualization data
  • Cloud provider metadata
  • Other configuration details

Attributes that are collected by Ohai are automatic level attributes, in that these attributes are used by the chef-client to ensure that these attributes remain unchanged after the chef-client is done configuring the node.

The chef-client Run

A “chef-client run” is the term used to describe a series of steps that are taken by the chef-client when it is configuring a node. The following diagram shows the various stages that occur during the chef-client run, and then the list below the diagram describes in greater detail each of those stages.

_images/chef_run.png

During every chef-client run, the following happens:

Stages Description
Get configuration data The chef-client gets process configuration data from the client.rb file on the node, and then gets node configuration data from Ohai. One important piece of configuration data is the name of the node, which is found in the node_name attribute in the client.rb file or is provided by Ohai. If Ohai provides the name of a node, it is typically the FQDN for the node, which is always unique within an organization.
Authenticate to the Chef Server The chef-client authenticates to the Chef server using an RSA private key and the Chef server API. The name of the node is required as part of the authentication process to the Chef server. If this is the first chef-client run for a node, the chef-validator will be used to generate the RSA private key.
Get, rebuild the node object The chef-client pulls down the node object from the Chef server. If this is the first chef-client run for the node, there will not be a node object to pull down from the Chef server. After the node object is pulled down from the Chef server, the chef-client rebuilds the node object. If this is the first chef-client run for the node, the rebuilt node object will contain only the default run-list. For any subsequent chef-client run, the rebuilt node object will also contain the run-list from the previous chef-client run.
Expand the run-list The chef-client expands the run-list from the rebuilt node object, compiling a full and complete list of roles and recipes that will be applied to the node, placing the roles and recipes in the same exact order they will be applied. (The run-list is stored in each node object’s JSON file, grouped under run_list.)
Synchronize cookbooks The chef-client asks the Chef server for a list of all cookbook files (including recipes, templates, resources, providers, attributes, libraries, and definitions) that will be required to do every action identified in the run-list for the rebuilt node object. The Chef server provides to the chef-client a list of all of those files. The chef-client compares this list to the cookbook files cached on the node (from previous chef-client runs), and then downloads a copy of every file that has changed since the previous chef-client run, along with any new files.
Reset node attributes All attributes in the rebuilt node object are reset. All attributes from attribute files, environments, roles, and Ohai are loaded. Attributes that are defined in attribute files are first loaded according to cookbook order. For each cookbook, attributes in the default.rb file are loaded first, and then additional attribute files (if present) are loaded in lexical sort order. All attributes in the rebuilt node object are updated with the attribute data according to attribute precedence. When all of the attributes are updated, the rebuilt node object is complete.
Compile the resource collection The chef-client identifies each resource in the node object and builds the resource collection. Libraries are loaded first to ensure that all language extensions and Ruby classes are available to all resources. Next, attributes are loaded, followed by lightweight resources, and then all definitions (to ensure that any pseudo-resources within definitions are available). Finally, all recipes are loaded in the order specified by the expanded run-list. This is also referred to as the “compile phase”.
Converge the node The chef-client configures the system based on the information that has been collected. Each resource is executed in the order identified by the run-list, and then by the order in which each resource is listed in each recipe. Each resource in the resource collection is mapped to a provider. The provider examines the node, and then does the steps necessary to complete the action. And then the next resource is processed. Each action configures a specific part of the system. This process is also referred to as convergence. This is also referred to as the “execution phase”.
Update the node object, process exception and report handlers

When all of the actions identified by resources in the resource collection have been done, and when the chef-client run finished successfully, the chef-client updates the node object on the Chef server with the node object that was built during this chef-client run. (This node object will be pulled down by the chef-client during the next chef-client run.) This makes the node object (and the data in the node object) available for search.

The chef-client always checks the resource collection for the presence of exception and report handlers. If any are present, each one is processed appropriately.

Stop, wait for the next run When everything is configured and the chef-client run is complete, the chef-client stops and waits until the next time it is asked to run.

About Run-lists

A run-list defines all of the information necessary for Chef to configure a node into the desired state. A run-list is:

  • An ordered list of roles and/or recipes that are run in the exact order defined in the run-list; if a recipe appears more than once in the run-list, the chef-client will not run it twice
  • Always specific to the node on which it runs; nodes may have a run-list that is identical to the run-list used by other nodes
  • Stored as part of the node object on the Chef server
  • Maintained using knife, and then uploaded from the workstation to the Chef server, or is maintained using the Chef management console

Run-list Format

A run-list must be in one of the following formats: fully qualified, cookbook, or default. Both roles and recipes must be in quotes, for example:

'role[NAME]'

or

'recipe[COOKBOOK::RECIPE]'

Use a comma to separate roles and recipes when adding more than one item the run-list:

'recipe[COOKBOOK::RECIPE],COOKBOOK::RECIPE,role[NAME]'

Empty Run-lists

Use an empty run-list to determine if a failed chef-client run has anything to do with the recipes that are defined within that run-list. This is a quick way to discover if the underlying cause of a chef-client run failure is a configuration issue. If a failure persists even if the run-list is empty, check the following:

  • Configuration settings in the knife.rb file
  • Permissions for the user to both the Chef server and to the node on which the chef-client run is to take place

About why-run Mode

why-run mode is a way to see what the chef-client would have configured, had an actual chef-client run occurred. This approach is similar to the concept of “no-operation” (or “no-op”): decide what should be done, but then don’t actually do anything until it’s done right. This approach to configuration management can help identify where complexity exists in the system, where inter-dependencies may be located, and to verify that everything will be configured in the desired manner.

When why-run mode is enabled, a chef-client run will occur that does everything up to the point at which configuration would normally occur. This includes getting the configuration data, authenticating to the Chef server, rebuilding the node object, expanding the run-list, getting the necessary cookbook files, resetting node attributes, identifying the resources, and building the resource collection and does not include mapping each resource to a provider or configuring any part of the system.

Note

why-run mode is not a replacement for running cookbooks in a test environment that mirrors the production environment. Chef uses why-run mode to learn more about what is going on, but also Kitchen on developer systems, along with an internal OpenStack cloud and external cloud providers to test more thoroughly.

When the chef-client is run in why-run mode, certain assumptions are made:

  • If the service resource cannot find the appropriate command to verify the status of a service, why-run mode will assume that the command would have been installed by a previous resource and that the service would not be running
  • For not_if and only_if attribute, why-run mode will assume these are commands or blocks that are safe to run. These conditions are not designed to be used to change the state of the system, but rather to help facilitate idempotency for the resource itself. That said, it may be possible that these attributes are being used in a way that modifies the system state
  • The closer the current state of the system is to the desired state, the more useful why-run mode will be. For example, if a full run-list is run against a fresh system, that run-list may not be completely correct on the first try, but also that run-list will produce more output than a smaller run-list

For example, the service resource can be used to start a service. If the action is :start and the service is not running, then start the service (if it is not running) and do nothing (if it is running). What about a service that is installed from a package? The chef-client cannot check to see if the service is running until after the package is installed. A simple question that why-run mode can answer is what the chef-client would say about the state of the service after installing the package because service actions often trigger notifications to other resources. So it can be important to know in advance that any notifications are being triggered correctly.

For a detailed explanation of the dry-run concept and how it relates to the why-run mode, see this blog post.

About Node Names

The name of a node is required as part of the authentication process to the Chef server. The name of each node must be unique within an organization, but otherwise can be any string that matches the following regular expression:

/^[\-[:alnum:]_:.]+$/

The name of a node can be obtained from the node_name attribute in the client.rb file or by allowing Ohai to collect this data during the chef-client run. When Ohai collects this data during the chef-client run, it uses the FQDN name of the node (which is always unique within an organization) as the name of the node.

Using the FQDN as the node name, and then allowing Ohai to collect this information during each chef-client run, is the recommended approach and the easiest way to ensure that the names of all nodes across the organization are unique.

Manage Nodes

There are several ways to manage nodes directly, including by using knife, the Chef management console add-on for the Chef server, or by using command-line tools that are specific to chef-client.

  • knife can be used to create, edit, view, list, tag, and delete nodes.
  • knife plug-ins can be used to create, edit, and manage nodes that are located on cloud providers.
  • The Chef management console add-on can be used to create, edit, view, list, tag, and delete nodes. In addition, node attributes can be modified and nodes can be moved between environments.
  • The chef-client can be used to manage node data using the command line and JSON files. Each JSON file contains a hash, the elements of which are added as node attributes. In addition, the run_list setting allows roles and/or recipes to be added to the node.
  • chef-solo can be used to manage node data using the command line and JSON files. Each JSON file contains a hash, the elements of which are added as node attributes. In addition, the run_list setting allows roles and/or recipes to be added to the node.
  • The command line can also be used to edit JSON files and files that are related to third-party services, such as Amazon EC2, where the JSON files can contain per-instance metadata that is stored in a file on-disk and then read by chef-solo or chef-client as required.

Node Objects

For the chef-client, two important aspects of nodes are groups of attributes and run-lists. An attribute is a specific piece of data about the node, such as a network interface, a file system, the number of clients a service running on a node is capable of accepting, and so on. A run-list is an ordered list of recipes and/or roles that are run in an exact order. The node object consists of the run-list and node attributes, which is a JSON file that is stored on the Chef server. The chef-client gets a copy of the node object from the Chef server during each chef-client run and places an updated copy on the Chef server at the end of each chef-client run.

An attribute is a specific detail about a node. Attributes are used by the chef-client to understand:

  • The current state of the node
  • What the state of the node was at the end of the previous chef-client run
  • What the state of the node should be at the end of the current chef-client run

Attributes are defined by:

  • The state of the node itself
  • Cookbooks (in attribute files and/or recipes)
  • Roles
  • Environments

During every chef-client run, the chef-client builds the attribute list using:

  • Data about the node collected by Ohai
  • The node object that was saved to the Chef server at the end of the previous chef-client run
  • The rebuilt node object from the current chef-client run, after it is updated for changes to cookbooks (attribute files and/or recipes), roles, and/or environments, and updated for any changes to the state of the node itself

After the node object is rebuilt, all of the attributes are compared, and then the node is updated based on attribute precedence. At the end of every chef-client run, the node object that defines the current state of the node is uploaded to the Chef server so that it can be indexed for search.

Attributes

An attribute is a specific detail about a node, such as an IP address, a host name, a list of loaded kernel modules, the version(s) of available programming languages that are available, and so on. An attribute may be unique to a specific node or it can be identical across every node in the organization. Attributes are most commonly set from a cookbook, by using knife, or are retrieved by Ohai from each node prior to every chef-client run. All attributes are indexed for search on the Chef server. Good candidates for attributes include:

  • any cross-platform abstraction for an application, such as the path to a configuration file
  • default values for tunable settings, such as the amount of memory assigned to a process or the number of workers to spawn
  • anything that may need to be persisted in node data between chef-client runs

In general, attribute precedence is set to enable cookbooks and roles to define attribute defaults, for normal attributes to define the values that should be specific for a node, and for override attributes to force a certain value, even when a node already has that value specified.

One approach is to set attributes at the same precedence level by setting attributes in a cookbook’s attribute files, and then also setting the same default attributes (but with different values) using a role. The attributes set in the role will be deep merged on top of the attributes from the attribute file, and the attributes set by the role will take precedence over the attributes specified in the cookbook’s attribute files.

Another (much less common) approach is to set a value only if an attribute has no value. This can be done by using the _unless variants of the attribute priority methods:

  • default_unless

  • set_unless (normal_unless is an alias of set_unless; use either alias to set an attribute with a normal attribute precedence.)

    Note

    This method was deprecated in Chef client 12.12 and will be removed in Chef 14. Please use default_unless or override_unless instead.

  • override_unless

Note

Use the _unless variants carefully (and only when necessary) because when they are used, attributes applied to nodes may become out of sync with the values in the cookbooks as these cookbooks are updated. This approach can create situations where two otherwise identical nodes end up having slightly different configurations and can also be a challenge to debug.

Note

Attributes can be configured in cookbooks (attribute files and recipes), roles, and environments. In addition, Ohai collects attribute data about each node at the start of the chef-client run. See https://docs.chef.io/attributes.html for more information about how all of these attributes fit together.

Attribute Types

The chef-client uses six types of attributes to determine the value that is applied to a node during the chef-client run. In addition, the chef-client sources attribute values from up to five locations. The combination of attribute types and sources allows for up to 15 different competing values to be available to the chef-client during the chef-client run:

Attribute Type Description
default A default attribute is automatically reset at the start of every chef-client run and has the lowest attribute precedence. Use default attributes as often as possible in cookbooks.
force_default Use the force_default attribute to ensure that an attribute defined in a cookbook (by an attribute file or by a recipe) takes precedence over a default attribute set by a role or an environment.
normal A normal attribute is a setting that persists in the node object. A normal attribute has a higher attribute precedence than a default attribute.
override An override attribute is automatically reset at the start of every chef-client run and has a higher attribute precedence than default, force_default, and normal attributes. An override attribute is most often specified in a recipe, but can be specified in an attribute file, for a role, and/or for an environment. A cookbook should be authored so that it uses override attributes only when required.
force_override Use the force_override attribute to ensure that an attribute defined in a cookbook (by an attribute file or by a recipe) takes precedence over an override attribute set by a role or an environment.
automatic An automatic attribute contains data that is identified by Ohai at the beginning of every chef-client run. An automatic attribute cannot be modified and always has the highest attribute precedence.

Attribute Persistence

At the beginning of a chef-client run, all attributes are reset. The chef-client rebuilds them using automatic attributes collected by Ohai at the beginning of the chef-client run and then using default and override attributes that are specified in cookbooks or by roles and environments. Normal attributes are never reset. All attributes are then merged and applied to the node according to attribute precedence. At the conclusion of the chef-client run, the attributes that were applied to the node are saved to the Chef server as part of the node object.

Attribute Precedence

Attributes are always applied by the chef-client in the following order:

  1. A default attribute located in a cookbook attribute file
  2. A default attribute located in a recipe
  3. A default attribute located in an environment
  4. A default attribute located in a role
  5. A force_default attribute located in a cookbook attribute file
  6. A force_default attribute located in a recipe
  7. A normal attribute located in a cookbook attribute file
  8. A normal attribute located in a recipe
  9. An override attribute located in a cookbook attribute file
  10. An override attribute located in a recipe
  11. An override attribute located in a role
  12. An override attribute located in an environment
  13. A force_override attribute located in a cookbook attribute file
  14. A force_override attribute located in a recipe
  15. An automatic attribute identified by Ohai at the start of the chef-client run

where the last attribute in the list is the one that is applied to the node.

Note

The attribute precedence order for roles and environments is reversed for default and override attributes. The precedence order for default attributes is environment, then role. The precedence order for override attributes is role, then environment. Applying environment override attributes after role override attributes allows the same role to be used across multiple environments, yet ensuring that values can be set that are specific to each environment (when required). For example, the role for an application server may exist in all environments, yet one environment may use a database server that is different from other environments.

Attribute precedence, viewed from the same perspective as the overview diagram, where the numbers in the diagram match the order of attribute precedence:

_images/overview_chef_attributes_precedence.png

Attribute precedence, when viewed as a table:

_images/overview_chef_attributes_table.png

Whitelist Attributes

Warning

When these settings are used, any attribute not defined in a whitelist will not be saved. Each attribute type is whitelisted independently of the other attribute types. For example, if automatic_attribute_whitelist defines attributes to be saved, but normal_attribute_whitelist, default_attribute_whitelist, and override_attribute_whitelist are not defined, then all normal, default and override attributes are saved, along with only the specified automatic attributes.

Attributes that should be saved by a node may be whitelisted in the client.rb file. The whitelist is a Hash of keys that specify each attribute to be saved.

Attributes are whitelisted by attribute type, with each attribute type being whitelisted independently. Each attribute type—automatic, default, normal, and override—may define whitelists by using the following settings in the client.rb file:

Setting Description
automatic_attribute_whitelist A Hash that whitelists automatic attributes, preventing non-whitelisted attributes from being saved. For example: ['network/interfaces/eth0']. Default value: all attributes are saved. If the Hash is empty, no attributes are saved.
default_attribute_whitelist A Hash that whitelists default attributes, preventing non-whitelisted attributes from being saved. For example: ['filesystem/dev/disk0s2/size']. Default value: all attributes are saved. If the Hash is empty, no attributes are saved.
normal_attribute_whitelist A Hash that whitelists normal attributes, preventing non-whitelisted attributes from being saved. For example: ['filesystem/dev/disk0s2/size']. Default value: all attributes are saved. If the Hash is empty, no attributes are saved.
override_attribute_whitelist A Hash that whitelists override attributes, preventing non-whitelisted attributes from being saved. For example: ['map - autohome/size']. Default value: all attributes are saved. If the Hash is empty, no attributes are saved.

Warning

It is recommended that only automatic_attribute_whitelist be used to whitelist attributes. This is primarily because automatic attributes generate the most data, but also that normal, default, and override attributes are typically much more important attributes and are more likely to cause issues if they are whitelisted incorrectly.

For example, normal attribute data similar to:

{
  "filesystem" => {
    "/dev/disk0s2" => {
      "size" => "10mb"
    },
    "map - autohome" => {
      "size" => "10mb"
    }
  },
  "network" => {
    "interfaces" => {
      "eth0" => {...},
      "eth1" => {...},
    }
  }
}

To whitelist the network attributes and prevent the other attributes from being saved, update the client.rb file:

normal_attribute_whitelist ['network/interfaces/']

When a whitelist is defined, any attribute of that type that is not specified in that attribute whitelist will not be saved. So based on the previous whitelist for normal attributes, the filesystem and map - autohome attributes will not be saved, but the network attributes will.

Leave the value empty to prevent all attributes of that attribute type from being saved:

normal_attribute_whitelist []

For attributes that contain slashes (/) within the attribute value, such as the filesystem attribute '/dev/diskos2', use an array. For example:

automatic_attribute_whitelist [['filesystem','/dev/diskos2']]