Introduction
- Ansible is an IT automation tool. It can be used to deploy applications, configure services on multiple servers in less efforts.
- It works agentless using SSH for connection.
- Configuration files are written in YAML and file extension is yml
- Ansible has controller machine in which Ansible is installed and all playbooks, required templates, files are stored.
- Controller machine connect to client machines over ssh and run required commands.
- Various Ansible modules are available such as user, file, filesystem, service, yum, apt etc.
- Refer http://docs.ansible.com/ansible/index.html
Installation
On RedHat based system using yum:
$ yum install epel-release $ yum install ansible
On Debian based systems using apt:
$ sudo apt-get install software-properties-common $ sudo apt-add-repository ppa:ansible/ansible $ sudo apt-get update $ sudo apt-get install ansible
Configuration
- Configuration files stored in /etc/ansible by default.
- Main configuration file is /etc/ansible/ansible.cfg
For config file Ansible looks into
- First location for ansible.cfg is /etc/ansible/ansible.cfg
- Second location is Current directory / ansible.cfg
So if we create directory name “config” in current directory. Then we need to export ANSIBLE_CONFIG settings.
export ANSIBLE_CONFIG=/opt/ansible/neelesh/config/ansible.cfg
Add above line to ~/.bashrc - Third location is ~/.ansible.cfg
- Hosts inventory is defined under /etc/ansible/hosts by default. However you can define custom host inventory in your ansible.cfg file.
In ansible hosts file, need to add entries in below format:[group_name-1] ip_address or hostname [group_name-2] ip_address or hostname [group_name-3:children] group name-1 group name-2
Note: We have created test-user user on all servers. test-user user has sudo privileges with NOPASSWD.
Basic Commands
List all hosts configured in hosts file.
$ ansible all --list-hosts
List hosts which are member of group_name-1
$ ansible group_name-1 --list-hosts
Pings all hosts which are mentioned in ansible hosts file
$ ansible all -m ping -u test-user -k -s
–> -k to ask for password. We can configure password less connection by doing key exchange.
-m for Ansible module.
-s to use sudo.
To get all facts about ansible clients.
$ ansible all -m setup -u test-user -k
To get facts in file use below command. You will get all facts inside ansible controller in ~/.ansible/tmp/facts/<IP of hadoop-servers>
$ ansible all -m setup --tree ~/.ansible/tmp/facts -u test-user -k
To get only IPaddress facts using setup module
$ ansible all -m setup -a 'filter=*ipv4*' -u test-user -k
Get Architecture details of Ansible clients using setup modules and arguments
$ ansible all -m setup -a 'filter=ansible_arch*' -u test-user -k $ ansible all -m setup -a 'filter=ansible_domain*' -u test-user -k $ ansible all -m setup -a 'filter=ansible_fqdn' -u test-user -k $ ansible all -m setup -a 'filter=ansible_interfaces' -u test-user -k $ ansible all -m setup -a 'filter=ansible_kernel' -u test-user -k $ ansible all -m setup -a 'filter=ansible_memtotal_mb' -u test-user -k $ ansible all -m setup -a 'filter=ansible_proc*' -u test-user -k $ ansible all -m setup -a 'filter=ansible_virt*' -u test-user -k
Check if file is present
$ ansible all -m file -a 'path=/etc/fstab' -u test-user -k
Create directory /tmp/etc
$ ansible all -m file -a 'path=/tmp/etc state=directory \ mode=0700 owner=root' -u test-user -k -s
Remove /tmp/etc
$ ansible all -m command -a 'rm -rf /tmp/etc removes=/tmp/etc' \ -s -u test-user -k
Install lynx browser in Redhat based linux
$ ansible all -s -m yum -a 'pkg=lynx state=installed update_cache=true'
Writing basic Playbook
We define Ansible’s configuration, deployment, and orchestration in Playbooks. Playbooks are like cookbooks in Chef. They can describe a policy you want your remote systems to enforce, or a set of steps in a general IT process.
Playbooks are expressed in YAML format (see YAML Syntax) and have a minimum of syntax.
Each playbook is composed of one or more ‘plays’ in a list. It is possible to run certain steps on webservers and certain steps on application servers by grouping them.
We will write playbook which will install httpd, restart it and enable it at boot time.
It is recommended to start playbook with ‘—‘
It also recommended to use “SPACE” instead of “TAB”,
first.yml
--- # My first playbook - hosts: group_name-1 user: test-user become: yes become_method: sudo gather_facts: yes connection: ssh tasks: - name: Install HTTPD Server package: name=httpd state=latest notify: Restart HTTPD handlers: - name: Restart HTTPD service: name=httpd state=restarted enabled=yes
first.yml has 3 sections.
- Host declaration
- hosts: group_name-1 user: test-user become: yes become_method: sudo gather_facts: yes connection: ssh
- Tasks
tasks: - name: Install HTTPD Server package: pkg=httpd state=latest notify: Restart HTTPD
- Handlers
handlers: - name: Restart HTTPD service: name=httpd state=restarted enabled=yes
All sections are self-explanatory.
- Execute first.yml:
$ ansible-playbook first.yml –k
Notes:
– In Ansible 2.0 for sudo privileges need to usebecome: yes become_method: sudo
– In Ansible version prior to 2.0 need to use – sudo: yes
– value of “notify” in tasks should be same as value of – name in handlers.
Using Roles
Roles are ways of automatically loading certain vars_files, tasks, and handlers for certain group of hosts. Eg. If we have web servers, application servers, db servers in our environment then we can have roles like
common – Common steps for all
web – For all web servers
db – For all db servers
Which organize our playbook appropriately.
Directory structure of role:
In ansible.cfg we can define path of roles to be stored using “roles_path = /path/to/roles/”
Inside roles directory there will be sub structure as below:
../roles/
———webserver/
———————– tasks
———————– files
———————– vars
———————– meta
———————– templates
../roles/
———dbserver/
…..
Ansible checks for “main.yml” in each subfolder inside roles, in above eg. tasks, files, vars, etc.
First.yml using roles:
--- # First.yml using role - hosts: group_name-1 user: test-user become: yes become_method: sudo gather_facts: yes connection: ssh roles: - webserver
../roles/webserver/tasks/main.yml
--- # tasks/main.yml - name: Install HTTPD Server package: pkg=httpd state=latest notify: Restart HTTPD
../roles/webserver/handlers/main.yml
--- # tasks/main.yml - name: Restart HTTPD service: name=httpd state=restarted enabled=yes
Now Just execute first.yml using steps given above.
Variables
We can define variables in playbook under “vars” and recall their values using {{…}}
There are 2 main type of variables system facts and user defined.
System facts we get from gathering facts and user defined variable has to declare in playbooks.
User Defined Variables
For eg. we can use variable in first.yml like below:
--- # first playbook using User defined variable - hosts: group_name-1 user: test-user become: yes become_method: sudo gather_facts: yes connection: ssh vars: pkg_name: httpd service_name: httpd tasks: - name: Install HTTPD Server package: pkg={{ pkg_name }} state=latest notify: Restart HTTPD handlers: - name: Restart HTTPD service: name={{ service_name }} state=restarted enabled=yes
If we are using roles then we can define all variables in ../roles/<role_name>/vars/main.yml
So in above example ../roles/<role_name>/vars/main.yml will look like:
--- # vars/main.yml pkg_name: httpd service_name: httpd
System Variables
We can use system variables for using system information like hostname, IPaddress, OS family, OS version etc. We get these values when enable “gather_facts” in playbook.
For eg. Suppose if we want to use FQDN of hosts in playbook, we can simply use {{ ansible_fqdn }} in our playbook.
We can use these variables in conditional statements as well. For eg. RedHat based system uses “httpd” as package name but Debian based system uses “apache2” as a package name. So if we want to install httpd on Redhat based systems and apache2 on debian based system then we can use conditional statement like below:
- name: Install HTTPD on CentOS yum: pkg= httpd state=latest when: ansible_os_family=="RedHat" - name: Install HTTPD on Ubuntu apt: pkg= apache2 state=latest when: ansible_os_family=="Debian"
Loops
We also can define loops in our playbooks. If we want to install multiple packages we can use below loop
- name: Install multiple packages package: pkg={{ item }} state=latest with_items: - httpd - php
until loop
Below example will verify httpd service status and it will wait till it gets “active (running)” in status output.
- name: Installing Apache Web Server yum: pkg=httpd state=latest - name: Verify Service Status shell: systemctl status httpd register: result until: result.stdout.find("active (running)") != 1 retries: 4 delay: 5 debug: var=result
Templates
Ansible uses jinja2 templates Jinja is nothing but extension of python.
Here is just an example of how we can use templates in Ansible Playbooks.
First.yml will install HTTPD server. Now we want to change default http port to 8989 instead of 80.
Here are the steps:
– copy default httpd.conf inside “templates” directory as httpd.conf.j2
– In ../roles/webserver/templates/httpd.conf.j2 just change “Listen 80” to “Listen {{ my_http_port }} “
– In ../roles/webserver/vars/main.yml
my_http_port: 8989
– In tasks/main.yml
--- # tasks/main.yml - name: Install HTTPD Server package: pkg=httpd state=latest notify: Restart HTTPD - name: Replace HTTPD.conf template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf owner=root group=root mode=0644 notify: Restart HTTPD
In this example template module will copy templates/httpd.conf.j2 to /etc/httpd/conf/httpd.conf and also replace {{ my_http_port }} variable to its value.
Ansible is very powerful, robust and yet easy tool used for Deployment Automation and configuration management across massive infrastructure.
You can drop me your queries related to Ansible on ngurjar[at]neeleshgurjar[dot]co[dot]in[dot]
Nice kbs sir
Really good document to start ansible
Thanks for the good article!!
Nice Doc Neelesh !!!