What is Ansible?
Ansible is an open-source engine that automates deployment, orchestration, cloud
provisioning, and other tools. It uses a playbook, to describe jobs, and YAML, which
is a human-readable programming language. Ansible is designed for multi-tier
deployment. It is agentless and works by connecting nodes through SSH.
Chef Architecture till now we studied-
Ansible Architecture
In the above diagram:
The management node controls the whole execution of the playbook.
The inventory file provides the list of hosts where the modules need to be run.
The management node does ‘SSH’ connections and executes the modules and then installs
the software.
Advantages of Ansible
Ansible is free and open-source.
It is agentless; it does not have a master–client model instead uses the SSH model.
It has flexible system requirements.
Ansible is developed in Python.
It is lightweight and quick to deploy.
Ansible uses YAML syntax in config files.
Ansible has a large community base.
Ansible works in PUSH Mechanism not like Chef which is PULL
Install Ansible
REDHAT
Ref - https://www.tecmint.com/install-epel-repo-on-rhel-8/
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
sudo dnf --enablerepo="epel" install ansible
or
if you have REDHAT Account in company, follow below-
342 subscription-manager register >> Give your username and password for REDHAT
343 subscription-manager list –available
This will give you POOL ID
344 subscription-manager attach --pool=8a85f99a75fb07cc01760049fe693e9d
345 subscription-manager list
346 dnf repolist
347 sudo subscription-manager repos --enable ansible-2.9-for-rhel-8-x86_64-rpms
348 dnf repolist
349 sudo yum install ansible
350 ansible --version
yum install ansible -y ## Install now
[root@ip-172-31-0-137 ~]# cd /etc/ansible/
[root@ip-172-31-0-137 ansible]# ls -ltr
total 28
drwxr-xr-x 2 root root 4096 Nov 8 19:40 roles
-rw-r--r-- 1 root root 1016 Nov 8 19:40 hosts
-rw-r--r-- 1 root root 19557 Nov 8 19:40 ansible.cfg
Other method
pip install ansible
Note - pip – python install package
Amazon Linux Machine Image
Using YUM in EC2 –
yum-config-manager --enable epel >> ENABLE Extra Package Enterprise Linux (EPEL) Repo
yum repolist >> Check if it is coming now
Also there are various other method for installing it. Follow below link-
https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#
Validate
ansible --version
Configure new Linux user-”ansadmin” for ansible
[root@ip-172-31-0-137 ansible]# useradd -d /home/ansadmin -m ansadmin
[root@ip-172-31-0-137 ansible]#
(Only for Controller)
[root@ip-172-31-0-137 ansible]# passwd ansadmin
Changing password for user ansi.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.
[root@ip-172-31-0-137 ansible]# passwd -x -1 ansadmin
Adjusting aging data for user ansi.
passwd: Success
Add linux user – ansi in sudoers file so that it can login to root with sudo permission and without
password
cp /etc/sudoers /etc/sudoers-orig
vi /etc/sudoers
su – ansadmin
from ansi, now try
sudo su – or
sudo -i or
sudo su – root
sudo -u root -i
For Ubuntu
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
ansadmin ALL=(ALL) ALL
SSH SETUP
Login to ansadmin user and do following –
Copy the id_rsa.pub file to authorized_keys
Generate Keys
ssh-keygen
In the Controller Machine-
controller$ pwd
/home/ansadmin/.ssh
[ansadmin@ip-172-31-0-137 .ssh]# cat id_rsa.pub >> authorized_keys
chmod 600 authorized_keys
Create an AMI and Launch Servers
One you have launched servers, you will find automatically you re able to connect to those servers
from Ansible Controller.
Inventory File
[root@ip-172-31-0-137 ansible]# ls -ltr /etc/ansible/hosts
-rw-r--r-- 1 root root 1094 Jan 26 19:37 /etc/ansible/hosts
Add below line
Here there are 2 Groups – one for server or controller and other for nodes
In the Controller Server (Source Server) –
[root@ip-172-31-5-127 ~]# chown -R ansadmin:root /etc/ansible/
To solve this issue – follow below steps
go to /etc/ssh/sshd_config and take backup
Change - PasswordAuthentication yes
Restart the SSHD service – service sshd restart
Validate using simple ping
In case SSH is not setup correctly you will get below error –
If not using SSH, then pass pem file which is generated while creating servers
ansible -m ping -u ec2-user --private-key=server.pem webservers
ansible -m ping -u ec2-user --private-key=server.pem all
if you don’t want to pass user name, do below in your inventory file
ansible -m ping --private-key=server.pem all
We can also like below – ex IP range 172.32.20.*
Modules – We will try to use all this modules -
Adhoc command
[root@ip-172-31-0-137 ansible]# ansible webservers -m shell -a 'hostname'
ip-172-31-0-137 | SUCCESS | rc=0 >>
ip-172-31-0-137
Copy module
[root@ip-172-31-0-137 ansible]# ansible all -m copy -a 'src=/etc/ansible/ansible.cfg dest=/tmp'
ip-172-31-0-137 | SUCCESS => {
"changed": true,
"checksum": "f678e2867b1765c7050baaedb553878d2c5b6094",
"dest": "/tmp/ansible.cfg",
"gid": 0,
"group": "root",
"md5sum": "2e69039656783b5d1a55e8f3073be821",
"mode": "0644",
"owner": "root",
"size": 19557,
"src": "/root/.ansible/tmp/ansible-tmp-1580070255.1-145301629884706/source",
"state": "file",
"uid": 0
}
With ROOT PRIVILEGE
[ansadmin@ip-172-31-40-162 template]$ ansible all -m copy -a
'src=/etc/ansible/template/httpd.conf dest=/etc/httpd/conf' --sudo
control$ ansible apache -m shell -a 'echo welcome123 > /root/.password1' -b
172.31.42.135 | SUCCESS | rc=0 >>
Ad hoc commands
Function Command
To check the connectivity of hosts #ansible <group> -m ping
To reboot hosts #ansible <group> -a”/bin/reboot”
To check the host system’s info #ansible <group> -m setup | less
To transfer files #ansible <group> -m copy -a ”src=home/ansible dest=/tmp/home”
To create a new user #ansible <group> -m user -a ”name=ansible password= <encrypted
password>”
To delete a user #ansible <group> -m user -a ”name=ansible state=absent”
To check if a package is installed and to update it #ansible <group> -m yum -a ”name=httpd state=latest”
To check if a package is installed but not to #ansible <group> -m yum -a ”name=httpd state=present”
update it
To check if a package is of a specific version #ansible <group> -m yum -a”name=httpd-1.8 state=latest”
To check if a package is not installed #ansible <group> -m yum -a”name=httpd state= absent
To start a service #ansible <group> -m service -a”name=httpd state=”started”
To stop a service #ansible <group> -m service -a”name=httpd state=”stopped”
To restart a service #ansible <group> -m service -a”name= httpd state=”restarted”
YAML – Yet Another Markup Lang
Please compare-
Key Value pair
Fruit: Apple << Make sure there is space
Array/List
If we like to categorize few elements in same group, then we will use it
Dash(-) Represent here, that it is an element of an array or list
Dictionary/Map – Set of property group together
under an Item
Equal Spaces – Indentation is very Important
Extra Space under Fat and Carbs – Syntax Error
This will result in syntax issue, so we should be checking this
Advanced -
List of dictionaries
This is a LIST of Dictionaries which is key-value pair –
Dictionary in Dictionary -
- Dictionary – we can move name and hosts (up & down)
- but in LIST it is not advisable to change
Ansible Playbook –
Playbooks are Ansible’s configuration, deployment, and orchestration language. They can
describe a policy you want your remote systems to enforce, or a set of steps in a general IT
process.
If Ansible modules are the tools in your workshop, playbooks are your instruction manuals,
and your inventory of hosts are your raw material.
Playbooks
It is the place where all the YAML files are stored and executed. It acts as a to-do list.
A playbook can have more than one play.
A play maps the instructions defined against a particular host.
It is typically written in a text editor such as notepad or notepad++ or visual studio code or
atom or VIM
Sample playbook/YAML file:
1. Install apache
2. create doc root - dir "/var/www/html/learnwithproject.com"
3. copy httpd.conf to server - timeout and directory structure
4. git pull the code to new doc root- index.html
5. start of apache
---
- name: "Play 1- apache configure"
hosts: webservers
become: yes
tasks:
- name: "Install packages"
yum:
name: "{{ item }}"
state: present
with_items:
- httpd
- vim
- wget
- tree
- git
- name: Create a directory if it does not exist
file:
path: /var/www/html/learnwithproject.com
state: directory
mode: '0755'
owner: root
group: root
- name: "Configure Apache with Timeout 150 secs"
copy:
src: /etc/ansible/template/httpd.conf
dest: /etc/httpd/conf/httpd.conf
owner: root
group: root
mode: '0644'
- name: "code copy"
git:
repo: 'https://github.com/mailrahulsre/learnwithprojects.com.git'
dest: /var/www/html/learnwithproject.com
version: master
- name: "start apache"
service: name=httpd state=started
[ansi@ip-172-31-2-20 ansible]$ cat play2.yml
--- #YAML Syntax- just to under this is YAML
- name: Play1
hosts: webservers
become: yes ## Sudo to root from ansi user
vars:
ansible_python_interpreter: /usr/bin/python # if you are using mixed python version in your system, then some error might come
tasks:
- name: "Install Apache"
yum:
name: ‘httpd’
state: present
- name: "start apache"
service: name=httpd state=started
Some general tags of YAML:
Name: Name of a playbook (optional)
Hosts: A mandatory field that specifies the list of hosts and the tasks that can be performed on the same
machine or on a different one (mandatory)
Vars: Defines the variables that we can use (optional)
Tasks: The list of actions that need to be performed; contains the name of the task (a task is always linked to a
module) (mandatory)
become: yes This says ansible to run the commands using ROOT (optional)
Loops
Loops can do one task on multiple things, such as create a lot of users, install a
lot of packages, or repeat a polling step until a certain result is reached.
- yum:
name: "{{ item }}"
state: present
with_items:
- httpd
- vim
- wget
- tree
Conditionals
Ansible supports the conditional execution of a task based on the run-time
evaluation of variable, fact, or previous task result.
tasks:
yum:
name: httpd
state: latest
when: ansible_os_family == "RedHat"
or
tasks:
- name: "shut down CentOS 6 systems"
command: /sbin/shutdown -t now
when:
- ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_major_version'] == "6"
Tags
Tags are useful to be able to run a subset of a playbook on-demand.
tasks:
- yum:
name: "{{ item }}"
state: latest
with_items:
- httpd
- mod_wsgi
tags:
- packages
- template:
src: templates/httpd.conf.j2
dest: /etc/httpd/conf/httpd.conf
tags:
- configuration
---
- name: "Play 1 – httpd install"
hosts: webservers
become: yes
tasks:
- name: Install important packages
yum:
name: "{{ item }}"
state: latest
with_items:
- tree
- tar
- telnet
- bind-utils
- httpd
when: ansible_os_family == "RedHat"
tags: install
- name: service start
service:
name: httpd
state: started
tags: service_started
[ansadmin@ip-172-31-4-13 ansible]$ ansible-playbook httpd.yml --tags=install
PLAY [Play 1 – git install] ***********************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [ip-172-31-34-89]
ok: [localhost]
TASK [Install important packages] *****************************************************************
ok: [ip-172-31-34-89] => (item=[u'tree', u'tar', u'telnet', u'bind-utils', u'zip'])
ok: [localhost] => (item=[u'tree', u'tar', u'telnet', u'bind-utils', u'zip'])
PLAY RECAP ****************************************************************************************
ip-172-31-34-89 : ok=2 changed=0 unreachable=0 failed=0
localhost : ok=2 changed=0 unreachable=0 failed=0
[ansadmin@ip-172-31-4-13 ansible]$
[ansadmin@ip-172-31-4-13 ansible]$
[ansadmin@ip-172-31-4-13 ansible]$ ansible-playbook git.yml -t service_started
PLAY [Play 1 – git install] ***********************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [ip-172-31-34-89]
ok: [localhost]
TASK [service start] ******************************************************************************
changed: [localhost]
changed: [ip-172-31-34-89]
PLAY RECAP ****************************************************************************************
ip-172-31-34-89 : ok=2 changed=1 unreachable=0 failed=0
localhost : ok=2 changed=1 unreachable=0 failed=0
control$ ansible-playbook apache.yml --skip-tags=install-packages
PLAY [Play 1- apache configure] *************************************************************************
TASK [Gathering Facts] **********************************************************************************
ok: [172.31.1.66]
TASK [Create a directory if it does not exist] **********************************************************
ok: [172.31.1.66]
TASK [Configure Apache with Timeout 150 secs] ***********************************************************
ok: [172.31.1.66]
TASK [code copy] ****************************************************************************************
ok: [172.31.1.66]
TASK [start apache] *************************************************************************************
ok: [172.31.1.66]
PLAY RECAP **********************************************************************************************
172.31.1.66 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Roles
Like we have roles in real life, similarly we have roles in Ansible which can re-used in multiple
playbooks.
We can do the same thing using playbook and running it
Project for Ansible Role –
Role Description –
Define common tasks for your Role-
Apache
1. Install Apache
2. Configure Apache
a. Copying httpd.conf from Template which will have timeout 150 secs
b. Copy test code – lb-health-check.html to document root
3. Service start
Let’s do it
Creating a directory structure
ansible-galaxy init /etc/ansible/roles/apache
cd /etc/ansible/roles/apache
[root@ip-172-31-14-110 apache]# ls -ltr files/ tasks/ meta/ handlers/
meta/:
total 4
-rw-r--r-- 1 root root 45 Jan 31 04:28 main.yml
tasks/:
total 16
-rw-r--r-- 1 root root 133 Jan 31 04:31 main.yml
-rw-r--r-- 1 root root 57 Jan 31 04:32 install.yml
-rw-r--r-- 1 root root 88 Jan 31 04:34 service.yml
-rw-r--r-- 1 root root 224 Jan 31 04:35 configure.yml
files/:
total 40
-rw-r--r-- 1 root root 34498 Jan 31 04:35 httpd.original
-rw-r--r-- 1 root root 16 Jan 31 04:36 index.html
handlers/:
total 4
-rw-r--r-- 1 root root 111 Jan 31 04:38 main.yml
vars/
main.yml
Update below task
cntrl $ pwd
/etc/ansible/roles/apache/tasks
[root@ip-172-31-14-110 tasks]# cat main.yml
---
# tasks file for /etc/ansible/roles/apache
- import_tasks: install.yml
- import_tasks: configure.yml
- import_tasks: service.yml
[root@ip-172-31-14-110 tasks]# cat install.yml
- name: ensure a list of packages installed
yum:
name: "{{ packages }}"
[ansadmin@ip-172-31-7-217 vars]$ pwd
/etc/ansible/roles/apache/vars
[ansadmin@ip-172-31-7-217 vars]$ cat main.yml
---
# vars file for /etc/ansible/roles/apache
packages:
- httpd
- httpd-tools
[root@ip-172-31-14-110 tasks]# cat configure.yml
- name: "Copy httpd Configuration file"
copy: src= files/httpd.original dest=/etc/httpd/conf/httpd.conf
- name: "Copy index.html file"
copy: src=files/index.html dest=/var/www/html/index.html
notify:
- restart apache
[root@ip-172-31-14-110 tasks]# cat service.yml
- name: Start and Enable http service
service: name=httpd state=restarted enabled=yes
Update Handlers
/etc/ansible/roles/apache/handlers
[root@ip-172-31-14-110 handlers]# cat main.yml
---
# handlers file for /etc/ansible/roles/apache
- name: restart apache
service: name=httpd state=restarted
Update meta/main.yml
[root@ip-172-31-14-110 apache]# cd meta/
[root@ip-172-31-14-110 meta]# ls
main.yml
[root@ip-172-31-14-110 meta]#
[root@ip-172-31-14-110 meta]#
[root@ip-172-31-14-110 meta]# cat main.yml
galaxy_info:
author: rahul Chaudhuri
description: apache
company: your company (optional)
Copy the files which needs to copied to nodes as per configure.yml
[root@ip-172-31-14-110 files]# ls -ltr
total 40
-rw-r--r-- 1 root root 34498 Jan 31 04:35 httpd.original
-rw-r--r-- 1 root root 16 Jan 31 04:36 index.html
Go to /etc/ansible and create business specific YAML file
[root@ip-172-31-14-110 ansible]# pwd
/etc/ansible
Create 2 Ansible Playbooks calling generic roles and some customization for their 2 separate
Business
cntrl $ cat xyz-com.yml
---
- name: Configure Apache for httpd
hosts: xyz-com-apache-node
become: yes
roles:
- httpd
- name: Configure Apache for httpd
hosts: xyz-com-apache-node
become: yes
tasks:
- name: copy the xyz.com code
copy:
src: /etc/ansible/xyz-com/xyz.html
dest: /var/www/html/xyz.html
owner: root
cntrl $ cat abc-com.yml
---
- name: Configure Apache for httpd
hosts: abc-com-apache-node
become: yes
roles:
- httpd
- name: Configure Apache for httpd
hosts: abc-com-apache-node
become: yes
tasks:
- name: copy the abc.com code
copy:
src: /etc/ansible/abc-com/abc.html
dest: /var/www/html/abc.html
owner: root
Host file change
Sample playbook -
Now RUN IT
Cheat SHEET
https://intellipaat.com/mediaFiles/2019/03/Ansible-cheat-sheet.pdf