Four reference files covering: - ansible.md — core commands, ansible.cfg, key settings - ansible-inventory.md — static/dynamic inventory, directory layout - ansible-variables.md — 22-level precedence, scoping, merge behavior - ansible-roles.md — structure, defaults vs vars, dependencies
215 lines
5.6 KiB
Markdown
215 lines
5.6 KiB
Markdown
# Ansible Inventory
|
|
|
|
> Define which hosts to manage, how to group them, and where to find them.
|
|
|
|
## Inventory Formats
|
|
|
|
### INI Format
|
|
|
|
```ini
|
|
# inventory/hosts.ini
|
|
|
|
[webservers]
|
|
web1.example.com
|
|
web2.example.com ansible_port=2222
|
|
|
|
[dbservers]
|
|
db1.example.com ansible_user=postgres
|
|
db[1:3].example.com # db1, db2, db3
|
|
|
|
[loadbalancers]
|
|
lb1.example.com
|
|
|
|
# Group of groups
|
|
[production:children]
|
|
webservers
|
|
dbservers
|
|
loadbalancers
|
|
|
|
# Group variables
|
|
[webservers:vars]
|
|
http_port=8080
|
|
app_env=production
|
|
|
|
[all:vars]
|
|
ansible_python_interpreter=/usr/bin/python3
|
|
```
|
|
|
|
### YAML Format (preferred)
|
|
|
|
```yaml
|
|
# inventory/hosts.yml
|
|
all:
|
|
vars:
|
|
ansible_python_interpreter: /usr/bin/python3
|
|
children:
|
|
production:
|
|
children:
|
|
webservers:
|
|
hosts:
|
|
web1.example.com:
|
|
web2.example.com:
|
|
ansible_port: 2222
|
|
vars:
|
|
http_port: 8080
|
|
dbservers:
|
|
hosts:
|
|
db1.example.com:
|
|
ansible_user: postgres
|
|
loadbalancers:
|
|
hosts:
|
|
lb1.example.com:
|
|
```
|
|
|
|
## Directory Layout
|
|
|
|
```
|
|
inventory/
|
|
├── hosts.yml # Host definitions
|
|
├── group_vars/
|
|
│ ├── all.yml # Vars for every host
|
|
│ ├── all/ # Dir form (merged, alphabetical)
|
|
│ │ ├── common.yml
|
|
│ │ └── vault.yml # Encrypted secrets
|
|
│ ├── webservers.yml # Vars for webservers group
|
|
│ └── production.yml # Vars for production parent group
|
|
└── host_vars/
|
|
├── web1.example.com.yml
|
|
└── db1.example.com/ # Dir form
|
|
├── main.yml
|
|
└── vault.yml
|
|
```
|
|
|
|
### Multiple Environments
|
|
|
|
```
|
|
inventories/
|
|
├── staging/
|
|
│ ├── hosts.yml
|
|
│ ├── group_vars/
|
|
│ └── host_vars/
|
|
└── production/
|
|
├── hosts.yml
|
|
├── group_vars/
|
|
└── host_vars/
|
|
```
|
|
|
|
```bash
|
|
ansible-playbook site.yml -i inventories/staging/
|
|
ansible-playbook site.yml -i inventories/production/
|
|
```
|
|
|
|
## Dynamic Inventories
|
|
|
|
### Script-Based (legacy)
|
|
|
|
A script that outputs JSON when called with `--list` or `--host <name>`.
|
|
|
|
```bash
|
|
#!/usr/bin/env python3
|
|
# inventory/dynamic.py — must be executable (chmod +x)
|
|
import json, sys
|
|
|
|
def get_inventory():
|
|
return {
|
|
"webservers": {
|
|
"hosts": ["web1.example.com", "web2.example.com"],
|
|
"vars": {"http_port": 8080}
|
|
},
|
|
"dbservers": {
|
|
"hosts": ["db1.example.com"]
|
|
},
|
|
"_meta": {
|
|
"hostvars": {
|
|
"web1.example.com": {"ansible_port": 22},
|
|
"db1.example.com": {"ansible_user": "postgres"}
|
|
}
|
|
}
|
|
}
|
|
|
|
if "--list" in sys.argv:
|
|
print(json.dumps(get_inventory(), indent=2))
|
|
elif "--host" in sys.argv:
|
|
host = sys.argv[sys.argv.index("--host") + 1]
|
|
hostvars = get_inventory().get("_meta", {}).get("hostvars", {})
|
|
print(json.dumps(hostvars.get(host, {})))
|
|
```
|
|
|
|
The `_meta.hostvars` key avoids per-host `--host` calls (efficiency).
|
|
|
|
### Plugin-Based (modern, preferred)
|
|
|
|
```yaml
|
|
# inventory/aws_ec2.yml — filename must end with the plugin suffix
|
|
plugin: amazon.aws.aws_ec2
|
|
regions:
|
|
- eu-west-1
|
|
keyed_groups:
|
|
- key: tags.Environment
|
|
prefix: env
|
|
- key: instance_type
|
|
prefix: type
|
|
filters:
|
|
tag:Managed: ansible
|
|
compose:
|
|
ansible_host: private_ip_address
|
|
```
|
|
|
|
Common inventory plugins:
|
|
|
|
| Plugin | Source | Suffix |
|
|
|-------------------------------|------------|-----------------|
|
|
| `amazon.aws.aws_ec2` | AWS EC2 | `aws_ec2.yml` |
|
|
| `azure.azcollection.azure_rm`| Azure | `azure_rm.yml` |
|
|
| `google.cloud.gcp_compute` | GCP | `gcp.yml` |
|
|
| `community.general.proxmox` | Proxmox | `proxmox.yml` |
|
|
| `community.docker.docker_containers` | Docker | `docker.yml` |
|
|
| `ansible.builtin.constructed` | Derived | `constructed.yml`|
|
|
|
|
```bash
|
|
# Verify dynamic inventory output
|
|
ansible-inventory -i inventory/aws_ec2.yml --graph
|
|
ansible-inventory -i inventory/aws_ec2.yml --list
|
|
```
|
|
|
|
### Constructed Inventory (compose groups from existing data)
|
|
|
|
```yaml
|
|
# inventory/constructed.yml
|
|
plugin: ansible.builtin.constructed
|
|
strict: false
|
|
groups:
|
|
is_debian: ansible_os_family == "Debian"
|
|
is_large: ansible_memtotal_mb > 8192
|
|
keyed_groups:
|
|
- key: ansible_distribution | lower
|
|
prefix: os
|
|
```
|
|
|
|
## Special Variables
|
|
|
|
| Variable | Purpose |
|
|
|-----------------------|------------------------------------|
|
|
| `ansible_host` | IP/hostname to connect to |
|
|
| `ansible_port` | SSH port (default: 22) |
|
|
| `ansible_user` | SSH user |
|
|
| `ansible_ssh_private_key_file` | SSH key path |
|
|
| `ansible_become` | Enable privilege escalation |
|
|
| `ansible_connection` | Connection type (`ssh`, `local`) |
|
|
| `ansible_python_interpreter` | Python path on target |
|
|
|
|
## Gotchas
|
|
|
|
- Script inventories must be executable (`chmod +x`) and have a shebang
|
|
- Plugin inventory files must end with the correct suffix or be listed in `enable_plugins`
|
|
- `group_vars/` directory must sit next to the inventory file, or at playbook level
|
|
- YAML inventory: hosts need trailing colon even with no vars (`web1.example.com:`)
|
|
- Groups named `all` and `ungrouped` are implicit — don't redefine them
|
|
- Directory form `group_vars/all/` merges files alphabetically — name carefully
|
|
|
|
## See Also
|
|
|
|
- `ansible` — core commands and ansible.cfg
|
|
- `ansible-variables` — variable precedence across inventory layers
|
|
- `ansible-roles` — role structure and organization
|