This article will make you understand what is Ansible inventory and how to connect to remote servers using Ansible inventory files.
Prerequisites
- One Ansible Control Node The Ansible control or mater node will be the machine we will use to connect to and control the Ansible hosts over SSH.
- One or more Linux client nodes
- SSH connection SSH connection should be enabled between Ansible control node and the remote client servers.
My Environment
Hostname | IP address | Operating System |
lco-ansible-master.example.com | 172.52.52.200 | CentOS Linux 7 (Core) |
lco-worker1.example.com | 172.52.52.201 | CentOS Linux 7 (Core) |
lco-worker2.example.com | 172.52.52.202 | CentOS Linux 7 (Core) |
What is Ansible Inventory?
Ansible is a configuration management tool which you use to setup and maintain the remote servers in an automated manner.
The list or the group of lists of such remote servers is called as Ansible inventory. This can be created in multiple formats as per your project requirements.
The default location of an Ansible inventory file is /etc/ansible/hosts
. The project specific inventory files also can be created in their respective locations on the system.
An example inventory file in INI format:
lco-ansible-master.example.com
[webservers]
lco-worker1.example.com
lco-worker1.example.com
[dbservers]
lco-worker3.example.com
lco-worker4.example.com
An example inventory file in YAML format:
all:
hosts:
lco-ansible-master.example.com:
children:
webservers:
hosts:
lco-worker1.example.com:
lco-worker1.example.com:
dbservers:
hosts:
lco-worker3.example.com:
lco-worker4.example.com:
Create you own Inventory file
Though Ansible comes up with a default inventory file located at /etc/ansible/hosts one can always create a custom inventory file as per their project requirements.
Note: During a playbook or ansible ad-hoc command execution you need to supply that custom inventory file with
-i
option as it wont be called by default.
Create a directory in you home folder:
[root@lco-ansible-master ~]# mkdir ansible
Create a file called myinventory
and put the following content in that:
[root@lco-ansible-master ansible]# cat myinventory
lco-ansible-master.example.com
lco-worker1.example.com
lco-worker2.example.com
This is the most basic form of an inventory file and it contains the list of all our nodes. Please note that hostnames and IP addresses are interchangeable.
Validate the inventory file:
[root@lco-ansible-master ansible]# ansible-inventory -i myinventory --list
{
"_meta": {
"hostvars": {}
},
"all": {
"children": [
"ungrouped"
]
},
"ungrouped": {
"hosts": [
"lco-ansible-master.example.com",
"lco-worker1.example.com",
"lco-worker2.example.com"
]
}
}
In the above output all
is used to refer to all servers from your inventory file and the ungrouped
group refers to servers which are not part of any group.
Run an ansible ad-hoc command to test inventory file functionality:
[root@lco-ansible-master ansible]# ansible -i myinventory -m ping all
lco-worker1.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
lco-worker2.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
lco-ansible-master.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
We have used ping module to check connectivity by pinging all the hosts part of our custom inventory file.
Ansible replies with a pong
if connection succeeded.
Hosts grouping in Inventory files
As I've already mentioned above that one can always group and subgroup the remote servers in an Ansible inventory file as per their project requirements.
For example look at the below file.
[root@lco-ansible-master ansible]# cat myinventory
[ansible-controller]
lco-ansible-master.example.com
[ansible-workers]
lco-worker1.example.com
lco-worker2.example.com
[web-server]
lco-worker1.example.com
[db-server]
lco-worker2.example.com
[all-systems:children]
ansible-controller
ansible-workers
Lets understand this file in detail.
- We have grouped our hosts here for example our worker nodes are part of
ansible-workers
group and our Ansible control machine is part ofansible-controller
group. - Servers are grouped on the basis of their purpose and qualities such as
web-server
anddb-server
- A host can be part of multiple groups.
- We have further break down the host groups into subgroups so that you can cover smaller and specific targets whenever needed.
Adding a Range of hosts in Ansible Inventory
Generally in IT organizations you will have a lot of hosts with a similar pattern in that case you can add them as a range instead adding them separately.
For example:
[root@lco-ansible-master ansible]# cat range_inventory
[ansible-workers]
lco-worker[1:2].example.com
Test the functionality:
[root@lco-ansible-master ansible]# ansible -m ping -i range_inventory all
lco-worker1.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
lco-worker2.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
It works!
You can also define alphabetic ranges as below:
[ansible-workers]
lco-worker-[a:f].example.com
Add aliases to your hosts in Ansible Inventory
Yes you can add easy to remember aliases to your hosts in an Ansible inventory file.
To use inventory aliases feature we need to add an variable called ansible_host
which will have remote host's IP or hostname as its value.
For example:
[root@lco-ansible-master ansible]# cat alises_inventory
master ansible_host=lco-ansible-master.example.com
worker1 ansible_host=lco-worker1.example.com
worker2 ansible_host=lco-worker2.example.com
Now run the ansible-inventory
command to analyze this file further.
[root@lco-ansible-master ansible]# ansible-inventory -i alises_inventory --list
{
"_meta": {
"hostvars": {
"master": {
"ansible_host": "lco-ansible-master.example.com"
},
"worker1": {
"ansible_host": "lco-worker1.example.com"
},
"worker2": {
"ansible_host": "lco-worker2.example.com"
}
}
},
"all": {
"children": [
"ungrouped"
]
},
"ungrouped": {
"hosts": [
"master",
"worker1",
"worker2"
]
}
}
You can observe by above output that hosts are now referenced by their aliases instead of their IP addresses or hostnames. It makes it easier to run ansible commands or playbooks against these individual servers.
Adding Host Variables to Ansible Inventory
We can add variables when we want to change the default behavior which relates to a host or a group in the Ansible inventory file.
To understand it in a simpler manner we can directly add variables to the hosts and groups in our main inventory file. Going forward in our Ansible series or articles we will dig deeper into Ansible variables concept where I will show you to store variables in separate host and group variable files.
Here is my updated inventory file which has host level variables defined.
[root@lco-ansible-master ansible]# cat variable_inventory
master ansible_host=lco-ansible-master.example.com ansible_user=ansible_user ansible_ssh_port=22
worker1 ansible_host=lco-worker1.example.com ansible_user=ansible_user ansible_ssh_port=22
worker2 ansible_host=lco-worker2.example.com ansible_user=ansible_user ansible_ssh_port=22
Here we have used three ansible variables. Above example shows defining remote user (ansible_user
here which has sudo access) and ssh port number when connecting to each of the nodes listed in this inventory file.
Variable can also be assigned at group level which will be applicable for all the hosts part of that group. For example:
[root@lco-ansible-master ansible]# cat group_variable_inventory
[ansible-controller]
master ansible_host=lco-ansible-master.example.com ansible_user=ansible_user ansible_ssh_port=22
[ansible-workers]
worker1 ansible_host=lco-worker1.example.com
worker2 ansible_host=lco-worker2.example.com
[ansible-workers:vars]
ansible_user=ansible_user
ansible_ssh_port=22
Verify the functionality of group variables by running the following command:
[root@lco-ansible-master ansible]# ansible-inventory -i group_variable_inventory --list
{
"_meta": {
"hostvars": {
"master": {
"ansible_host": "lco-ansible-master.example.com",
"ansible_ssh_port": 22,
"ansible_user": "ansible_user"
},
"worker1": {
"ansible_host": "lco-worker1.example.com",
"ansible_ssh_port": 22,
"ansible_user": "ansible_user"
},
"worker2": {
"ansible_host": "lco-worker2.example.com",
"ansible_ssh_port": 22,
"ansible_user": "ansible_user"
}
}
},
"all": {
"children": [
"ansible-controller",
"ansible-workers",
"ungrouped"
]
},
"ansible-controller": {
"hosts": [
"master"
]
},
"ansible-workers": {
"hosts": [
"worker1",
"worker2"
]
}
}
There are two default groups:
all
andungrouped
. Theall
group contains every host. Theungrouped
group contains all hosts that don’t have another group aside fromall
. Every host will always belong to at least 2 groups (all
andungrouped
orall
and some other group).
Pattern matching to manage hosts and groups
We can use patterns to target one or more hosts which are part of our inventory in order to run commands and playbooks against them. Pattern matching supports wildcards and regex.
Common patterns
This table lists common patterns for targeting inventory hosts and groups.
Description | Pattern(s) | Targets |
All hosts | all (or * ) | All the hosts part of your inventory file |
One host | host1 | A single host (here host1 ) |
Multiple hosts | host1:host2 (or host1,host2 ) | Both the hosts (host1 and host2 ) |
One group | ansible-workers | A single group (here ansible-workers ) |
Multiple groups | webservers:dbservers | all hosts in webservers plus all hosts in dbservers |
Excluding groups | webservers:!milpitas | all hosts in webservers except those in milpitas |
Intersection of groups | webservers:&dev | any hosts in webservers that are also in dev |
Few examples:
[root@lco-ansible-master ansible]# ansible webservers:&dev -m ping -i inventory
[root@lco-ansible-master ansible]# ansible webservers:!milpitas -m ping -i inventory
That's all.
You should be now having a fair enough idea about Ansible inventories. You now know how we can organize hosts into groups and subgroups, set up inventory variables (at host and group levels), and use patterns in order to connect different groups of servers while running commands and playbooks.
Hope you like the article. Stay Tuned and don't forget to subscribe for more.
Thank you. Happy learning!