Getting started With Ansible - Part Two (Inventory)

This article is based on the inventory and modules in Ansible and we will learn how they can be used in Ansible.

In the previous article Getting started with Ansible – Part 1 of the series “Learning Ansible”, we have seen the installation of Ansible and the set up of web and database servers with CentOS and Ubuntu operating systems. We also saw the creation of a user, giving the user sudo privilege, and enabling password authentication.
 
So, in this article, we will learn the following.
  • Inventory 
  • Groups in Inventory, Group of groups
  • Variables in Inventory
  • Execute Inventory file for a host with variables different than group variables.
  • Escalate privilege for the user.
  • Ansible modules like ping, yum, apt and service.

Inventory, Groups, and Group of groups

 
Inventory is a text file where we define the host information that we are going to manage through Ansible.
 
The default path of the inventory file is /etc/ansible/hosts/ but we can also specify a different inventory file using -I <path of inventory file> on the command line.
 
So in continuation of the previous article Getting started with Ansible – Part 1 where we created our project directory “superman”, we are going to create an inventory file.
 
Step 1
 
Create an inventory file using the command
  1. vim inventory  
Ansible
 
Step 2
 
Add the below code in the inventory file. 
  1. websrv01 ansible_host=172.31.4.33 ansible_user=devops ansible_ssh_pass=devops123    
  2. websrv02 ansible_host=172.31.15.84 ansible_user=devops ansible_ssh_pass=devops123    
  3. websrv03 ansible_host=172.31.8.231 ansible_user=devops ansible_ssh_pass=devops123    
  4. dbsrv01 ansible_host=172.31.1.205 ansible_user=devops ansible_ssh_pass=devops123    
  5.     
  6.      
  7. [WebServersGroup]    
  8. websrv01    
  9. websrv02    
  10. websrv03    
  11.      
  12. [DBServerGroup]    
  13. dbsrv01    
  14.      
  15. [DataCenter_Ncali:children]    
  16. WebServersGroup    
  17. DBServerGroup     
Now let’s understand code written in the inventory file,
  • Here we can see that we have specified all our hosts; i.e. the IP of 3 web servers and 1 DB server and we have also given the username and password for all of them.
  • We can see a group of web servers named WebServersGroup. This would be really helpful if we want to configure something on all web servers then we can simply give this WebServersGroup rather than specifying the IP of each web server host machine.
  • We can see a group of DB servers, though as of now we have only 1 db server but it is a good practice to keep similar kind of hosts in a group to later manage them effectively.
  • We can also see a group called DataCenter_Ncali: children. This is a group of groups for North California region as all our servers are present in this region so we have given the group name as DataCenter_Ncali: children. This would be helpful in case we have different hosts residing in different region.
  • So, if we want to run a configuration then we can club them as per region and can run the configuration by giving the appropriate group name which will contain other subgroups.
  • DataCenter_Ncali:children is a master group and underneath specifies the other group names.
Step 3
 
We have to ping each of the hosts defined in the inventory file using the ping module.
 
To call any module in Ansible we use -m option.
 
So, the command will be the following.
  1. ansible -I inventory -m ping websrv01  
Output
 
Ansible
 
Few things to note here,
 
Now, we are getting this error because whenever we do SSH to any host then for the first time it asks whether we want to connect or not and when we say yes, it saves the fingerprint of that host machine to the local host's file. So, this is the same due to which we are getting the error above.
 
Step 4
 
Thus, the same thing is happening with ansible as well and it will also get the prompt for yes or no. So, now we have to make ansible to skip this option.
 
So open default ansible config file at /etc/ansible/ansible.cfg and uncomment host_key_checking=False.
 
Now let's try again.
  1. ansible -I inventory -m ping websrv01  
Output
 
Ansible
 
And we can see it has successfully pinged web server 01 and has returned pong which means success.
 
Step 5
 
We can also see ping running on the entire group DataCenter_Ncali. This will run the ping command on all web servers and the db server.
  1. ansible -I inventory -m ping DataCenter_Ncali  
Output
 
Ansible
 
We can also do the same using all or * command in the end, this will execute ping on all the hosts (not all groups) mentioned in the inventory file.
  1. ansible -i inventory -m ping all  
  2. ansible -i inventory -m ping '*'  

Variables in Inventory

 
Variables are used to store values in programs and as the name suggests the values can be changed throughout the program.
 
These values are essential to decide the code flow. Ansible variables help to determine how the tasks execute on different systems based on the values assigned to these variables.
 
Step 6
 
Above in the inventory file, we saw host-level variables like ansible_user and ansible_ssh_pass but this was repetitive as we had to define this for each host.
 
Instead what we can do is, we can define these details at the group level using group variables.
 
So, the new inventory file will look something like,
  1. websrv01 ansible_host=172.31.4.33  
  2. websrv02 ansible_host=172.31.15.84  
  3. websrv03 ansible_host=172.31.8.231  
  4. dbsrv01 ansible_host=172.31.1.205  
  5.    
  6. [WebServersGroup]  
  7. websrv01  
  8. websrv02  
  9. websrv03  
  10.    
  11. [DBServerGroup]  
  12. dbsrv01  
  13.    
  14. [DataCenter_Ncali:children]  
  15. WebServersGroup  
  16. DBServerGroup  
  17.    
  18. [DataCenter_Ncali:vars]  
  19. ansible_user=devops  
  20. ansible_ssh_pass=devops123   
We can ping it again and see if it works,
  1. ansible -I inventory -m ping *  
Ansible
 
Great… It works 😊. So, we have learned how we can use variables at the group level.
 

What if some host has a different username and password?

 
For such cases, we can define the username and password at the host level, as host-level variables have higher priority than group-level variables.
 
So, suppose Db server has a different user with different username and password then we can define it at the host level for Db server.
 
Now, for rest hosts, the group level variables will be applied but for the host with variables at the host level, group-level variables will not be applied.
 
Ansible
 
Step 7
 
Now let’s suppose we want to install some package on all servers. For this Ansible has a yum module.
 
Ping module didn’t have any arguments to pass but the yum module has.
 
We will run the below command:
  1. ansible -I inventory -m yum -a “name=httpd state=present” websrv01  
Output
 
Ansible
 
This says we need to be a root user to perform this command.
 
Here execution is happening with DevOps user and DevOps user is a normal user so cannot install packages but it does have sudoers privilege. So, we can escalate the privilege from the command line.
 
Note
In the previous article Getting started with Ansible – Part 1, we have already given this user “DevOps” root privilege in the sudoers file.
 
To escalate the privilege from the command line we can use - - become.
 
Now the command will look like,
  1. ansible -i inventory -m yum -a "name=httpd state=present" websrv01 --become  
Output
 
Ansible
 
Great… It says that httpd package has been installed on web server 01. YAY… 😊
 
Let’s do it again,
 
Ansible
 
Now it says changed as false because it has already installed the package. So this behavior is called IDEMPOTENT behavior of configuration management tools as mentioned in Introduction to Configuration Management and Ansible.
 
Step 8
 
As our Web server 3 (Ubuntu) is Debian based so we can install package there using apt module. Here package name is apache2.
  1. ansible -i inventory -m apt -a "name=apache2 state=present" websrv03 –become  
  2.   
  3. ansible -i inventory -m apt -a "update-cache=yes" websrv03 --become  
Ansible
 
So apache2 package has been installed successfully.
 
Step 9
 
Lastly, we can start the service on the web servers and for this we have service module in Ansible.
  1. ansible -i inventory -m service -a "name=httpd state=started enabled=yes" websrv01 --become  
Ansible
 
So, the service has been started on web server 1 and similarly, we can do it for other web servers.
 

Summary

 
So, in this article, we have seen practically how we can create inventory file, how we can change global ansible config, how to set up global variables and group and how to use different modules in Ansible.
 
I hope you find this article helpful. Stay tuned for more … Cheers!!
 
You can also check out some of my previous articles of the series “Learning Ansible” here,