Hosts, Groups and Connection Details
Scenario: A playbook targetswebserversand reportsskipping: no hosts matched. The inventory does contain the web servers - under a group calledwebserver, singular.
New words, in plain English
- Inventory file - a text file listing hosts and the groups they belong to. INI or YAML format.
- Group - a named set of hosts, written in INI as
[groupname]. - Host variable - a setting attached to one host - for example which port to SSH to.
- Pattern - the expression a play uses to choose hosts: a group name, a host name, or a combination.
The inventory is the map of your estate. In its simplest form it is a list of names under group headings. Each host can carry connection details as inline variables - the most important being ansible_host (the address to actually connect to), ansible_port, ansible_user, and ansible_ssh_private_key_file.
Ansible always provides two implicit groups: all (every host in the inventory) and ungrouped (hosts that belong to no other group). A host may belong to as many groups as you like, and group_names inside a play tells you which ones the current host is in.
Groups can contain other groups using [parent:children]. This is how estates are usually modelled: a production group whose children are webservers, dbservers and loadbalancers. Variables set on the parent apply to every host underneath it, which is exactly what you want for things like the environment name.
Analogy: An inventory is a company directory. Individual entries are people; groups are departments; [parent:children] is the org chart that says Engineering contains Backend and Frontend. Sending an email to 'Engineering' reaches everyone below it without you listing names.
A worked example
[webservers]
web01 ansible_host=127.0.0.1 ansible_port=2201 ansible_user=web01
web02 ansible_host=127.0.0.1 ansible_port=2202 ansible_user=web02
[dbservers]
dbprod ansible_host=127.0.0.1 ansible_port=2203 ansible_user=dbprod
[loadbalancers]
lb01 ansible_host=127.0.0.1 ansible_port=2204 ansible_user=lb01
# A parent group made of other groups.
[production:children]
webservers
dbservers
loadbalancers
# Variables that apply to every host in the inventory.
[all:vars]
ansible_ssh_private_key_file=/opt/lab-ssh/id_ed25519
ansible_python_interpreter=/usr/bin/python3
Two habits prevent most inventory pain. First, verify rather than assume: ansible-inventory --graph draws the tree Ansible actually built, and ansible <pattern> --list-hosts shows exactly who a play would touch. Running that before a risky change costs three seconds and has prevented a lot of very expensive minutes.
Second, resist putting real configuration values inline in the inventory file. Connection details belong there; application settings do not. The moment you have more than a handful, they belong in group_vars/ and host_vars/ where they are readable and reviewable.
Warning: no hosts matched is not an error - it is a successful run against zero machines, and it exits 0. Automation that only checks the exit code will report a completely no-op deploy as a success.
Goal: Put this to work in the ansible-inventory-groups lab. Open/labs/ansible, pickansible-inventory-groups, and fix the real broken project - Ansible really does SSH into four managed hosts and converge them.