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.
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 ping2. 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/python3YAML 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: deployHost ranges #
Avoid repeating lines: numeric and alphabetic ranges are supported.
[webservers]
web[01:20].example.com
[dbservers]
db-[a:c].example.com3. 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: 400Precedence 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é maximaleCommon 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 YAMLTargeting patterns #
Patterns let you target a subset of the inventory in ad-hoc commands, playbooks (hosts:) and with --limit:
| Pattern | Meaning |
|---|---|
all or * | All hosts |
webservers | A group |
webservers:dbservers | Union of two groups |
webservers:&prod | Intersection: in webservers AND prod |
webservers:!web2.lab | Exclusion |
web*.lab | Wildcard 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 botocoreExample: 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_addressansible-inventory -i inventories/aws/aws_ec2.yml --graph
ansible role_web -i inventories/aws/aws_ec2.yml -m pingScript 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ésGood practice: Cache dynamic plugins (cache: true,cache_timeout: 300) to speed up runs and avoid hitting the provider's API limits.
