Ansible is a simple open-source agentless IT automation tool used for configuration management and automatic deployment of applications. With ansible, a simple YAML code is written once for the installation and deployed multiple times.
Ansible uses an inventory to work against multiple managed nodes or “hosts” in your infrastructure at the same time. After you’ve defined your inventory, you can use patterns to select which hosts or groups you want Ansible to run against.
A good introduction about Ansible was done in our previous article on “Introduction to Ansible Automation on Linux – Understanding Ansible“
In this article, our focus will be on “Ansible Inventory Management”.
Ansible Inventory Management
The Ansible inventory file is a list of hosts or a group of hosts on which commands, modules, and tasks in playbook operate. The default location for the host inventory file is /etc/ansible/hosts
. The ansible commands use a different host inventory file when they are used with the --inventory PATHNAME
option, simplified as -i PATHNAME.
By passing multiple inventory parameters from the command line or configuring ANSIBLE_INVENTORY, you can target multiple inventory sources (directories, dynamic inventory scripts, or files supported by inventory plugins) at the same time. You can also pull inventory from dynamic or cloud sources, as well as different formats such as YAML, ini, and so on.
Modules are the programs that perform the actual work of the tasks of a play. Core modules come bundled with Ansible. There are more than 300 core modules to choose from.
The goal of a play is to map a group of hosts to well-defined roles. These are called tasks. A task is a call to an ansible module.
Individual hosts or user-defined groups of hosts can be listed in the inventory file.
Ansible playbooks are written using the YAML language. YAML files have a .yml extension. YAML files optionally begin with a three dash
(—). Immediately after the three dashes, the line starts with a single dash (-). Next, we define hosts or group of hosts. You then define whether you will be a root user or not by using the keyword become. Then immediately after you define the tasks and finally define your modules.
How to define Inventory in Ansible
Before we embark on defining an Inventory, we must ensure the following requirements are met.
- One Ansible control node.
- Two or more Ansible hosts.
Step 1 : Install Ansible in your system
In the previous article, we touched on Ansible installation.
Installation of Ansible from OS package manager
The quickest and easiest method is installing Ansible using package manager:
### Ubuntu / Debian ###
sudo apt update
sudo apt install ansible
### CentOS 8 / Rocky Linux 8 / AlmaLinux 8 ###
sudo yum install epel-release
sudo yum install ansible
### Arch / Manjaro ###
sudo pacman -S ansible
### macOS ###
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install ansible
Installation of Ansible using Pip/Pip3
Alternative method is the installation of Ansible using Pip Python package manager:
### Ubuntu / Debian ###
sudo apt update
sudo apt install python3 python3-pip
sudo pip3 install ansible
### CentOS 8 / Rocky Linux 8 / AlmaLinux 8 ###
sudo yum install python3 python3-pip
sudo pip3 install ansible
Confirm Ansible version installed in your system:
$ ansible --version
ansible [core 2.11.5]
config file = None
configured module search path = ['/home/rocky/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
ansible collection location = /home/rocky/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible
python version = 3.6.8 (default, Sep 21 2021, 18:40:00) [GCC 8.4.1 20200928 (Red Hat 8.4.1-1)]
jinja version = 2.10.1
libyaml = True
Step 2 : Set up your Inventory file
Ansible creates an inventory file during installation, which is normally located at /etc/ansible/hosts. During a playbook or command execution, Ansible uses this as the default location if a custom inventory file is not specified with the -i option.
To edit the contents of your default Ansible location, use the text editor of your choice and edit the /etc/ansible/hosts file.
sudo vi /etc/ansible/hosts
Command output :
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
# Ex 1: Ungrouped hosts, specify before any group headers.
## green.example.com
## blue.example.com
## 192.168.100.1
## 192.168.100.10
# Ex 2: A collection of hosts belonging to the 'webservers' group
## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
.
.
.
.
## [dbservers]
##
## db01.intranet.mydomain.net
## db02.intranet.mydomain.net
## 10.25.1.56
## 10.25.1.57
# Here's another example of host ranges, this time there are no
# leading 0s:
## db-[99:101]-node.example.com
[Servers]
192.168.201.2
192.168.201.3
[Servers:vars]
ansible_user=Jil
ansible_password='***********@1987'
Towards the end of the configuration file, I have created a group called [Servers] and listed their IP addresses. These are my two servers for the purposes of this article. In [Servers:vars] i have defined my servers variables, which include my server user and password.
After making your changes save and exit your editor.
We will do one more thing. We will now allow host_key_checking in the ansible.cfg file.
using your text editor :
sudo vi /etc/ansible/ansible.cfg
Scroll down till you get to this line of the script
# uncomment this to disable SSH key host checking
# host_key_checking = False
Uncomment the line to disable SSH key host checking.
host_key_checking = False
Save and exit your editor.
Step 3: Testing connection from control node
We will now test if our Ansible control node is able to connect to our two hosts. This will be achieved by pinging our hosts:
sudo ansible Servers -m ping
The output:
[cloudspinx@rocky-linux ~]$ ansible Servers -m ping
[DEPRECATION WARNING]: Distribution fedora 34 on host 192.168.201.3 should use
/usr/bin/python3, but is using /usr/bin/python for backward compatibility with
prior Ansible releases. A future Ansible release will default to using the
discovered platform python for this host. See https://docs.ansible.com/ansible/
2.9/reference_appendices/interpreter_discovery.html for more information. This
feature will be removed in version 2.12. Deprecation warnings can be disabled
by setting deprecation_warnings=False in ansible.cfg.
192.168.201.3 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.201.2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
Congratulations, you have successfully pinged your hosts from your Ansible control node.
Step 4 : Running Ad-hoc commands
Once the connection is successful, it’s time to test an ad-hoc command. In this article, I will check the OS release running on my two Servers and the disk usage.
Check my Servers OS release
This can be done by executing this command:
ansible Servers -a "cat /etc/os-release"
The output of the command.
[cloudspinx@rocky-linux ~]$ ansible Servers -a "cat /etc/os-release"
192.168.201.2 | CHANGED | rc=0 >>
NAME="Rocky Linux"
VERSION="8.4 (Green Obsidian)"
ID="rocky"
ID_LIKE="rhel centos fedora"
VERSION_ID="8.4"
PLATFORM_ID="platform:el8"
PRETTY_NAME="Rocky Linux 8.4 (Green Obsidian)"
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:rocky:rocky:8.4:GA"
HOME_URL="https://rockylinux.org/"
BUG_REPORT_URL="https://bugs.rockylinux.org/"
ROCKY_SUPPORT_PRODUCT="Rocky Linux"
ROCKY_SUPPORT_PRODUCT_VERSION="8"
[DEPRECATION WARNING]: Distribution fedora 34 on host 192.168.201.3 should use
/usr/bin/python3, but is using /usr/bin/python for backward compatibility with
prior Ansible releases. A future Ansible release will default to using the
discovered platform python for this host. See https://docs.ansible.com/ansible/
2.9/reference_appendices/interpreter_discovery.html for more information. This
feature will be removed in version 2.12. Deprecation warnings can be disabled
by setting deprecation_warnings=False in ansible.cfg.
192.168.201.3 | CHANGED | rc=0 >>
NAME=Fedora
VERSION="34 (Server Edition)"
ID=fedora
VERSION_ID=34
VERSION_CODENAME=""
PLATFORM_ID="platform:f34"
PRETTY_NAME="Fedora 34 (Server Edition)"
ANSI_COLOR="0;38;2;60;110;180"
LOGO=fedora-logo-icon
CPE_NAME="cpe:/o:fedoraproject:fedora:34"
HOME_URL="https://fedoraproject.org/"
DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f34/system-administrators-guide/"
SUPPORT_URL="https://fedoraproject.org/wiki/Communicating_and_getting_help"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_BUGZILLA_PRODUCT="Fedora"
REDHAT_BUGZILLA_PRODUCT_VERSION=34
REDHAT_SUPPORT_PRODUCT="Fedora"
REDHAT_SUPPORT_PRODUCT_VERSION=34
PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
VARIANT="Server Edition"
VARIANT_ID=server
[Jil@rocky-linux ~]$
Check my Servers disk usage
To check disk usage, you would run this command:
ansible Servers -a "df -h" -u Jil
Command output :
[cloudspinx@rocky-linux ~]$ ansible Servers -a "df -h" -u clouflare
[DEPRECATION WARNING]: Distribution fedora 34 on host 192.168.201.3 should use
/usr/bin/python3, but is using /usr/bin/python for backward compatibility with
prior Ansible releases. A future Ansible release will default to using the
discovered platform python for this host. See https://docs.ansible.com/ansible/
2.9/reference_appendices/interpreter_discovery.html for more information. This
feature will be removed in version 2.12. Deprecation warnings can be disabled
by setting deprecation_warnings=False in ansible.cfg.
192.168.201.3 | CHANGED | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 2.0G 0 2.0G 0% /dev/shm
tmpfs 783M 1.1M 782M 1% /run
/dev/mapper/fedora_fedora-root 15G 1.8G 14G 12% /
tmpfs 2.0G 88K 2.0G 1% /tmp
/dev/vda1 1014M 234M 781M 24% /boot
tmpfs 392M 0 392M 0% /run/user/1000
192.168.201.2 | CHANGED | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
devtmpfs 3.8G 0 3.8G 0% /dev
tmpfs 3.8G 0 3.8G 0% /dev/shm
tmpfs 3.8G 9.2M 3.8G 1% /run
tmpfs 3.8G 0 3.8G 0% /sys/fs/cgroup
/dev/mapper/rl-root 48G 5.0G 43G 11% /
/dev/mapper/rl-home 24G 213M 24G 1% /home
/dev/vda1 1014M 324M 691M 32% /boot
tmpfs 777M 1.2M 776M 1% /run/user/42
tmpfs 777M 4.0K 777M 1% /run/user/1000
[Jil@rocky-linux ~]$
Wow, that is cool, isn’t it? You have successfully run an ad-hoc command. There is no limit to what you can achieve with ad-hoc commands, from installing packages to individual nodes, upgrading systems, shutting down some services, and so on.
Running playbooks in Ansible
Lets create a playbook that will check if vi text editor is available on our Servers group created above.
Step 1: Create a playbook file.
To create a playbook file:
sudo ansible-playbook ilovevim.yml
Paste this code :
---
- name: ilovevim
hosts: Servers
tasks:
- name: ensure vim is installed
yum:
name: vi
state: latest
From the sample output, – name: ilovevim defines our play, hosts: Servers defines our two servers hosts created above, – name: ensure vi is here defines our task, yum: is our module.
Save and exit and your text editor.
Step 2: Running the playbook file.
Once you have created your playbook and defined all the parameters, run your playbook.
sudo ansible-playbook ilovevim.yml
Command output:
[cloudspinx@rocky-linux ansible]$ sudo ansible-playbook ilovevim.yml
PLAY [ilovevim] ****************************************************************
TASK [Gathering Facts] *********************************************************
[DEPRECATION WARNING]: Distribution fedora 34 on host 192.168.201.3 should use
/usr/bin/python3, but is using /usr/bin/python for backward compatibility with
prior Ansible releases. A future Ansible release will default to using the
discovered platform python for this host. See https://docs.ansible.com/ansible/
2.9/reference_appendices/interpreter_discovery.html for more information. This
feature will be removed in version 2.12. Deprecation warnings can be disabled
by setting deprecation_warnings=False in ansible.cfg.
ok: [192.168.201.3]
ok: [192.168.201.2]
TASK [ensure vi is here] *******************************************************
ok: [192.168.201.2]
ok: [192.168.201.3]
PLAY RECAP *********************************************************************
192.168.201.2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.201.3 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
The output ok=2 changed=0 for our two servers indicates that no changes were made. Ansible never make changes for something that is already there. This, therefore, means that our task to check if vi is there/installed in our servers is already present i.e vi is present in our two hosts, and it’s already in the current state. Ansible will only make a change if the change is not there.
What if we wanted to remove vim our hosts?
Go to your ilovevim.yml playbook and change the state to removed.
---
- name: Ensure vim is removed on the system
hosts: Servers
tasks:
- name: ensure vim is removed
package:
name: vim
state: absent
Save and exit your editor the run the playbook:
[cloudspinx@rocky-linux ansible]$ ansible-playbook ilovevim.yml
PLAY [ilovevim] **************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************
[DEPRECATION WARNING]: Distribution fedora 34 on host 192.168.201.3 should use /usr/bin/python3, but is using /usr/bin/python for backward
compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in version
2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [192.168.201.3]
ok: [192.168.201.2]
TASK [remove vim] ************************************************************************************************************************************
ok: [192.168.201.2]
ok: [192.168.201.3]
TASK [ensure vi is here] *****************************************************************************************************************************
ok: [192.168.201.2]
ok: [192.168.201.3]
PLAY RECAP *******************************************************************************************************************************************
192.168.201.2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.201.3 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Congratulations on running your playbook.
Conclusion
In this guide, you have successfully defined an Ansible Inventory, connected to nodes, and checked on a few ad-hoc examples on how to use ansible. We also briefly looked at playbook. This was a brief guide and we do hope you have followed along. With Ansible you can automate Infrastructure, Applications, networks, Containers, Security, and Cloud. This is a tool that every SysAdmin should have at his/her disposal to help him achieve much more in a very short time. Thank you.
See more resources: