In this post we’ll talk about the concept of Inventory. When we installed
Ansible, an example inventory file was automatically placed at the location
/etc/ansible/hosts
for us. This is the default inventory file for Ansible.
Inventory file Link to heading
An inventory file consists of the information of various remote hosts that Ansible knows of. This file needs to be configured before we can start using Ansible to work with remote systems.
Hosts specified in the inventory file can either belong to a group or be ungrouped. A group is specified like below:
[groupname]
host1
host2
Ungrouped hosts should be specified before specifying any grouped hosts. You can either provide FQDN or IP address of the host. Make sure that the remote host(s) is/are reachable from the system you’re using to run Ansible commands through the FQDN or IP provided in inventory file.
Inventory file can be of different formats. The one you saw above and that we’re going to follow throughout the series is INI-like syntax (Ansible’s default). You can read about other formats in Ansible’s documentation.
Playing with remote systems Link to heading
For this post, we’re going to work with two remote systems. You can work this
out in various ways by creating two Linux virtual machines on your laptop or a
cloud provider. Two systems I’m going to work with have IP addresses
172.29.33.22
and 172.29.33.23
.
My inventory file (/etc/ansible/hosts
):
$ cat /etc/ansible/hosts
[servers]
172.29.33.22
172.29.33.23
Let’s start throwing some Ansible magic to them:
$ ansible -m ping all
172.29.33.23 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).\r\n",
"unreachable": true
}
172.29.33.22 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Permission denied
(publickey,gssapi-keyex,gssapi-with-mic).\r\n",
"unreachable": true
}
Oops, that was embarassing. Our first real Ansible command failed. 😢
Ah, our host system doesn’t have SSH access to the remote systems! We need to configure that first by enabling password-less SSH access from host system to both the remote systems. This can be done by creating ssh keys and copying them to remote system.
And then execute same command again:
$ ansible -m ping all
172.29.33.23 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.29.33.22 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Now that worked like a charm. One thing you need to ensure when configuring SSH
access is that, by default, Ansible will use same user to connect to remote
system via SSH as that on the host you’re executing Ansible from. That means,
if on the host system you’re logged in as user randomuser
, Ansible will try
to connect to remote system as the user randomuser
only.
But what is above command doing anyway? It’s using the module ping
on hosts
that belong to group all
. In response, since SSH connectivity is OK, it’s
getting a pong
response and the result is SUCCESS
.
But we didn’t configure all
group; we configured servers
group. By default,
Ansible has two groups: all
and ungrouped
. Hosts that are not a part of any
user defined group belong to the group ungrouped
and all
contains all hosts
in the inventory file.
Let’s do something else on this remote systems. Let’s do yum -y update
(assuming they are running CentOS/RHEL) on these systems:
$ ansible -m yum --args="name='*' state=latest" all
We use yum
module of Ansible and ask it to work on all installed packages
(name='*'
) such that their updated to their latest versions (state=latest
).
*
is a regular expresssion which indicates “all installed packages” to yum
.
Expect this command to take some time and print ugly output. It’s going to return only when the updates have been downloaded and installed on the remote system. Time it will take depends on: number of updates available, internet speed and type of disk (HDD vs. SSD).
Let’s try shell
module which executes the specified command on remote
systems:
$ ansible -m shell --args="date" all
172.29.33.22 | SUCCESS | rc=0 >>
Fri Sep 29 15:00:30 UTC 2017
172.29.33.23 | SUCCESS | rc=0 >>
Fri Sep 29 15:00:30 UTC 2017
$ ansible -m shell --args="df -h" all
172.29.33.22 | SUCCESS | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 10G 1.2G 8.9G 12% /
devtmpfs 900M 0 900M 0% /dev
tmpfs 920M 0 920M 0% /dev/shm
tmpfs 920M 17M 904M 2% /run
tmpfs 920M 0 920M 0% /sys/fs/cgroup
tmpfs 184M 0 184M 0% /run/user/0
172.29.33.23 | SUCCESS | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 10G 1.2G 8.9G 12% /
devtmpfs 900M 0 900M 0% /dev
tmpfs 920M 0 920M 0% /dev/shm
tmpfs 920M 17M 904M 2% /run
tmpfs 920M 0 920M 0% /sys/fs/cgroup
tmpfs 184M 0 184M 0% /run/user/0
tmpfs 184M 0 184M 0% /run/user/1000
rc=0
that we see in the first line of output for both systems indicates that
return code of executing the command was 0 (which means there were no errors.)
That’s it for this post Link to heading
There’s more that can be talked about inventory file: host variables, group variables, aliases, and more. But I’ll keep it for the next post to avoid making this too long. I personally feel bored of reading really long posts written across the Internet. 😉
As always, if you have any comments/feedback/suggestion, please let me know below! Until next time. 😉