# Inventory Configuration and Management

> Chapter 3 of the Courseiva REDHAT-RHCE curriculum — https://courseiva.com/learn/redhat-rhce/inventory-configuration-and-management

**Official objective:** 2.2 — Create and manage static and dynamic inventories

## Introduction

The EX294 exam objective 2.2 tests your ability to manage where Ansible looks for the servers it controls. Understanding inventory configuration and management is critical because it directly affects which servers get your automation instructions — get it wrong and you update the wrong machine or skip a critical patch.

## The Property Manager's Guest List Analogy

A property manager is responsible for a large apartment complex with dozens of flats. They need to know exactly which flats are occupied, who lives in each one, and how to contact them for maintenance or emergencies. They keep a master tenant list, but they also rely on a digital system that updates automatically when new tenants move in or out.

In IT, managing servers across a network is like managing that apartment complex. The property manager's static tenant list is a static inventory: a manually maintained file that lists every server (flat), its IP address (flat number), and the operating system (tenant name). This works fine for a small, unchanging building, but breaks down when tenants move in and out frequently.

The digital system that updates automatically is the dynamic inventory. It queries a central database or cloud provider's API (like a building management system) to fetch the current list of servers. This ensures that when a new server is spun up (a new tenant moves in), it is automatically included in future maintenance runs without the property manager having to edit a spreadsheet. The property manager now focuses on running the building, not updating paperwork. This is exactly how Ansible knows which servers to manage: it reads an inventory file (static) or pulls from a source like Amazon EC2 or Azure (dynamic) to build a reliable, up-to-date guest list.

## Core explanation

Ansible is an automation tool that lets you configure servers, deploy applications, and manage infrastructure without logging into each machine individually. To do this, Ansible needs to know which servers to talk to. This list of servers is called an inventory. You can think of it as a phone book for your network.

There are two main types of inventory: static and dynamic. A static inventory is a file you write by hand, usually in INI or YAML format. For example, you might create a file called 'hosts' that lists three web servers:

- [webservers]
- web1.example.com
- web2.example.com
- web3.example.com

This file explicitly tells Ansible, 'these are the machines to run your tasks on'. Static inventories are simple and predictable. They work well for small environments where servers don't change often. However, in a modern cloud environment, servers can be created and destroyed automatically in seconds. If you use a static inventory, you would have to manually update that file every time a server is added or removed. This is tedious and error-prone.

Dynamic inventories solve this problem. A dynamic inventory is a script or program that fetches the current list of servers from an external source, like cloud provider APIs (Amazon Web Services, Google Cloud, Microsoft Azure) or a configuration management database (CMDB). When Ansible runs, it executes this script instead of reading a static file. The script returns the inventory in JSON format, which Ansible parses. Because the script queries the live state, the inventory is always up to date without manual editing.

For the EX294 exam, you need to know how to configure both types. For static inventories, you must understand the INI format (simple key-value sections) and the YAML format (more structured, used in playbooks). You also need to know how to use groups and nested groups. A group is a collection of servers that share a role, like 'webservers' or 'databases'. Nested groups let you combine smaller groups into larger ones, such as grouping all production servers into a 'production' group.

For dynamic inventories, you need to know that Ansible ships with built-in inventory scripts for major cloud providers. For example, the 'aws_ec2' plugin can dynamically list all your EC2 instances based on tags or regions. To use it, you configure a YAML file that tells Ansible which plugin to use and how to filter the results. The exam also tests the concept of 'inventory plugins' which are the modern replacement for older scripts. You need to remember that inventory plugins are configured in the 'ansible.cfg' file under the '[inventory]' section.

Inventories live in a specific location by default: /etc/ansible/hosts. But you can specify a different path using the '-i' flag when running a playbook. You can also use multiple inventory sources at once by passing a comma-separated list or a directory containing multiple inventory files. This is useful if you have some servers in a static file and some in a dynamic source.

Variables can be assigned to hosts or groups directly in the inventory file. For example, you might set 'ansible_user=admin' for a group. But the exam emphasises that variables are typically separated into their own files for clarity (using 'host_vars' and 'group_vars' directories). The inventory itself should only contain the list of hosts and group memberships.

Finally, the inventory can also include 'range notation' to define many hosts in a single line, like 'www[1:100].example.com', which expands to 100 hosts. This is a shorthand for static inventories that beginners often miss. Understanding this notation can save you hours of typing in the exam.

## Real-world context

Imagine you are the sole IT administrator for a company called 'QuickCart', an online retailer that runs its own infrastructure. You have 20 physical servers in a data center running a mix of Linux and Windows. Most of these servers rarely change, so you keep a static inventory file called 'inventory' that lists every server by hostname and groups them into 'web', 'database', and 'monitoring'. Every morning, you run an Ansible playbook that applies security patches to all servers. The static inventory works perfectly because the list stays the same.

But the company grows, and the CTO decides to move to the cloud to handle traffic spikes during holiday sales. You now use Amazon Web Services (AWS) to spin up 50 temporary 'web' instances whenever traffic increases. Managing these with a static inventory becomes impossible. You would need to update the file each time an instance launches or terminates.

You decide to implement a dynamic inventory. You create an 'inventory_aws.yml' file that uses the 'amazon.aws.aws_ec2' plugin. You configure it to fetch all EC2 instances with the tag 'Environment: production'. Now, when you run your patch playbook, Ansible automatically queries AWS and gets the current list of running instances. If an instance is terminated, it disappears from the inventory automatically. If a new instance is launched with the right tag, it appears.

You also use groups dynamically by filtering on tags. For example, instances with tag 'Role: web' are grouped under 'webservers'. This allows you to target patching only to web servers without hardcoding hostnames.

One day, a junior administrator accidentally deletes the inventory_aws.yml file. Without it, your playbook fails because it cannot find any hosts. You recover by storing the inventory configuration in a version control system (Git). This ensures you can always restore it.

In a real production environment, you might also use multiple inventory sources together: a static file for your permanent data center servers, and a dynamic source for cloud instances. You would place all inventory files in a directory and point Ansible to that directory with the '-i' option. This combination gives you the reliability of static lists for fixed assets and the flexibility of dynamic updates for cloud assets.

When troubleshooting, you run 'ansible-inventory --list' to see exactly what hosts Ansible sees. This command prints the compiled inventory as JSON. If a cloud instance is missing, you check the tags or the plugin configuration. This diagnostic step is common in real-world operations and the exam expects you to know it.

## Exam focus

The EX294 exam tests inventory configuration and management in several direct ways. Firstly, you will be asked to create a static inventory file in INI or YAML format. The exam will give you a list of hostnames and ask you to place them into specific groups. The trap here is forgetting that group names are case-sensitive and must use correct syntax. For example, square brackets around group names in INI format, or a YAML list with the correct indentation.

- Common trap: mixing INI and YAML syntax in the same file. The exam file will be purely one format.
- Common trap: forgetting to add the hostname on a new line after the group header.
- Common trap: using spaces instead of tabs (YAML uses spaces, but incorrect number breaks parsing).

Secondly, you must understand dynamic inventories. The exam specifies that you should be able to 'create and manage both static and dynamic inventories'. For dynamic, you need to know how to configure an inventory plugin. The most likely one tested is the 'aws_ec2' plugin. You will need to know the structure of the configuration file: a YAML file with 'plugin', 'regions', 'filters', and 'keyed_groups'. You do not need to memorise every option, but you must recognise the correct format of a plugin configuration.

- Key concept: inventory plugins are configured in YAML files, not scripts.
- Key concept: dynamic inventory sources must be executable or configured as a plugin.
- Key concept: you can verify the generated inventory with 'ansible-inventory --graph' or '--list'.

Thirdly, the exam tests your ability to use inventory variables. You must know the difference between host variables and group variables. Host variables are set directly on the host line (e.g., 'host1 ansible_user=admin'). Group variables are set in special files named 'group_vars/<group_name>' or directly in the inventory file under the '[group_name:vars]' section. The trap is that group variables override host variables only if they are defined at a higher precedence level, but the exam keeps it simple: group variables apply to all hosts in that group.

- Trap: setting a variable in the wrong section. For example, putting a group variable under a host line.
- Trap: thinking variable files must be named exactly after the group (e.g., 'group_vars/webservers.yml').

Fourthly, you must understand host patterns. The exam will test whether you can target a subset of hosts using patterns like 'webservers', '!database', or '*.example.com'. These patterns are used in playbooks to limit which hosts run a play.

Finally, the exam expects you to know the default inventory location (/etc/ansible/hosts) and how to override it with the '-i' flag. They may ask you to run a playbook with a specific inventory file, and if you do not specify '-i', it will fail or use an empty inventory.

- Trap: assuming the current directory's 'hosts' file is used automatically. It is not.
- Trap: not realising that you can specify a directory containing multiple inventory files.

## Step by step

1. **Define Your Server List** — Identify all the servers you want Ansible to manage. For a static inventory, write them in a text file in INI or YAML format. For a dynamic inventory, decide which cloud provider or database holds the authoritative list.
2. **Organise Servers into Groups** — Group servers by role (e.g., webservers, databases) or environment (e.g., production, testing). In a static file, use square brackets or YAML sections. In a dynamic plugin, use tags or filters to automatically assign hosts to groups.
3. **Add Variables (Optional)** — Assign variables like 'ansible_user' or custom application settings to hosts or groups. You can do this inline in the inventory file or in dedicated 'host_vars' and 'group_vars' directories for cleaner separation.
4. **Test the Inventory** — Run 'ansible-inventory --list -i <your_inventory>' to see the compiled list of hosts and variables. This verifies that your syntax is correct and that all expected servers appear. Use '--graph' for a visual tree of groups.
5. **Use the Inventory in a Playbook** — Write a simple playbook that targets a specific group, e.g., 'hosts: webservers'. Run it with 'ansible-playbook -i <inventory> playbook.yml'. This confirms that Ansible can connect to the servers and execute tasks.
6. **Maintain and Update** — For static inventories, update the file whenever servers are added or removed. For dynamic inventories, ensure the plugin configuration remains accurate and that the external source is reachable. Store inventory files in version control.

## Comparisons

### Static Inventory vs Dynamic Inventory

**Static Inventory:**
- Manually written and maintained file in INI or YAML format.
- Best for small, fixed environments where servers rarely change.
- Requires manual edits when servers are added or removed.

**Dynamic Inventory:**
- Uses a script or plugin to fetch server list automatically from an external source.
- Ideal for cloud environments where servers are created and destroyed frequently.
- Updates dynamically without manual intervention.

### INI Format vs YAML Format

**INI Format:**
- Uses square brackets to define groups: [webservers].
- Hosts listed one per line under the group header.
- Group variables defined with [group:vars] section.

**YAML Format:**
- Uses YAML dictionaries and lists: webservers:
  hosts:
    host1:.
- More structured and can be used in playbooks and inventory files.
- Group variables defined as a 'vars' key under the group.

### Inventory Plugins vs Custom Inventory Scripts

**Inventory Plugins:**
- Pre-built by Ansible for cloud providers like AWS, Azure, GCP.
- Configured via YAML files with specific plugin options.
- Modern and recommended approach for dynamic inventories.

**Custom Inventory Scripts:**
- Custom scripts written in any language (Python, Shell) that return JSON.
- Older method, requires writing and maintaining code.
- Deprecated in favour of plugins, but still supported.

## Diagram

_Flowchart showing how Ansible uses either a static file or dynamic plugins to determine which hosts to run playbooks on._

```mermaid
flowchart TD
    A[Ansible Control Node] --> B[Static Inventory File]
    A --> C[Dynamic Inventory Plugin]
    B --> D[INI/YAML File with Hosts & Groups]
    C --> E[AWS EC2 Plugin]
    C --> F[Azure Plugin]
    C --> G[Custom Script]
    D --> H[Playbook execution on listed hosts]
    E --> H
    F --> H
    G --> H
```

## Common misconceptions

- **Misconception:** Static inventories are useless and should never be used in a production environment. **Reality:** Static inventories are perfectly valid for environments where servers do not change frequently, such as on-premise data centers with fixed hardware. Many organisations use a mix of static and dynamic. (Beginners often hear about cloud automation and assume static is outdated. They do not realise many companies still run physical servers.)
- **Misconception:** Dynamic inventories require writing a shell script from scratch. **Reality:** Ansible provides built-in inventory plugins for major cloud providers and other sources. You only need to configure them in a YAML file, not write custom code. (This misconception comes from older documentation that described writing custom dynamic inventory scripts. The modern approach is plugin-based and much simpler.)
- **Misconception:** The inventory file can only contain hostnames and no variables. **Reality:** You can define host and group variables directly in the inventory file using the ':vars' sections or by assigning them inline after the hostname. (New users often separate variables into separate files and assume the inventory file is just a list of hosts, missing the inline variable feature.)
- **Misconception:** If you define a host in a dynamic inventory and also in a static inventory, Ansible will crash. **Reality:** Ansible merges hosts from all inventory sources. If the same host appears in multiple sources, it will combine the variables from both, with a precedence order. (Users fear conflict and assume duplication causes errors. In reality, Ansible handles this gracefully, which is a feature for hybrid environments.)
- **Misconception:** The '-i' flag is optional because Ansible always uses /etc/ansible/hosts as default. **Reality:** The '-i' flag is only optional if the default file exists and you want to use it. If you have no default or want a different file, you must specify '-i'. It is best practice to always use '-i' in playbooks to avoid ambiguity. (Many beginners rely on the default and then wonder why their playbook runs on no hosts when they move to a new machine.)

## Key takeaways

- An inventory is simply a list of the servers Ansible will manage, and it can be either a static file you write or a dynamic source that updates automatically.
- Static inventories are written in INI or YAML format, with groups defined by square brackets or YAML keys, and they are best for fixed, unchanging server lists.
- Dynamic inventories use plugins or scripts to fetch the current server list from cloud providers or databases, eliminating manual updates in volatile environments.
- Inventory plugins are configured in YAML files and are the modern, preferred method over custom scripts for dynamic inventories in Ansible.
- You can combine multiple inventory sources by pointing Ansible to a directory containing both static files and dynamic plugin configurations.
- Use 'ansible-inventory --list' or 'ansible-inventory --graph' to inspect exactly which hosts Ansible sees and debug missing hosts.
- Variables can be assigned to hosts or groups directly in the inventory file, but best practice is to keep them in separate 'host_vars' and 'group_vars' directories.
- The '-i' flag is used to specify the inventory file or directory; it is not optional and should always be explicitly provided in scripts and playbooks.

## FAQ

**What is the difference between static and dynamic inventory in Ansible?**

A static inventory is a file you manually write and maintain with a list of servers. A dynamic inventory is a script or plugin that automatically fetches the server list from an external source like AWS, so it updates without manual edits.

**How do I specify a custom inventory file when running an Ansible playbook?**

Use the '-i' flag followed by the path to your inventory file or directory. For example: ansible-playbook -i /path/to/inventory playbook.yml.

**Can I use both static and dynamic inventories at the same time?**

Yes. You can point the '-i' flag to a directory that contains both a static hosts file and a dynamic inventory plugin configuration. Ansible will merge the hosts from all sources.

**What format should my static inventory file be in?**

Static inventories can be in INI format (with groups in square brackets) or YAML format (with keys and lists). The exam tests both, so you should know the syntax for each.

**How do I debug an inventory that seems to be missing hosts?**

Run 'ansible-inventory --list -i <inventory>' to see the full compiled JSON. Check that your plugin filters or group definitions are correct. Also verify that the external source (e.g., cloud provider) is reachable.

**What is the default location Ansible looks for the inventory file?**

The default location is /etc/ansible/hosts. However, it is considered bad practice to rely on this; always use the '-i' flag to be explicit.

## Check your understanding

1. **What command would you run to see a visual tree of your inventory groups and hosts?**

   Answer: Run 'ansible-inventory --graph' to display a tree view of groups and their member hosts.

2. **In a static inventory INI file, what section header would you use to define a group called 'databases'?**

   Answer: Use '[databases]' (square brackets) to define the group.

3. **How do you specify a custom inventory directory when running a playbook?**

   Answer: Use the flag '-i my_inventory_directory' when calling ansible-playbook.

4. **What is the default file path that Ansible searches for an inventory if no '-i' is provided?**

   Answer: The default is /etc/ansible/hosts.

5. **Name one built-in inventory plugin that Ansible provides for cloud providers.**

   Answer: The 'aws_ec2' plugin for Amazon Web Services (or 'azure_rm' for Azure, 'gcp_compute' for GCP).

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/redhat-rhce/inventory-configuration-and-management
