Understanding basics of Ansible

Ansible is a radically simple IT automation engine that automates cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other IT needs.

Designed for multi-tier deployments since day one, Ansible models your IT infrastructure by describing how all of your systems inter-relate, rather than just managing one system at a time.

Inventory

Ansible can work with one or multiple systems in your infrastructure. To work with these systems/servers, it needs to create a connection with these servers. This is done using SSH for Linux and power shell remoting for windows that makes Ansible agentless. It means we don't need to install any additional software on the target machine.

Information about these target systems is stored in a file called an Inventory file. If you don't create a new Inventory file then Ansible uses a default Inventory file located at “/etc/ansible/hosts”.

We can define the server names in an Inventory like

server1.company.com
server2.company.com

OR we can just pass their IP address

192.168.1.201
192.168.1.202

Groups in Inventory

We can create different groups of servers inside the Inventory like

[database]
192.168.1.201
192.168.1.202
[node]
192.168.1.201
[master]
92.168.1.202

The name of the group can be anything we want. It is used to target specific machines for specific installations.

Ansible creates a default group named “all”, it includes all the servers defined in an Inventory file.

Alias

We can define the alias of the servers to make it more readable using “ansible_host”.

db ansible_host=192.168.1.202
node ansible_host=192.168.1.201

There are other inventory parameters present like

ansible_connection - ssh/winrm/localhost
ansible_port - 22/5986
ansible_user - root/administrator
ansible_ssh_pass - Password

ansible_connection defines how Ansible connects to the target server

db ansible_host=192.168.1.202 ansible_connection=ssh
node ansible_host=192.168.1.201 ansible_connection=winrm

ansible_port defines which port to connect to (of target server), by default it is set to port 22 for SSH but we can update the value using the ansible_port parameter

db ansible_host=192.168.1.202 ansible_connection=ssh  ansible_port=9090
node ansible_host=192.168.1.201 ansible_connection=winrm

ansible_user defines the user used to make the remote connection, by default it is root.

db ansible_host=192.168.1.202 ansible_connection=ssh  ansible_port=9090
node ansible_host=192.168.1.201 ansible_connection=winrm ansible_user="xyz"

ansible_ssh_pass defines the SSH password for Linux

ansible_password for windows

db ansible_host=192.168.1.202 ansible_connection=ssh  ansible_port=9090
node ansible_host=192.168.1.201 ansible_connection=winrm ansible_user="xyz" ansible_ssh_pass=TR@57!

We can make a group of groups using [<group-name>:children],
In this group, we can define the names of the other groups.

[database]
192.168.1.201
192.168.1.202
[node]
192.168.1.201
[master]
92.168.1.202

[code:children]
database
node

Ansible Playbook

Ansible Playbooks are Ansible orchestration language. Here, we define what we want to do with the servers. We can define a different variety of commands that include copying some stuff on the servers, installing some software on them to deploying virtual machines on servers. Ansible playbook gives a variety of commands to work with.

All playbooks are written in YAML format. A playbook is a single YAML file containing a set of plays. Each play contains a set of tasks to perform(tasks to perform on a server or a server group).

Each task runs some actions called Modules like command, script, service, yum, etc. We will see them in detail later in the article.

Ansible-playbook Example:

# Play 1  
- name: update web servers
hosts: webservers
become: yes
become_user: root

tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
# Play 2
- name: update db servers
hosts: databases
remote_user: root
tasks:
- name: ensure postgresql is at the latest version
yum:
name: postgresql
state: latest
- name: ensure that postgresql is started
service:
name: postgresql
state: started

Each playbook must have at least a name, hosts, and tasks to execute and can have other properties like:

name:

Name of the play, a single ansible-playbook can have multiple plays and each must have a unique name.

hosts:

Name of host group defined in an Inventory file

become:

Executes the play using a user with higher privileges

become_user:

Changes the user to the given user while executing the tasks.

tasks:

Set of tasks to perform on the defined hosts.

and many more…

Each play has a set of tasks that gets executed in a defined order. So the order of tasks plays a major role in a play. But the direct properties order does not matter like in Play 2 (in the ansible-playbook example) writing remote_user before the hosts are not going to impact it but reversing the order of tasks will change the whole play.

Each task must have a name and module.

Examples of tasks

    - name: Install the httpd apps
yum: name=httpd

- name: Deploy configuration File
template: src=templates/index.j2 dest=/var/www/html/index.html

- name: start the httpd service
service: name=httpd state=started

- name: Install common software requirements
yum: pkg={{ item }} state=installed
with_items:
- git
- ntp
- vim

The main part of a task is the module that it executes.

Modules

A module is a reusable, standalone script that Ansible runs on your behalf, either locally or remotely. Modules interact with your local machine, an API, or a remote system to perform specific tasks like changing a database password or spinning up a cloud instance.

Ansible ships with several modules, that are categorized in many categories that can be executed directly on remote hosts or through Playbooks.

Users can also write their own modules. These modules can control system resources, like services, packages, or files (anything really), or handle executing system commands.

We can execute modules using the ansible command like:

ansible group1 -m ping -i inventories.txt

-m is used to define the module in the ansible command.

and using playbook like:

  - name: Test connectivity
hosts: all
tasks:
- name: Ping test
ping:

They are categorized into different module categories like System, Commands, Files, Database, Cloud, etc.

System

It is used to modify the system like modifying the user, IP tables, firewall settings, etc.

  - name: System module category Example
hosts: all
tasks:
- name: Add the user 'johnd' with a specific uid and a primary group of 'admin'
user:
name: johnd
comment: John Doe
uid: 1040
group: admin

Commands

It is used to run a command or scripts on host servers

  - name: Command module category example
hosts: all
tasks:
- name: Execute the UNAME command
register: unameout
command: "uname -a"

Files

It is used to work with files like copying a file in all the defined servers, searching a file in all the defined servers, etc.

  - name: Files module category example
hosts: all
tasks:
- name: Change file ownership, group and permissions
ansible.builtin.file:
path: /etc/foo.conf
owner: foo
group: foo
mode: '0644'

Database

Used to work with databases like MySQL, PostgreSQL, MongoDB, etc.

  - name: Database module category example
hosts: all
tasks:
- mssql_db:
name: jackdata
state: present
- copy:
src: dump.sql
dest: /tmp
- mssql_db:
name: my_db
state: import
target: /tmp/dump.sql

Cloud

Used to work with cloud service providers like AWS, Azure, Docker, etc.

- name: Cloud module category example
hosts: all
tasks:
- name: Create a new direct connect gateway attached to virtual private gateway
dxgw:
state: present
name: my-dx-gateway
amazon_asn: 7224
virtual_gateway_id: vpg-12345
register: created_dxgw

Windows

Helps to use ansible in Windows operating system, it includes modules like Win_copy, Win_command, Win_domain, Win_use, etc.

- name: Windows module category example
hosts: all
tasks:
- name: Download the 7-Zip package
win_get_url:
url: https://www.7-zip.org/a/7z1701-x64.msi
dest: C:\temp\7z.msi

There are many more modules present, it is not possible to talk about all of them in the article. You can see the list of modules using the command :

ansible-doc -l

Running ansible-playbook

There are two ways to run an Ansible playbook

  1. Using ansible command
  2. Using ansible-playbook command

Ansible command is used when we execute a single task on the defined servers in Inventory.

Syntax:

ansible <host-group> -a <command> -i <inventory file path with name>

ansible <host-group> -m <module> -i <inventory file path with name>

If we want to use the direct command then we have to use “-a” and if we are using any module to execute the task, we have to use “-m”.

Examples:

ansible group1 -a "/sbin/reboot" -i inventory.txtansible group1 -m ping -i inventories/inventory1.txt

The first command is used to reboot the server, here we are directly calling the command so we used -a. In the second command, we are using the ping module to check the connectivity of the group1 server group.

group1 is a group of servers present in the inventory file, We need to provide the inventory file name with the path where the server groups are defined.

But if we are using the server name directly in the command then there is no need to provide any inventory file name.

ansible 192.168.1.201 -a "/sbin/reboot"

But the main purpose of Ansible is not to run single commands but to run multiple commands at the same time on multiple servers. For that, we need to write an ansible-playbook, and to execute the ansible-playbook we need ansible-playbook command

Syntax:

ansible-playbook <anisble playbook name> -i <inventory-file>

Sample-playbook.yaml

  - name: Test connectivity
hosts: all
tasks:
- name: Ping test
ping:

inventory.txt

node ansible_host=192.168.1.201
target ansible_host=192.168.100.21

We can run the playbook like this:

ansible-playbook Sample-playbook.yaml -i inventory.txt

We are not defining any host group as ‘all’ is a default host group that contains all the hosts defined in the inventory file.

For more information, refer to the official documentation: ANSIBLE

Full stack developer