Ansible Inventory Patterns — Target Hosts and Groups
Introduction
Inventory patterns control which hosts Ansible targets. Instead of running against all hosts, you can target specific groups, use wildcards, combine groups with AND/OR/NOT logic, and use regex — all from the command line or in playbooks.
Basic Patterns
# All hosts
ansible all -m ping
# Specific group
ansible webservers -m ping
# Specific host
ansible db01 -m ping
# Multiple groups
ansible 'webservers:databases' -m ping
# Multiple hosts
ansible 'web01:web02:db01' -m ping
Wildcard Patterns
# All hosts starting with "web"
ansible 'web*' -m ping
# All .example.com hosts
ansible '*.example.com' -m ping
# Single character wildcard
ansible 'web0?' -m ping # web01, web02, ... web09
Group Operations
Union (OR) — hosts in either group
ansible 'webservers:databases' -m ping
Intersection (AND) — hosts in BOTH groups
ansible 'webservers:&production' -m ping
# Only hosts that are in webservers AND production
Exclusion (NOT) — hosts NOT in a group
ansible 'webservers:!staging' -m ping
# Webservers that are NOT in staging
Complex Patterns
# Production webservers, excluding hosts being patched
ansible 'webservers:&production:!patching' -m ping
# All hosts in either web or db, but only in production
ansible 'webservers:databases:&production' -m ping
Regex Patterns
# Regex (prefix with ~)
ansible '~web[0-9]+\.example\.com' -m ping
# Match numbered hosts
ansible '~^(web|db)[0-9]{2}$' -m ping
Numeric Ranges
# inventory.yml — range shorthand
all:
children:
webservers:
hosts:
web[01:50]: # web01 through web50
web[a:f]: # weba through webf
databases:
hosts:
db-[01:03]: # db-01, db-02, db-03
caches:
hosts:
192.168.1.[10:20]: # IP range
Playbook Targeting
# Target specific groups in playbooks
---
- name: Configure all web servers
hosts: webservers
tasks: [...]
- name: Configure production databases only
hosts: databases:&production
tasks: [...]
- name: All servers except staging
hosts: all:!staging
tasks: [...]
# Dynamic host targeting
- name: Target from variable
hosts: "{{ target_hosts | default('all') }}"
tasks: [...]
# Override at runtime
ansible-playbook site.yml -e "target_hosts=web01"
--limit Flag
Restrict targets at runtime without editing playbooks:
# Limit to one host
ansible-playbook site.yml --limit web01
# Limit to multiple hosts
ansible-playbook site.yml --limit 'web01,web02'
# Limit with pattern
ansible-playbook site.yml --limit 'web*'
# Limit to group intersection
ansible-playbook site.yml --limit 'webservers:&production'
# Exclude hosts
ansible-playbook site.yml --limit 'all:!db01'
# Retry failed hosts from last run
ansible-playbook site.yml --limit @site.retry
Inventory Listing
# Show all hosts in inventory
ansible-inventory --list
# Show hosts matching a pattern
ansible-inventory --host web01
# Graph view
ansible-inventory --graph
# Graph of specific group
ansible-inventory --graph webservers
Output:
@all:
|--@webservers:
| |--web01
| |--web02
|--@databases:
| |--db01
|--@ungrouped:
| |--monitoring01
Special Groups
| Group | Contains |
|---|---|
all | Every host in inventory |
ungrouped | Hosts not in any group (except all) |
localhost | The control machine |
# Target localhost explicitly
- hosts: localhost
connection: local
tasks:
- name: Run locally
ansible.builtin.debug:
msg: "Running on controller"
Nested Groups
# inventory.yml
all:
children:
production:
children:
prod_web:
hosts:
web01:
web02:
prod_db:
hosts:
db01:
staging:
children:
stag_web:
hosts:
stag-web01:
stag_db:
hosts:
stag-db01:
# Target all production (web + db)
ansible production -m ping
# Target only production web servers
ansible prod_web -m ping
Troubleshooting
| Issue | Solution |
|---|---|
| "No hosts matched" | Check pattern syntax and inventory: ansible-inventory --list |
| Wrong hosts selected | Use --list-hosts to preview: ansible-playbook site.yml --list-hosts |
| Host in wrong group | Check inventory structure: ansible-inventory --graph |
| Pattern not working | Quote patterns with special chars: ansible 'web*:&prod' -m ping |
Best Practices
- Use semantic group names —
webservers,databases, notgroup1 - Nest groups for environments —
production > prod_web,staging > stag_web - Use
--limitfor one-offs — don't edit inventory for temporary restrictions - Test with
--list-hosts— preview targeting before running - Avoid
allin production — be explicit about which hosts you target
Conclusion
Inventory patterns give you surgical precision in host targeting. Master union (:), intersection (&), and exclusion (!) operators, and you can target any combination of hosts without modifying your inventory or playbooks.