How-to's and Support

Ansible Inventory: A Guide to Creating and Using One

7 min read

Ansible is an agentless system automation tool. You can use it to manage system configuration, perform maintenance tasks, and deploy software on managed nodes from a central control node. The only software you need on the managed nodes is OpenSSH, and there are even some workarounds for that.

Ansible uses an inventory file to identify control nodes. This file lists the nodes, organizes them into groups, and may also provide additional information about them.

In this post, you'll see how to create an inventory, use it to target nodes, create groups, and associate variables with them.

Let's get started!

What's an Ansible Inventory?

When you configure Ansible to operate on one or more hosts, it identifies them with an inventory file. So you can target nodes using patterns instead of building lists or limiting yourself to hostnames or IP addresses. You can use hostnames and addresses if you want, but an Ansible Inventory gives you powerful tools for managing your systems.

Probably the most widely used feature is Ansible's system groups. You can group your target hosts by any arbitrary group name you want. You can even put hosts in more than one group.

Here's an example inventory file with three groups:

[webservers]
www1.example.com
www2.example.com

[dbservers]
db1.example.com
db2.example.com

[linux]
www1.example.com
www2.example.com
db1.example.com
db2.example.com

[windows]
exchange.example.com

This inventory has two hosts in the webservers group, two more in the dbservers group, and then all four of those servers are also part of the linux group. Meanwhile, a single host makes up the windows group. These groupings give you quite a bit of flexibility, depending on the tasks you need to perform.

The inventory file above is written in INI. Ansible supports both YAML and INI formats for inventory files. We'll stick with INI for this tutorial. 

The default location for your Ansible inventory is /etc/ansible/hosts. But, as you'll see below, you can override that location on the command line. You can also point Ansible at your hosts’ files, which is the third format Ansible supports for inventory files.

Starting an Ansible Inventory

First, you'll need to install Ansible on your system. It will also help to have access to one or more managed nodes.

Even though we've already seen an inventory file, let's start one from scratch. Start in an empty directory:

$ mkdir ansible
$ cd ansible

You'll need root access to edit the default inventory file in /etc/ansible/hosts. But we're going to start with a file in an alternative location.

Copy the default inventory file into your working directory:

$ cp /etc/ansible/hosts sample_inventory

This gives you an empty inventory file with documentation included in the form of comments. 

Adding Hosts

Here are a few of the first lines. The file is too large to include here.

$ less sample_inventory

# This is the default ansible 'hosts' file.
#

To add hosts, list them in the file. The comments show that you can use names or IP addresses.

I have three hosts to add. I'll replace the sample nodes listed in the file with mine. You can follow along with systems you can have access to. Remember—your control node can be a managed node, too.

# Ex 1: Ungrouped hosts, specify before any group headers:

ix
genosha
zaku

Now I can target my three Linux servers by name. 

This ad hoc command executes uptime in a shell on the targeted host:

$ ansible -i sample_inventory ix -m shell -a uptime
ix | CHANGED | rc=0 >>
 02:44:22 up 26 days,  1:29,  2 users,  load average: 0.06, 0.02, 0.00

Let's break this command down:

  • -i sample_inventory tells ansible to use the sample_inventory file in the working directory as the inventory for this command.

  • ix is the target host.

  • -m shell tells Ansible to use the shell module, which will run a shell command on the target host.

  • -a uptime tells the shell modules to run the uptime command.

Adding Groups

This works well for a small home network, but if you're administering an enterprise network, you need to be able to target hosts by type, role, or both. Let's add some groups.

Group definitions go after the ungrouped hosts. Let's create three groups using the hosts I already defined. 

[group1]
ix
genosha

[group2]
genosha
zaku

[group3]
zaku
ix

Let's execute uptime on a group of hosts:

$ ansible -i sample_inventory group1 -m shell -a uptime
ix | CHANGED | rc=0 >>
 20:07:34 up 26 days, 18:52,  2 users,  load average: 0.08, 0.02, 0.01
genosha | CHANGED | rc=0 >>
15:07  up 9 days, 23:04, 5 users, load averages: 1.32 1.50 1.71
 
$ ansible -i sample_inventory group2 -m shell -a uptime
zaku | CHANGED | rc=0 >>
 15:09:18 up 102 days, 16 min,  2 users,  load average: 0.10, 0.10, 0.09
genosha | CHANGED | rc=0 >>
15:09  up 9 days, 23:06, 5 users, load averages: 1.10 1.33 1.62

The host named genosha belongs to both groups, so Ansible targeted it in both ad hoc commands. The output of its uptime command is different from the other two hosts because it's a MacBook. 

Creating Variables

I'm managing two Linux and one macOS node. While macOS is Unix-like, it's different from Linux in important ways. We can use Ansible variables to abstract away many of these differences.

Variables are key/value pairs that you associate with hosts or groups. Once defined, you can refer to them in your ad hoc commands or playbooks.

Here's a simple example:

ix home=/home
genosha home=/Users
zaku home=/home

On Linux systems, home directories are located in /home by default. On macOS system, these directories reside in /Users. The home variable in this inventory defines the correct location for each host.

Here's the variable in action:

$ ansible -i sample_inventory group1 -m shell -a "ls {{home}}"
ix | CHANGED | rc=0 >>
egoebelbecker
homebridge
lost+found
plex
genosha | CHANGED | rc=0 >>
Shared
egoebelbecker

Ansible uses Jinja2 to process variables and other dynamic expressions. So, when you use a variable in an ad hoc command, place it between two sets of curly braces like this: {{}}. This command listed the comments of the home variable on each host.

You can add variables to groups, too. Let's simplify the inventory a bit:

[mac]
genosha

[mac:vars]
home=/Users

[linux]
ix
zaku

[linux:vars]
home=/home

If you list a node in a group, you don't have to list it in the ungrouped hosts at the top. So we can remove the node names from the top.

Instead, we have a mac and a linux group now. 

We also have two new headings: mac:vars and linux:vars. These headings define the home variables. 

$ ansible -i sample_inventory linux -m shell -a "ls {{home}}"
zaku | CHANGED | rc=0 >>
egoebelbecker
ix | CHANGED | rc=0 >>
egoebelbecker
homebridge
lost+found
plex
$ ansible -i sample_inventory genosha -m shell -a "ls {{home}}"
genosha | CHANGED | rc=0 >>
Shared
egoebelbecker

The variables still work, whether we target the nodes as a group or individually.

Changing Inventories

So far, we've been passing the name of an inventory file on the command line in our example commands. This is a powerful feature since it allows you to create inventory files for projects that require special host groups or variables that you don't want to mix with other projects. For example, the CloudBees Continuous Delivery/Release Orchestration EC-Ansible plugin supports custom inventories so that you can create custom variables and deployment playbooks.

But the default inventory is often good enough for most purposes. Let's give it a try.

Let's back up the default inventory and copy our sample inventory into its place:

$ sudo cp /etc/ansible/hosts /etc/ansible/hosts.backup
$ sudo cp sample_inventory /etc/ansible/hosts

Now, we can omit the -i command-line option:

$ ansible group1 -m shell -a "ls {{home}}"
ix | CHANGED | rc=0 >>
egoebelbecker
homebridge
lost+found
plex
genosha | CHANGED | rc=0 >>
Shared
egoebelbecker

Take Inventory

We’ve seen what an Ansible inventory is. We covered how to create one, how to organize your managed nodes into groups, and how to use variables to store and use node properties. Then we wrapped up with the difference between a project and a default inventory.

Take control of your IT automation with Ansible and its powerful inventory capabilities now, and take a look at the CloudBees CD/RO EC-Ansible plugin to see how you can automate your software delivery pipelines.

This post was written by Eric Goebelbecker. Eric has worked in the financial markets in New York City for 25 years, developing infrastructure for market data and financial information exchange (FIX) protocol networks. He loves to talk about what makes teams effective (or not so effective!).

Stay up-to-date with the latest insights

Sign up today for the CloudBees newsletter and get our latest and greatest how-to’s and developer insights, product updates and company news!