Roles are a way of classifying the different types of services in your infrastructure, as shown in Figure 14-1.
Roles can be used to represent the types of servers in your infrastructure:
- Load balancer
- Application server
- Database cache
- Database
- Monitoring
Although you can add recipes directly to a node’s run list, that’s not how your infrastructure works. Think about how you normally refer to servers:
- “It’s a web server.”
- “It’s a database server.”
- “It’s a monitoring server.”
Roles allow you to conveniently encapsulate the run lists and attributes required for a server to be what you already think it is. Roles make it easy to configure many nodes identically without repeating yourself each time.
In addition to obvious roles, such as a “web server,” it is common practice to group any functionality that goes together into a role. The most common example is a base role, where you include all the recipes that should be run on every node.
Create a Web Server Role
Roles can be created and managed in the same fashion as data bags—there is a directory under chef-playgroundin which they are organized. The directory name is roles by default.
Use the chef-playground directory you created in Chapter 11. Use the same dual command prompt setup you used there. Start the
chef-zero
server on an open port in one window. We will be using port 9501 in the examples in this chapter:
Make sure the chef-playground directory is the current working directory:
Now run
knife upload nodes
to load up chef-zero
with fake node data:
Create a roles directory in chef-playground:
We’re going to create a .json file representing the role data. A basic role has a
name:
, description:
, and run_list
. The role can be used to encapsulate a long list of recipes into just one alias. Create file chef-playground/roles/webserver.json with the code in Example 14-1.
Then run
knife role from file
passing in the webserver.json file. Similar to data bags, knife role from file
assumes webserver.json is located in a subdirectory named roles, and not in the current directory.
Run
knife show role
as follows to display the details about the webserver
role:
You can reset a node’s run list with the
knife node set
command. Change the run list of the snowman
node to use the webserver
role you just created, using the following command on Linux/Mac OS X:
or, on Windows:
During the Chef run, the reference to the web server role will be expanded to the entries in the role’s run list:
- recipe[motd]
- recipe[users]
- recipe[apache]
Attributes and Roles
Create a .json file to represent a
base
role. This role will include references to the chef-client::delete_validation
and chef-client::default
recipes, both of which we recommended running on every node in Chapter 10. In this case, we’ll also set an attribute to tell the chef-client::default
recipe to set the init_style
to use runit
instead of the default. Create the file chef-playground/roles/base.json with the code provided in Example 14-2.
Then run
knife role from file
passing in the webserver.json file. Similar to data bags, knife role from file
assumes webserver.json is located in a subdirectory named roles, and not in the current directory:
When you run
knife role show base
as follows, notice that the role has attributes set as well as items in a run list:
As we discussed in Chapter 8, it is recommended that you restrict your use of attributes in roles to those of default priority, to make it easier to follow the composition of attributes when they come from multiple sources.
Because roles can have attributes, they have a place in the attribute hierarchy of precedence. Figure 14-2 is a modified version of the attribute precedence diagram we showed you in Figure 8-3 that includes roles. Roles can override attributes defined in recipes or attribute files, but they have a lower priority than the automatic attributes defined by
ohai
. Attribute settings in roles are intended to be global settings that override attributes set within cookbooks.Roles and Search
Roles can be search items as well. The following example shows how you can search for a recipe in the run list of a role. Note that you must use the
\
character to escape the [
and ]
characters in the query string:
Because roles introduce the idea that a list of recipes in a run list can be expanded, there are two ways to search for recipes in a node’s run list:
knife search node "recipe:<recipe_name>"
- When you do not want the search to include the expanded set of recipes within roles
knife search node "recipes:<recipe name>"
- When you do want the search to expand role references
Recall that earlier in the chapter we assigned the
snowman
node to have the webserver
role in its run list. Implicitly, when the role reference is expanded during a Chef run, the node will run the following recipes in the webserver
role’s run_list
:- recipe[motd]
- recipe[users]
- recipe[apache]
However, if you perform a
recipe:
search for, say, the recipe[apache::config]
, you might not get the results you intended:
Notice when the reference to
"role[webserver]"
is expanded, snowman
does have "recipe[apache]"
in its run list. But it doesn’t have "recipe[apache]"
directly in its run list if it is not expanded. So, snowman
does not show up in the search results because the recipe
search does not expand the node’s run list.NOTE
If you want to fully expand all the recipe references in a run list, perform a
recipes:
search instead. Then snowman
shows up in the search results:
There are similar search commands with expansion for roles as there are for recipes:
knife search node role:<role_name>
- When you do not want the search to include the expanded set of role references
knife search node "roles:<role_name>"
- When you do want the search to expand role references
Role Cookbook
Another issue related to the expansion of roles is that when a change gets made to a role, it gets reflected immediately across your entire infrastructure. Roles are not versioned in any way.
This usually has the most impact with run lists. Say, for example, one of your Chef infrastructure developers decided to remove the
recipe[apache]
role from the webserver
role we have been using in this chapter. We’ll say this developer made the change because she didn’t want web servers to default to using the Apache web server, but instead wanted to offer cookbook developers the choice of using the Apache or Nginx web servers for their apps:
If the
webserver
role were used widely across your infrastructure, this could have unintended consequences for cookbooks that assumed the old behavior where the recipe[apache]
was included in the role. Or conversely, if developers are careful not to make changes to the run lists of existing roles, it can result in a proliferation of differently named roles with similar functions. For example, that Chef developer might have instead chosen to create two new roles—webserver-apache
and webserver-nginx
—to make her intention to complement the existing webserver
role more clear.
Because cookbooks are versioned, a pattern of using a role cookbook in lieu of using the run list feature of roles is one technique many Chef developers use. They still use roles for common attributes, but the role run list is moved to a cookbook. A recipe can emulate a role run list easily through the use of the
include_recipe
command we introduced in Include_Recipe.
For example, in this case, we could create a
webserver
cookbook where the default recipe includes the apache
cookbook:
Nodes could still include the
webserver
role as a classification mechanism and for any shared attributes. It can still be handy to run this command to find all the web servers on your network:NOTE
In this scenario, the run list of the
webserver
role would be blank, and instead nodes would add the cookbook recipe[webserver]
to their run list. Cookbooks are versioned, and with environments, which we’ll introduce in the next chapter, you can ensure that a subset of nodes in your infrastructure is fixed to use specific versions of a cookbook. This is referred to as version pinning a node (or pinning a node).Summary
We covered roles in this chapter. Roles provide a way to classify patterns of use in your infrastructure. Roles can contain attributes and a list of recipes and other roles as a run list. This allows you to package all the settings for a node configuration into a single role reference.
In the next and final chapter of this book, we’ll cover environments, which provide a different code of abstraction—a way to map your organization’s app deployment workflow to a set of server configurations and cookbook versions.
No comments:
Post a Comment