Ansible Static vs Dynamic Inventory

The inventory is the foundation of every Ansible operation. Before Ansible can do anything useful, it must know what machines exist and how to reach them. The inventory file is how you provide that information. This lesson covers static inventory thoroughly and introduces dynamic inventory — the pattern used in production cloud environments where server lists change constantly.

What Is the Ansible Inventory

The Ansible inventory is a structured list of managed nodes (hosts). It can be a simple text file, a directory of files, a script that generates JSON, or an API-backed inventory plugin. In all cases, the inventory answers the same fundamental questions: which hosts exist, how are they grouped, and what variables apply to them.

Ansible uses the inventory to determine which hosts to target when you run a playbook or an ad-hoc command. The pattern ansible all targets every host in the inventory. The pattern ansible webservers targets every host in the webservers group. Understanding inventory structure is therefore central to controlling exactly what Ansible touches and what it leaves alone.

The Static Inventory File: INI Format

The simplest inventory is a plain text file in INI format. Here is a complete example:

[webservers]
web01 ansible_host=192.168.56.11
web02 ansible_host=192.168.56.12

[databases]
db01 ansible_host=192.168.56.13
db02 ansible_host=192.168.56.14

[loadbalancers]
lb01 ansible_host=192.168.56.10

[production:children]
webservers
databases
loadbalancers

[all:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/id_ed25519
ansible_python_interpreter=/usr/bin/python3

Breaking Down the INI Format

Host entries: Each line inside a group section defines one host. The hostname or alias on the left side is what Ansible uses internally. The ansible_host variable specifies the actual IP address or DNS name to connect to. These can be the same value or different — using an alias on the left (like web01) makes playbooks more readable than using IP addresses directly.

Groups: Square brackets define groups. Groups are arbitrary collections of hosts. A host can belong to multiple groups. Groups let you target subsets of your infrastructure — run a task on [webservers] without touching [databases].

Children groups: The [production:children] syntax creates a group of groups. production contains all hosts in webservers, databases, and loadbalancers. This is powerful for managing hierarchical environments (production, staging, development).

Group variables: The [all:vars] section defines variables that apply to every host. You can also create [groupname:vars] sections to apply variables to specific groups only.

The Static Inventory File: YAML Format

The same inventory can be expressed in YAML, which is more verbose but integrates naturally with the rest of the Ansible YAML ecosystem:

all:
  vars:
    ansible_user: ubuntu
    ansible_ssh_private_key_file: ~/.ssh/id_ed25519
  children:
    webservers:
      hosts:
        web01:
          ansible_host: 192.168.56.11
        web02:
          ansible_host: 192.168.56.12
    databases:
      hosts:
        db01:
          ansible_host: 192.168.56.13
    production:
      children:
        webservers:
        databases:

Both formats are valid. For small static inventories, INI is more concise. For complex hierarchies or when integrating inventory with other YAML tooling, YAML is preferred.

Inventory Ranges and Patterns

When you have many similarly named hosts, inventory ranges reduce repetition:

[webservers]
web[01:20] ansible_host=10.0.1.[1:20]

This single line expands to twenty hosts: web01 through web20 with IPs 10.0.1.1 through 10.0.1.20. Alphabetical ranges also work: db[a:d] expands to dba, dbb, dbc, dbd.

The Two Built-In Groups

Every Ansible inventory has two implicit groups that you never need to define:

  • all: Contains every host in the inventory, regardless of what explicit groups they belong to.
  • ungrouped: Contains hosts that have not been assigned to any explicit group.

You can always use ansible all -m ping to test all hosts, or ansible ungrouped -m ping to test only ungrouped hosts.

Directory-Based Inventory

As your infrastructure grows, a single inventory file becomes unwieldy. Ansible supports a directory as an inventory source. Create a directory called inventory/ and place multiple files inside it:

inventory/
  hosts.ini          # Main host definitions
  group_vars/
    webservers.yml   # Variables for webservers group
    databases.yml    # Variables for databases group
    all.yml          # Variables for all hosts
  host_vars/
    web01.yml        # Variables for web01 specifically

Ansible automatically reads all files in the inventory directory and merges them. The group_vars/ and host_vars/ subdirectories are a convention that Ansible recognises — more on these in the variables lesson.

Dynamic Inventory: Introduction

Static inventory works well when your infrastructure is stable and manually maintained. In cloud environments, however, servers are created and destroyed automatically — by autoscaling groups, by CI/CD pipelines, by infrastructure-as-code tools. A static file cannot keep up. Dynamic inventory solves this problem.

A dynamic inventory source is a script or plugin that queries an external data source (AWS, Azure, GCP, a CMDB, Terraform state) and returns the current list of hosts in a format Ansible understands. The dynamic inventory runs every time Ansible starts, so it always reflects the actual current state of your infrastructure.

Inventory Plugins vs Inventory Scripts

Ansible supports two mechanisms for dynamic inventory:

Inventory plugins are the modern approach (recommended). They are built-in or installable plugins that use YAML configuration files to query data sources. For example, the aws_ec2 plugin queries the AWS EC2 API and returns instances filtered by tags, regions, or instance state.

Inventory scripts are the legacy approach — executable scripts that Ansible calls and that return JSON. While still supported, scripts are more complex to write and maintain than plugins.

Using the aws_ec2 Inventory Plugin

To use the AWS EC2 inventory plugin, create a file named aws_ec2.yml (the _ec2 suffix activates the plugin automatically):

plugin: amazon.aws.aws_ec2
regions:
  - us-east-1
filters:
  instance-state-name: running
  tag:Environment: production
keyed_groups:
  - key: tags.Role
    prefix: role
compose:
  ansible_host: public_ip_address

This configuration queries AWS for all running EC2 instances tagged with Environment=production, groups them by their Role tag, and uses the public IP address for SSH connections. When you run ansible-inventory -i aws_ec2.yml --list, Ansible calls the AWS API and returns a live list of matching instances.

Testing Your Inventory

The ansible-inventory command is an essential tool for inspecting and debugging inventory:

ansible-inventory -i inventory.ini --list      # Show all hosts as JSON
ansible-inventory -i inventory.ini --graph     # Show group hierarchy as a tree
ansible-inventory -i inventory.ini --host web01  # Show variables for a specific host

Try This: Build a Two-Group Inventory

In your Ansible lab directory, create an inventory.ini file that places web01 and web02 in a [webservers] group and db01 in a [databases] group. Add a [all:vars] section with the appropriate connection variables. Then run:

ansible-inventory -i inventory.ini --graph

Confirm the output shows your two groups with the correct hosts. Then run ansible webservers -i inventory.ini -m ping to verify you can target a group specifically.

Summary

The Ansible inventory defines which hosts exist and how to connect to them. Static inventories use INI or YAML format and are ideal for stable environments. Dynamic inventories use plugins or scripts to query live data sources — essential in cloud environments where infrastructure changes constantly. Inventory directories with group_vars/ and host_vars/ subdirectories scale cleanly for complex environments. The ansible-inventory command is your primary tool for inspecting and debugging inventory configuration.

Leave a Comment