Ansible Inventory
The inventory is used to define which hosts are managed by Ansible. The inventory supports the following formats:
- • IP addresses
- • Hostnames
- • Ranges (
<span>server[b:c]</span>
) - • Host groups (
<span>webserver</span>
) - • Subgroups (
<span>lnmp:children</span>
)
Inventory
172.25.250.10
[webserver]
server[b:c]
[mysql]
172.25.250.1[3:4]
[lnmp:children]
webserver
mysql
- • Directly defining a hostname or address, currently
<span>172.25.250.10</span>
does not belong to any group.
172.25.250.10
- • Defining a host group, the
<span>webserver</span>
group includes<span>serverb</span>
to<span>serverc</span>
[webserver]
server[b:c]
- • Groups can be nested
[lnmp:children]
webserver
mysql
- • Using ranges to match hosts
server[b:c]
172.25.250.1[3:4]
Selecting Hosts and Host Groups
Matching All Hosts
ansible all --list-hosts
hosts (5):
172.25.250.10
serverb
serverc
172.25.250.13
172.25.250.14
Matching Specific Hosts or Host Groups
ansible serverc --list-hosts
hosts (1):
serverc
ansible lnmp --list-hosts
hosts (4):
serverb
serverc
172.25.250.13
172.25.250.14
Matching Multiple Hosts and Host Groups
ansible serverb,serverc --list-hosts
hosts (2):
serverb
serverc
ansible webserver,mysql --list-hosts
hosts (4):
serverb
serverc
172.25.250.13
172.25.250.14
Matching Ungrouped Hosts
ansible ungrouped --list-hosts
hosts (1):
172.25.250.10
Using Wildcards to Select Hosts
ansible server* --list-hosts
hosts (2):
serverb
serverc
ansible *25.* --list-hosts
hosts (3):
172.25.250.10
172.25.250.13
172.25.250.14
Wildcard Logical Combinations
- •
<span>&</span>
: Intersection - •
<span>!</span>
: Negation - •
<span>,</span>
: Union
# Match all hosts starting with server, excluding serverc
ansible 'server*,!serverc' --list-hosts
hosts (1):
serverb
# Match hosts common to both groups webserver and lnmp
ansible 'webserver,&lnmp' --list-hosts
hosts (2):
serverb
serverc
# Exclude serverc in the previous example
ansible 'webserver,&lnmp,!serverc' --list-hosts
hosts (1):
serverb
Using Regular Expressions for Matching
# '~' followed by a regex, the example below matches hosts starting with se
ansible '~^se' --list-hosts
hosts (2):
serverb
serverc
Matching Hosts with Limit
ansible all --limit serverb,172.25.250.13 --list-hosts
hosts (2):
serverb
172.25.250.13
# Using file matching
cat <<EOF > ip.txt
serverb
serverc
172.25.250.14
EOF
ansible all --limit @/home/student/ansible/ip.txt --list-hosts
hosts (3):
serverb
serverc
172.25.250.14
Special Host: localhost
Finally, let’s talk about a special host <span>localhost</span>
, which is a special host that can be used without being declared in the inventory.
<span>localhost</span>
refers to the local machine, and when not declared in the inventory, Ansible will connect using <span>local</span>
, which is equivalent to executing commands locally. Below is the difference between it and SSH connection:
Item | local | ssh |
Execution Location | Executed locally on the control node | Executed remotely via ssh |
Network Usage | No | Yes |
Permission Control | Current user | Can specify remote user |
Common Use Cases | Control node configuration, local debugging | Production environments, managing multiple hosts |
You can explicitly specify <span>localhost</span>
in the inventory to set the connection method to <span>ssh</span>
.
<span>local</span>
and <span>ssh</span>
connections have one major difference: <span>local</span>
will ignore the <span>remote_user</span>
option, as shown in the following example:
# Configuration file
[test@awx-1 ansible]$ cat ansible.cfg
[defaults]
inventory = ./inventory
fork = 20
ask_pass = False
remote_user = remote-manager
host_key_checking = False
ansible_python_interpreter = /usr/bin/python3.9
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
# Current user
[test@awx-1 ansible]$ id
uid=1000(test) gid=1000(test) groups=1000(test) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# View inventory, current localhost is commented out
[test@awx-1 ansible]$ cat inventory
#localhost ansible_ssh_password=redhat
# Test
[test@awx-1 ansible]$ ansible localhost -b -m command -a 'id'
localhost | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# It can be seen that it executed successfully
# Remove the comment from the inventory
[test@awx-1 ansible]$ cat inventory
localhost ansible_ssh_password=redhat
# Test again
[test@awx-1 ansible]$ ansible localhost -b -m command -a 'id'
localhost | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: remote-manager@localhost: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password,keyboard-interactive).",
"unreachable": true
}
# It can be seen that an error occurred because test cannot directly ssh as remote-manager user
It can be seen that the <span>local</span>
method ignores the <span>remote_user</span>
option, while <span>ssh</span>
does not.