Chapter 3. Setting Up an Ansible Managed Environment

This chapter covers the following subjects:

Understanding Projects

Configuring Static Inventory

Working with Dynamic Inventory

Managing Settings in ansible.cfg

The following RHCE exam objectives are covered in this chapter:

• Understand core components of Ansible

• Inventories

• Configuration files

• Install and configure an Ansible control node

• Create a static host inventory file

• Create a configuration file

• Create and use static inventories to define groups of hosts

“Do I Know This Already?” Quiz

The “Do I Know This Already?” quiz allows you to assess whether you should read this entire chapter thoroughly or jump to the “Exam Preparation Tasks” section. If you are in doubt about your answers to these questions or your own assessment of your knowledge of the topics, read the entire chapter. Table 3-1 lists the major headings in this chapter and their corresponding “Do I Know This Already?” quiz questions. You can find the answers in Appendix A, “Answers to the ’Do I Know This Already?’ Quizzes and Review Questions.

Table 3-1 “Do I Know This Already?” Section-to-Question Mapping

Image

1. Which of the following is not a valid method of using inventory?

a. If nothing is specified, Ansible looks for a file with the name inventory in the current directory.

b. Specify the name of the inventory file in ansible.cfg.

c. Specify the name of the inventory file as a command-line argument using the -i option.

d. Use the default inventory in /etc/ansible/hosts.

2. Which of the following symptoms do you see if no inventory file was specified?

a. Ansible generates an error message.

b. Ansible tells you that no inventory hosts could be found.

c. Ansible tries to run commands against localhost.

d. The Ansible command doesn’t complain but just doesn’t give anything as a result.

3. What is the name of the default Ansible inventory?

a. /etc/hosts

b. /etc/inventory

c. /etc/ansible/inventory

d. /etc/ansible/hosts

4. Which of the following is not a requirement that must be met by a dynamic inventory script?

a. It must be executable.

b. It must be written in Python.

c. It must respect the arguments --list and --host.

d. It must produce its output in JSON format.

5. Which statement about using multiple inventory files is true?

a. Ansible doesn’t support using multiple inventory files.

b. Multiple dynamic inventory files are supported; using multiple static inventory files is not.

c. When the name of a directory is specified as the inventory that has to be used, all files in that directory are used as inventory.

d. When multiple inventory files are used, each file has to be specified separately as a command-line option using the -i option.

6. Which of the following should not be used in inventory files?

a. Variables that apply to specific hosts

b. Host groups

c. IP addresses

d. Nested host groups

7. Which statement about privilege escalation is not true?

a. Privilege escalation can be defined in the ansible.cfg file.

b. Privilege escalation can be defined in individual playbooks.

c. Privilege escalation parameters can be specified on the command line.

d. Privilege escalation can be specified in the inventory file.

8. Where should the inventory file be stored in a big corporation where Ansible is used to manage hundreds of servers and appliances?

a. In /etc/ansible/hosts

b. In DNS

c. In the project directory

d. In Ansible Tower

9. Which statement about the remote_user setting is not true?

a. The remote_user typically is defined in the [defaults] section in ansible.cfg.

b. The remote_user setting refers to the user account that is used to run all tasks on managed hosts after privilege escalation.

c. The remote_user setting can also be applied on the command line or in a playbook.

d. Without a remote_user setting, Ansible won’t work correctly.

10. Which parameter can be used to disable the requirement to check validity of SSH host keys?

a. host_key_checking

b. ssh_host_keys

c. verify_host_keys

d. verify_ssh_keys

Foundation Topics

In the preceding chapter you read about the Linux requirements of an Ansible managed environment. At this point your hosts should all meet these requirements, so now it’s time to focus on the Ansible part of the configuration. In this chapter you learn about two essential components: the inventory and the ansible.cfg configuration file. But first, we need to spend some time talking about Ansible projects.

Understanding Projects

In some cases, a small IT staff may use Ansible to manage just a few servers. In other cases, Ansible is used to manage multiple IT projects in a worldwide organization. These different use cases ask for a different approach in the way Ansible is used. If it is used at a small scale, there’s nothing wrong with having just one Ansible configuration take care of all needs in IT. If, however, Ansible is used to manage large-scale environments, it’s a good idea to work with different project directories.

A project directory is a self-contained environment that includes everything needed to work in a specific project. The playbooks are found within the project directory. These are the Ansible scripts, written in YAML, that enforce the desired configuration on managed hosts. Apart from these playbooks, other components may also be found in the project directory, such as variable files, additional files used to include tasks, and the inventory and the ansible.cfg configuration files.

Having all of these within the same project directory makes it easy to delegate tasks in an Ansible managed environment. If you’re working on just a few servers, this approach might not make too much sense, but once your Ansible environment is taking care of many managed assets, you will recognize the convenience of working with project directories.

Using project directories is good to keep together items that belong together. While using the project directory, you may put the ansible.cfg file and the inventory file in the specific project directory. This approach makes sense if each project has its own specific configuration files. Alternatively, the configuration files may be in the ansible user home directory. This approach makes sense if different user accounts exist for managing Ansible, where each user has his own configuration. You can also choose to manage all Ansible configuration at a system level, where inventory and ansible.cfg are the same for your entire system. Table 3-2 summarizes the different options.

Table 3-2 Options for Storing Configuration Files

Image

Configuring Static Inventory

The purpose of the Ansible inventory is to identify hosts that Ansible has to manage. Inventory also can be used for other purposes:

Image

• List hosts

• Group hosts

• Specify host variables

Listing Hosts

In its simplest form, the inventory file is just a list of hosts that Ansible uses to identify the hosts that matter in this project. If you prefer a project-oriented approach, you can have different inventories in different projects because in one project you may be addressing different hosts than in other projects. In the project approach, each project directory should have its own inventory file.

In smaller Ansible managed environments, the file /etc/ansible/hosts can be used as the inventory file. If this file exists, it’s not necessary to have project inventory files as well.


Exam tip

If you have doubts about the format of lines in the inventory file on the exam, look at /etc/ansible/hosts. It contains nice examples of how hosts can be specified in the inventory file.


An Ansible inventory can be just a list of host names or IP addresses. You don’t need to specify name-resolving information as well because DNS or the /etc/hosts file should be taking care of name resolving. Apart from just listing the names or IP addresses of hosts, the inventory file also can work with ranges. For instance, the line server[1:6].example.com would address all servers between server1 and server6.

Inventory Host Groups

When you’re working with many hosts, using host groups is convenient. Host groups can be defined in inventory, and a host may be a member of multiple host groups. You can also work with nested groups, where a group is a member of another group. The example in Listing 3-1 shows what host group definitions should look like.

Listing 3-1 Inventory File with Host Groups

ansible1
ansible2
192.168.4.1
192.168.4.2

[web]
web1
web2

[db]
db1
db2

[servers:children]
web
db

In Listing 3-1, you first see the hosts ansible1 and ansible2, which are not members of any specific group. Also, you see two IP addresses. You are allowed (though it is not recommended) to include IP addresses as well. Next, a group web and a group db are defined. In the example you also see the group servers that address all hosts in the group [web] as well as the [db] group.

In general, there are three different approaches for using groups. Functional groups are used to be able to address specific groups of hosts, like web servers and file servers. Regional host groups are convenient when working with a region-oriented infrastructure, and staging host groups can be defined to address different hosts according to the staging phase your current environment is in. Table 3-3 gives a summary of a host groups approach.

Table 3-3 Host Group Usage Overview

Image

Apart from the defined host groups, there are also implicit host groups, as shown in Table 3-4. These group names don’t have to be defined because they are implicitly there. These are the groups all and ungrouped. Apart from that, there is the implicit host localhost, which doesn’t have to be addressed in inventory.

Image

Table 3-4 Implicit Hosts and Host Groups

Image

Using Inventory in Commands

The inventory file is an essential component of your Ansible configuration because it identifies hosts and allows you to put hosts together in groups. To view the current inventory, you can use the ansible -i inventory <pattern> --list-hosts command. Notice the use of the -i inventory option, which is mandatory to indicate that a specific inventory must be used.

Another command to show inventory information is ansible-inventory:

• Use ansible-inventory -i inventory --list to list inventory hosts in JSON output format.

• Use ansible-inventory -i inventory --graph to display a graphical overview of hosts in the inventory.

If you’re using Ansible commands and don’t want to use the default inventory in /etc/ansible/hosts, you must use the -i option to point to the inventory file you want to use. This may be an absolute pathname or a relative pathname, so in the example ansible -i inventory --list-hosts, a file with the name inventory in the local directory is addressed. As an alternative, you may also set the default inventory to use in the ansible.cfg file, which is discussed later.

In Exercise 3-1 you learn how to work with host groups.

Exercise 3-1 Working with Host Groups

1. Log in as the ansible user and use the command mkdir base to create a project directory with the name base. Use cd base to get into this directory.

2. In this directory, create a file with the name inventory and give it the following contents:

ansible1
ansible2

[web]
web1
web2

[db]
db1
db2

[servers:children]
db
web

3. Type ansible all --list-hosts. You get a failure message because the ansible command does not find any inventory containing hosts.

4. Type ansible -i inventory all --list-hosts. Now you see a list of all hosts in inventory.

5. Type ansible -i inventory ungrouped --list-hosts. This command shows all hosts that are not a member of any group.

6. Use ansible-inventory -i inventory --graph. This command shows a hierarchical overview of inventory, including information about which host is a member of which group.

7. Use ansible-inventory -i inventory --list. This command shows the contents of the inventory represented in JSON format.

Specifying Host Variables

In older versions of Ansible, the inventory file was also used to define variables for specific hosts. This behavior is deprecated and should not be used anymore. You might, however, see inventory files that still contain variable definitions, and for that reason, this section describes how it works.

Listing 3-2 shows an inventory file that contains host variables.

Listing 3-2 Sample Inventory with Variables

[lamp]
ansible1.example.com

[file]
ansible2.example.com

[win]
windows.example.com

[win:vars]
ansible_user=ansible
ansible_password=@nsible123
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore

As you can see, the variables are set at a group level, using [groupname:vars]. You shouldn’t use this approach anymore, though. Variables in current versions of Ansible should be set using the host_vars and group_vars directories, as explained in Chapter 6, “Working with Variables and Facts.”

Working with Dynamic Inventory

In small environments it is common to manually define the Ansible inventory. If you’re using Ansible in big and dynamic environments, like public cloud environments, you should use dynamic inventory instead. In dynamic inventory a script is used to discover inventory hosts in a specific environment. Community-provided inventory scripts are available on GitHub (Google for the exact link of the environment for which you want to find a dynamic inventory script); alternatively, it’s not difficult to write your own dynamic inventory scripts.

Working with Community-Provided Dynamic Inventory Scripts

As mentioned, many community-provided inventory scripts are available. The scripts often come with an .ini file that is used to provide specific information on how to connect to the specific resource. To use the community-provided inventory scripts, you have to make sure that they are made executable, using the Linux chmod +x command. After making the scripts executable, you must provide required parameters, either by putting them in the .ini file that comes with the inventory script or by providing them as command-line parameters to the ansible command. You can obtain good inventory script-specific information on how to do this from the Ansible documentation at https://docs.ansible.com.

Writing Your Own Inventory Scripts

Writing your own inventory script is not too difficult, particularly if you have programming experience. Inventory scripts have a few requirements: they must contain a --list option as well as a --host option. Also, the output must be produced in JSON format.

In Listing 3-3 you can see an example of the dynamic inventory script pascal.py written in Python. This script generates an inventory that is based on the local Linux host resolving mechanisms in use. This means that it uses the contents of /etc/hosts as the inventory.

Listing 3-3 Dynamic Inventory Script Example

#!/usr/bin/python
""" Dynamic Inventory Script Example """

from subprocess import Popen, PIPE
import sys

try:
    import json
except ImportError:
    import simplejson as json

RESULT = {}
RESULT[’all’] = {}

PIPE = Popen([’getent’, ’hosts’], stdout=PIPE, universal_newlines=True)

RESULT[’all’][’hosts’] = []

for line in PIPE.stdout.readlines():
    s = line.split()
    RESULT[’all’][’hosts’] = RESULT[’all’][’hosts’]+s

RESULT[’all’][’vars’] = {}

if len(sys.argv) == 2 and sys.argv[1] == ’--list’:
    print(json.dumps(RESULT))

elif len(sys.argv) == 3 and sys.argv[1] == ’--host’:
    print(json.dumps({}))

else:
    print("Requires an argument, please use --list or --host <host>")

Note

You can download the script in Listing 3-3 from the GitHub repository; it is named listing33.py. Use git clone https://github.com/sandervanvugt/rhce8-book to get access to this sample file and many others.


To use the sample inventory script in Listing 3-3, you can run it directly by using the command ./listing33.py --list. Alternatively, you can use it as an argument to the ansible command. You learn how to do this in Exercise 3-2.

Exercise 3-2 Using a Dynamic Inventory Script

1. Type cd ~ to get back to the current user home directory, and type sudo yum install -y git to install the git software.

2. Type git clone https://github.com/sandervanvugt/rhce8-book to clone this book’s GitHub repository.

3. Type cd rhce8-book to go into the rhce8-book directory.

4. Type alternatives --set python /usr/bin/python3. This command creates a symbolic link with the name python that points to the python3 binary and thus guarantees that all scripts that are configured to use /usr/bin/python are also working.

5. Type ./listing33.py --list to show the result of the Python script when it is started by itself. You then see the unformatted command output.

6. Install json_pp by typing sudo yum install perl-JSON-PP.

7. Type ./listing33.py --list | json_pp to show output that is formatted in a readable way.

8. Type ansible -i listing33.py all --list-hosts to use the script to show all hosts.

Using Multiple Inventory Files

In large environments, it may be useful to access multiple inventory files. You can easily do that by putting all inventory files in a directory and specifying the name of the directory as the inventory file to be used. If it’s a static inventory file, you just have to copy it to the inventory directory. If it’s a dynamic inventory file, you also need to do that, and in addition you have to make sure that the execute permission is set on the inventory file.

Managing Settings in ansible.cfg

When you’re working with Ansible, multiple settings are required to reach out to manage hosts. Table 3-5 lists the most important of these settings. To provide the settings in a persistent way, the ansible.cfg configuration file is used. Specific ansible.cfg files can be created in the current project directory; a generic ansible.cfg file is available as /etc/ansible/ansible.cfg. Listing 3-4 shows an example of an ansible.cfg file.

Image


Exam tip

The /etc/ansible/ansible.cfg file is well annotated, and that makes it an excellent resource on the RHCE exam. If you have any doubt about specific parameters to be used, check the /etc/ansible/ansible.cfg file for examples!


Listing 3-4 Sample ansible.cfg File

[defaults]
remote_user = ansible
host_key_checking = false
inventory = inventory

[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False

As seen in Listing 3-4, the ansible.cfg file is laid out in .ini file format, with different sections. The section header is between square brackets, and parameters are specified in a key = value format. The common sections in ansible.cfg are [defaults] and [privilege escalation]. In the default section, generic information is provided. The privilege_escalation section defines how the ansible user should require administrative privileges to connect to the managed hosts.

Image

Table 3-5 ansible.cfg Common Settings

Image

Notice that all of the settings specified in the ansible.cfg file can also be specified in Ansible playbooks. If there are conflicting settings, the most specific setting always wins. So settings defined in a playbook override the settings in the ansible.cfg file. In Exercise 3-3 you practice creating an ansible.cfg as well as an inventory file in the current user home directory.

Exercise 3-3 Creating an ansible.cfg File

1. Type cd ~ to ensure that you are in the current user home directory.

2. Type vim ansible.cfg to open a new inventory file that is to be created.

3. Create the defaults section by including the following lines:

[defaults]
remote_user = ansible
host_key_checking = false
inventory = inventory

4. Configure the privilege escalation section by including the following lines:

[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False

5. Copy the inventory file that you created earlier by using cp base/inventory.

6. Type ansible-inventory --list. This shows you all hosts currently in inventory, without the need to use the -i inventory option to specify the name of the inventory file.

Summary

In this chapter you learned about two essential components in every Ansible project: the inventory file and the ansible.cfg file. You read how to create static as well as dynamic inventory files and how to define default settings that Ansible should be working with in the ansible.cfg file. In the next chapter you’ll learn how to use all of these settings when working with Ansible ad hoc commands and modules.

Exam Preparation Tasks

As mentioned in the section “How to Use This Book” in the Introduction, you have a couple of choices for exam preparation: the exercises here, Chapter 16, “Final Preparation,” and the exam simulation questions on the companion website.

Review All Key Topics

Review the most important topics in this chapter, noted with the Key Topic icon in the outer margin of the page. Table 3-6 lists a reference to these key topics and the page numbers on which each is found.

Image

Table 3-6 Key Topics for Chapter 3

Image

Memory Tables

Print a copy of Appendix D, “Memory Tables” (found on the companion website), or at least the section for this chapter, and complete the tables and lists from memory. Appendix E, “Memory Tables Answer Key,” also on the companion website, includes completed tables and lists to check your work.

Define Key Terms

Define the following key terms from this chapter, and check your answers in the glossary:

ansible.cfg

inventory

playbook

project

YAML

Review Questions

1. What syntax do you use to define a group named all in inventory?

2. Which name should you use for an inventory file that is created in your local project directory?

3. What is the name of the default inventory file?

4. How do you define a group with the name linux that has as members the groups web and file?

5. Which two command-line options should be respected by any dynamic inventory script?

6. How do you refer to hosts web001 up to web010 from one line in inventory?

7. What is the default name of the group that hosts are automatically a member of if they don’t belong to any specific group?

8. Which command should you use to display a graphical overview of inventory hosts, including the groups they are a member of?

9. What is wrong with the following command?

ansible -i inventory --list-hosts

10. Which parameter in ansible.cfg should you use to specify the mechanism to escalate permissions?

End-of-Chapter Lab

In the preceding chapter you set up the basic Linux environment to work with Ansible. Now it’s time to create a project directory.

Lab 3-1

Configure a project directory that meets the following requirements:

• All hosts are entered in a static inventory file.

• An Ansible configuration file is created to take care of the following:

• The project inventory file is used as the default inventory.

• Privilege escalation is configured such that the ansible user is used, and sudo is used to run tasks that require privilege escalation.

• After setting up this environment, use the appropriate command to list all hosts in inventory.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset