Tuesday, May 14, 2019

How to create an ansible playbook and roles

Ansible is an open source platform which helps to automate the configuration management , application deployment in complex IT environment which includes linux,windows based systems . Ansible is commonly known as infrastructure as a code. 

Designed for multi tier deployments Ansible models our IT infrastructure by designing how all our systems are inter related rather than just managing them  .It uses no agents and no additional custom security infrastructure, so it's easy to deploy - and most importantly, it uses a very simple language (YAML, in the form of Ansible Playbooks) that allow you to describe your automation jobs in a way that approaches plain English.

Ansible uses following components to work
  • Inventory file(s)
  • Group vars
  • Host vars
  • Playbooks
  • Roles
  • Tasks
Inventory files are the list of hosts which ansible trying to interact . The default location of the ansible  host file is /etc/ansible/hosts . Group vars and Host vars are the hosts specified in the inventory file. Roles are the ways of automatically loading certain variables and files and handlers as per the known file structure.

Ansible playbooks are the organised group of scripts that defines work for a server configuration managed by the ansible platform. Ansible plays are written by using yamal format.

Directory layout of ansible playbook 

Below is the basic directory layout of ansible playbook 

####################################################
production                # inventory file for production servers
staging                   # inventory file for staging environment

group_vars/
   group1                 # here we assign variables to particular groups
   group2                 # ""
host_vars/
   hostname1              # if systems need specific variables, put them here
   hostname2              # ""

library/                  # if any custom modules, put them here (optional)
filter_plugins/           # if any custom filter plugins, put them here (optional)

site.yml                  # master playbook
webservers.yml            # playbook for webserver tier
dbservers.yml             # playbook for dbserver tier

roles/
    common/               # this hierarchy represents a "role"
        tasks/            #
            main.yml      #
#########################################################

A sample playbook is given below (which we are not using any roles to split up.)


########################################################

# site.yml
---
- hosts: all    # The hosts which the playbook is going to interact #
  vars:
  remote_user: user  # User details which is used to execute this playbook#
  become: yes # Need sudo password for execution #

  tasks: # This task is used to install the ntp package from the yum repository #
  - name: Install ntp
    yum: name=ntp state=present
    tags: ntp

  - name: Configure ntp file # If we want to copy some pre configured file we need to use this session      with template #
    template: src=ntp.conf.j2 dest=/etc/ntp.conf
    tags: ntp
    notify: restart ntp

  - name: Start the ntp service # to start and enable the ntp service after the configuration #
    service: name=ntpd state=started enabled=yes
    tags: ntp

  - name: test to see if selinux is running   # check whether the selinux is enabled and disable it if it is      enabled#
    command: getenforce
    register: sestatus
    changed_when: false

  -hosts: web # This session will install the apache in web servers
  tasks:
  - name: Install httpd Package
    yum: name=httpd state=latest
  - name: Copy httpd configuration file
    copy: src=/data/httpd.original dest=/etc/httpd/conf/httpd.conf
  - name: Copy index.html file
    copy: src=/data/index.html dest=/var/www/html
    notify:
    - restart apache
  - name: Start and Enable httpd service
    service: name=httpd state=restarted enabled=yes
  handlers:
  - name: restart apache
    service: name=httpd state=restarted


- hosts: database   # This session will install the mysql package with below mentioned variables #
  vars:
    mysql_port: 3306
    dbname: somedb
    dbuser: someuser
    dbpass: somepass
  remote_user: user
  become: yes

    tasks:  # if we need to install multiple packages we can use the item method #
  - name: Install Mysql package
    yum: name={{ item }} state=installed
    with_items:
     - mysql-server
     - MySQL-python
     - libselinux-python
     - libsemanage-python

  - name: Configure SELinux to start mysql on any port
    seboolean: name=mysql_connect_any state=true persistent=yes
    when: sestatus.rc != 0

  - name: Create Mysql configuration file
    template: src=my.cnf.j2 dest=/etc/my.cnf
    notify:
    - restart mysql

  - name: Start Mysql Service
    service: name=mysqld state=started enabled=yes

  - name: insert iptables rule     #configure IP tables rule for mysql #
    lineinfile: dest=/etc/sysconfig/iptables state=present regexp="{{ mysql_port }}" insertafter="^:OUTPUT " line="-A INPUT -p tcp --dport {{ mysql_port }} -j ACCEPT"
    notify: restart iptables

  - name: Create Application Database
    mysql_db: name={{ dbname }} state=present

  - name: Create Application DB User
    mysql_user: name={{ dbuser }} password={{ dbpass }} priv=*.*:ALL host='%' state=present
#########################################################################

We can split the above playbook to short and structured way as below 

######################################################################

# site.yml
---
# This playbook deploys the whole application stack in this site.

- name: apply common configuration to all nodes
  hosts: all
  remote_user: user

  roles:
    - common

- name: configure and deploy the webservers and application code
  hosts: webservers
  remote_user: user

  roles:
    - web

- name: deploy MySQL and configure the databases
  hosts: dbservers
  remote_user: user

  roles:
    - db
#####################################################################

We can create the roles using the ansible galaxy command which will be installed along with the ansible.

#ansible-galaxy init web

This will create follwoing directories inside the ansible/role /web directory


  • files: This directory contains regular files that need to be transferred to the hosts you are configuring for this role. This may also include script files to run.
  • handlers: All handlers that were in your playbook previously can now be added into this directory.
  • meta: This directory can contain files that establish role dependencies. You can list roles that must be applied before the current role can work correctly.
  • templates: You can place all files that use variables to substitute information during creation in this directory.
  • tasks: This directory contains all of the tasks that would normally be in a playbook. These can reference files and templates contained in their respective directories without using a path.
  • vars: Variables for the roles can be specified in this directory and used in your configuration files.

structure of a role

Each folder will contain main.yml file with necessary information

├── README.md

├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
└── vars
└── main.yml

I will explain the web role with the yml file detail separately fro better understanding

Tasks directory : 

Edit the main.yml inside the task directory as below We can split the main task in to 3 files 

root@unixchips web]# cat tasks/main.yml
---
# tasks file for /etc/ansible/roles/apache
- import_tasks: install.yml
- import_tasks: configure.yml
- import_tasks: service.yml
***************************************** 
root@unixchips apache]# cat tasks/install.yml
---
- name: Install httpd Package
  yum: name=httpd state=latest
******************************************* 
[root@unixchips web]# cat tasks/configure.yml
---
- name: Copy httpd configuration file
  copy: src=files/httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: Copy index.html file
  copy: src=files/index.html dest=/var/www/html
  notify:
  - restart apache
**********************************************
[root@unixchips web]# cat tasks/service.yml
---
- name: Start and Enable httpd service
  service: name=httpd state=restarted enabled=yes

Files directory:

Copy the required files ( index.html and httpd.conf) to this directory

[root@unixchips web]# ll files/*
-rw-r--r-- 1 root root 11753 May  4 10:01 files/httpd.conf
-rw-r--r-- 1 root root    66    May  4 10:02 files/index.html
[root@unixchips web]# cat files/index.html
This is a homepage created by unixchips for ansible roles.
[root@unixchips web]#

Handlers directory:

The main.yml file in this directory contains the code to restart the apache whenever any change is executed 

[root@unixchips web]# cat handlers/main.yml
---
# handlers file for /etc/ansible/roles/apache
- name: restart apache
  service: name=httpd state=restarted

Meta directory :

Edit the main.yml in meta directory as below to update the author and other details 

root@unixchips web# cat meta/main.yml
galaxy_info:
  author:unixchips
  description: Apache Webserver Role
  company: unixchips
  # If the issue tracker for your role is not on github, uncomment the
  # next line and provide a value
  # issue_tracker_url: http://example.com/issue/tracker
  # Some suggested licenses:
  # - BSD (default)
  # - MIT
  # - GPLv2
  # - GPLv3
  # - Apache
  # - CC-BY
  license: license (GPLv2, CC-BY, etc)
  min_ansible_version: 1.2
  # If this a Container Enabled role, provide the minimum Ansible Container version.
------skipped

When we check the directory structure in detail we will bet the output as below using the tree command 

root@unixchips web]# tree
.
|-- README.md
|-- defaults
|   `-- main.yml
|-- files
|   |-- httpd.conf
|   `-- index.html
|-- handlers
|   `-- main.yml
|-- meta
|   `-- main.yml
|-- tasks
|   |-- configure.yml
|   |-- install.yml
|   |-- main.yml
|   `-- service.yml
|-- templates
|-- tests
|   |-- inventory
|   `-- test.yml
`-- vars
    `-- main.yml
8 directories, 13 files

Now we need to create the main playbook as below 

[root@unixchips web]# cat /etc/ansible/runsetup.yml
---
 - hosts: node2
   roles:
   - apache

If we run the playbook using the ansible command we will get the output as below 

root@unixchips web]# ansible-playbook /etc/ansible/runsetup.yml
PLAY [node2] ***************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************
ok: [node2]
TASK [apache : Install httpd Package] **************************************************************************
changed: [node2]
TASK [apache : Copy httpd configuration file] ******************************************************************
Changed: [node2]
TASK [apache : Copy index.html file] ***************************************************************************
changed: [node2]
TASK [apache : Start and Enable httpd service] *****************************************************************
changed: [node2]
RUNNING HANDLER [apache : restart apache] **********************************************************************
changed: [node2]
PLAY RECAP *****************************************************************************************************
node2                      : ok=6    changed=5    unreachable=0    failed=0


Login to the node and check the apache status 

root@node2 ~]# rpm -q httpd
httpd-2.4.6-67.el7.centos.6.x86_64
[root@node2 ~]# systemctl status httpd
httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled)
   Active: active (running) since Sat 2018-05-04 10:23:44 IST; 1min 58s ago
     Docs: man:httpd(8)
           man:apachectl(8)

We have succesfully installed the apache web server using ansible code. 

Thank you for the reading 




No comments:

Post a Comment