RousselTMLEARNING

Automation

Ansible: the inventory (static, dynamic, groups and variables)

Understand and master the Ansible inventory: INI and YAML files, groups, host and group variables, patterns, dynamic inventories and the ansible-inventory command.

1. The role of the inventory #

Telling Ansible which machines to act on.

What is an inventory? #

The inventory is the list of machines (hosts) Ansible manages, organized into groups. A playbook never targets an IP address directly: it targets a group or a pattern defined in the inventory. This is what lets you replay the same automation on development, acceptance or production simply by changing the inventory.

Hierarchy of an Ansible inventory: all, groups and hosts
Every host belongs to the implicit all group.

Ansible provides two implicit groups: all (all hosts) and ungrouped (hosts that belong to no other group).

Where is the default inventory? #

By default Ansible reads /etc/ansible/hosts. In practice, you version the inventory with the project and point to it with -i or in ansible.cfg:

# Dans le dépôt du projet
cat ansible.cfg
[defaults]
inventory = ./inventories/lab/hosts.ini
host_key_checking = False

# Ou en ligne de commande
ansible all -i inventories/prod/hosts.ini -m ping

2. Writing a static inventory #

The INI and YAML formats.

INI format #

The INI format is the most concise. Groups are in square brackets, [group:children] declares a group of groups and [group:vars] common variables.

# inventories/lab/hosts.ini
bastion.lab ansible_host=192.168.56.5

[webservers]
web1.lab ansible_host=192.168.56.11
web2.lab ansible_host=192.168.56.12

[dbservers]
db1.lab ansible_host=192.168.56.21 ansible_port=2222

[prod:children]
webservers
dbservers

[prod:vars]
ansible_user=deploy
ansible_python_interpreter=/usr/bin/python3

YAML format #

The YAML format is more verbose but highly structured, ideal when variables become numerous:

# inventories/lab/hosts.yml
all:
  children:
    webservers:
      hosts:
        web1.lab: { ansible_host: 192.168.56.11 }
        web2.lab: { ansible_host: 192.168.56.12 }
    dbservers:
      hosts:
        db1.lab:
          ansible_host: 192.168.56.21
          ansible_port: 2222
  vars:
    ansible_user: deploy

Host ranges #

Avoid repeating lines: numeric and alphabetic ranges are supported.

[webservers]
web[01:20].example.com

[dbservers]
db-[a:c].example.com

3. Variables: group_vars and host_vars #

Separating data from code.

Recommended layout #

Rather than overloading the inventory file, put variables in dedicated directories. Ansible loads them automatically:

projet/
├── ansible.cfg
├── inventories/
│   └── lab/
│       ├── hosts.ini
│       ├── group_vars/
│       │   ├── all.yml          # valable pour tous les hôtes
│       │   ├── webservers.yml   # valable pour le groupe webservers
│       │   └── dbservers/
│       │       ├── main.yml
│       │       └── vault.yml    # secrets chiffrés (voir Ansible Vault)
│       └── host_vars/
│           └── db1.lab.yml      # valable pour un seul hôte
└── site.yml
# inventories/lab/group_vars/webservers.yml
http_port: 8080
nginx_worker_processes: auto

# inventories/lab/host_vars/db1.lab.yml
postgres_max_connections: 400

Precedence order #

When the same variable is defined in several places, the most specific wins: host_vars > group_vars of a child group > group_vars of a parent group > group_vars/all. Variables passed with -e (extra vars) override everything.

ansible-inventory -i inventories/lab/hosts.ini --host db1.lab
ansible webservers -i inventories/lab/hosts.ini -m debug -a "var=http_port"
ansible-playbook site.yml -e http_port=9090      # priorité maximale
Common mistake: Redefining the same variable in all.yml and in a playbook without knowing the precedence order produces baffling behavior. Keep a single source of truth per variable.

4. Inspecting and targeting the inventory #

ansible-inventory and patterns.

The ansible-inventory command #

Before running anything, check how Ansible interprets your inventory:

ansible-inventory -i inventories/lab/hosts.ini --list          # JSON complet avec variables
ansible-inventory -i inventories/lab/hosts.ini --graph         # vue arborescente
ansible-inventory -i inventories/lab/hosts.ini --host web1.lab # variables d'un hôte
ansible-inventory -i inventories/lab/hosts.ini --list --yaml   # export YAML
Output of ansible-inventory --graph
Example output for the inventory above.

Targeting patterns #

Patterns let you target a subset of the inventory in ad-hoc commands, playbooks (hosts:) and with --limit:

PatternMeaning
all or *All hosts
webserversA group
webservers:dbserversUnion of two groups
webservers:&prodIntersection: in webservers AND prod
webservers:!web2.labExclusion
web*.labWildcard on the name
~web[0-9]+Regular expression
ansible 'webservers:&prod' -m ping
ansible-playbook site.yml --limit 'webservers:!web2.lab'
ansible-playbook site.yml --limit @retry_hosts.txt     # relancer sur les hôtes en échec
ansible all -i inventories/lab/hosts.ini --list-hosts   # voir qui sera ciblé

5. Dynamic inventories #

When machines change all the time.

Principle #

In the cloud or on Kubernetes, machines appear and disappear: maintaining a file by hand is impossible. An inventory plugin queries a source of truth (AWS, Azure, GCP, VMware, NetBox...) and generates the inventory on the fly, groups and variables included.

# Lister les plugins disponibles
ansible-doc -t inventory -l | head

# Installer la collection AWS puis son SDK
ansible-galaxy collection install amazon.aws
pip install boto3 botocore

Example: EC2 by tags #

# inventories/aws/aws_ec2.yml  (le nom doit finir par aws_ec2.yml)
plugin: amazon.aws.aws_ec2
regions: [eu-west-3]
filters:
  tag:Environment: prod
  instance-state-name: running
keyed_groups:
  - key: tags.Role
    prefix: role
hostnames:
  - private-ip-address
compose:
  ansible_host: private_ip_address
ansible-inventory -i inventories/aws/aws_ec2.yml --graph
ansible role_web -i inventories/aws/aws_ec2.yml -m ping

Script or mixed inventory #

An executable that returns JSON (--list and --host) also works. You can point to a directory containing static files, plugins and scripts: Ansible merges them all.

ansible-playbook site.yml -i inventories/lab/     # un dossier = tous les inventaires fusionnés
Good practice: Cache dynamic plugins (cache: true, cache_timeout: 300) to speed up runs and avoid hitting the provider's API limits.

Related articles

Ansible: ad-hoc commands

Run immediate actions on a fleet of servers with ansible: the ping, command, shell, copy, apt, service and se…

Ansible: structuring your code with roles

Create, organize and reuse Ansible roles: directory layout, defaults, tasks, handlers, templates, dependencie…

Ansible: generating dynamic files with Jinja2 and facts

Create dynamic configuration files: Jinja2 templates, variables, facts, filters, loops, conditions, lookups a…

Keep learning

Support us

♥ SUPPORT US

Support RousselTM Learning

Courses, articles, labs and certificates stay free with no intrusive ads. A voluntary contribution, of any amount you choose, pays for hosting, lab environments and new content.

Contribute with PayPal Any amount · card or PayPal accountLearn more
QR code PayPal
Or scan this QR code with your phone

Thank you, every contribution counts!