Pages

Monday, February 1, 2016

Ansible – Advanced Playbook


In the previous article we have seen how we can use playbooks to execute a series of tasks on the remote machine. In this article we will see another basic example of using playbooks. We will install Apache Http Server on the remote Machine using playbooks.

Now lets create a Ansible directory which we will use for our article. The next main step is to tell Ansible about the remote machines that we need to talk. For this we need to create a Ansible hosts file also called as inventory file. This file contains list of Ip address that are defined in groups that we can use them while running Ansible commands. By default the location of this file is /etc/Ansible/hosts. This is a global file that we can use but Ansible lets you create your hosts file and pass that to the Ansible command.

When we run the Ansible command, the command will always check for the Ansible.cfg file in the local directory that it is being run. If the file is found it will override the global configuration with the local values.

Once the directory is created, create a ansible.cfg file with the values as,
[root@vx111a ansible]# cat ansible.cfg
[defaults]
hostfile=hosts

We have defined the hostfile configuration option with the value of the hosts, within the defaults group.

Now lets define the hosts file like this,
[root@vx111a ansible]# cat hosts
[dev]
172.16.202.96 ansible_ssh_user=root

In the host file we have defined a “dev” group with an IP address and the user with which we need to login to that machine and perform actions on.

The next step is to create a playbook where we will have all the necessary instructions on the tasks that need to execute on the remote machine. Here is the playbook for the article,

[root@vx111a ansible]# cat apache.yml
---
- hosts: dev
  user: root
  sudo: no
  tasks:
   - name: Install Apache
     yum: pkg=httpd state=latest
     notify:
     - restart apache
   - name: ensure apache is running
     service: name=httpd state=started 
  handlers:
   - name: restart apache
     service: name=httpd state=restarted

[root@vx111a ansible]# ansible-playbook apache.yml

PLAY [dev] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [172.16.202.96]

TASK: [Install Apache] ********************************************************
changed: [172.16.202.96]

TASK: [ensure apache is running] **********************************************
changed: [172.16.202.96]

NOTIFIED: [restart apache] ****************************************************
changed: [172.16.202.96]

PLAY RECAP ********************************************************************
172.16.202.96              : ok=4    changed=3    unreachable=0    failed=0  

In the above playbook,

hosts: dev
The Host file is the important part in the Ansible working. This is mandatory and every playbook should have it. It tells Ansible where to run the listed tasks. When provided with a host group, Ansible will take the host group from the playbook and will try looking for it in an inventory file that we already defined (in hosts file).

user: root
This will tell Ansible to use the Root User rather than any other User.

sudo: no
We are making Ansible not to do a Sudo access for running the tasks.

Now comes the task details which are defined as

  tasks:
   - name: Install Apache
     yum: pkg=httpd state=latest
     notify:
     - restart apache
   - name: ensure apache is running
     service: name=httpd state=started 
  handlers:
   - name: restart apache
     service: name=httpd state=restarted

In the above playbook,

- name: Install Apache
Every Task will have a name parameter. The name parameter represents what the task is doing and is present only to improve readability. This parameter is optional.

yum: pkg=httpd state=latest
The next line is about installing the Package httpd. For this we will use the YUM module available in Ansible. Ansible does not provide a separate package module which can identify the operating system running on the remote machine and use the correct tool for installing the package. We need to use the specific modules (like YUM , APT) for installing packages on the remote machine.

In the yum module's case, the state parameter has the latest value and it indicates that the httpd latest package should be installed. The command to execute more or less translates to yum install httpd.

notify:
   - restart apache
The ‘notify’ actions are triggered at the end of each block of tasks in a playbook, and will only be triggered once even if notified by multiple different tasks. For instance, multiple resources may indicate that apache needs to be restarted because they have changed a config file, but apache will only be bounced once to avoid unnecessary restarts. The things listed in the notify section of a task are called handlers

handlers:
   - name: restart apache
     service: name=httpd state=restarted

Handlers are list of tasks much similar from the regular tasks. Handlers are what notifiers notify. If nothing notifies a handler, it will not run. Regardless of how many things notify a handler, it will run only once, after all of the tasks complete in a particular play. In the above handler we have defined one action which is to restart the Httpd Service.

Now lets run the playbook using the Ansible-playbook command as,
[root@vx111a ansible]# ansible-playbook apache.yml

PLAY [dev] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [172.16.202.96]

TASK: [Install Apache] ********************************************************
changed: [172.16.202.96]

TASK: [ensure apache is running] **********************************************
changed: [172.16.202.96]

NOTIFIED: [restart apache] ****************************************************
changed: [172.16.202.96]

PLAY RECAP ********************************************************************
172.16.202.96              : ok=4    changed=3    unreachable=0    failed=0  


From the above output we can see how the tasks defined ran on the remote machine. There are certain things to understand in this.

GATHERING FACTS ***************************************************************
ok: [172.16.202.96]

The first default task when any playbook is run is gathering Facts task. The aim of this task is to gather useful metadata about the machine in the form of variable which are then used as a part of the task that follow in the playbook. The data include IP address , architecture of the system , host name etc.

One another things to understand is the last step which is a “PLAY RECAP” step

PLAY RECAP ********************************************************************
172.16.202.96              : ok=4    changed=3    unreachable=0    failed=0  

As we already know that the playbook does not give us any output. The OK=4 in the playbook will give us the necessary details of the tasks that are run on the remote machines and their status. In the above, 4 tasks were run and they were all success.  The Changed=3 tells us that the System state was changed 3 times during the execution of the playbook.

Ansible also provides us with other options that can help us in running Ansible playbooks.

List-tasks
While running Ansible, there are cases where we need to check the tasks that we defined  
The playbook. We can use

[root@vx111a ansible]# ansible-playbook apache.yml --list-tasks
playbook: apache.yml

  play #1 (dev):                                                  TAGS: []
    Install Apache                                                 TAGS: []
    ensure apache is running                                  TAGS: []

Start-at-task
There are cases sometimes where we need to start a particular task on the remote machine or re-run a task, for this we can use

[root@vx111a ansible]# ansible-playbook apache.yml --start-at-task="restart apache"

PLAY [dev] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [172.16.202.96]

PLAY RECAP ********************************************************************
172.16.202.96              : ok=1    changed=0    unreachable=0    failed=0  

In the above case, I am re-running the task “restart apache” on the hosts defined.

Step
Ansible also provides us with an option to ask for permission before running a task on the remote machine using the –step like

[root@vx111a ansible]# ansible-playbook apache.yml --step

PLAY [dev] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [172.16.202.96]
Perform task: Install Apache (y/n/c): y

Perform task: Install Apache (y/n/c):  ****************************************
ok: [172.16.202.96]
Perform task: ensure apache is running (y/n/c): y

Perform task: ensure apache is running (y/n/c):  ******************************
ok: [172.16.202.96]

PLAY RECAP ********************************************************************
172.16.202.96              : ok=3    changed=0    unreachable=0    failed=0  

If you check the above output we can see that for every task to run Ansible will ask a confirmation before doing that.


That’s about Playbook. We will see more details in the next articles.

4 comments :

  1. Hi Jagdesh
    I think This is the best one tutorial blog.I request you to please add
    more Ansible playbook example and also add Ansible with Docker
    details
    Thanks
    manoj.himt@gmail.com

    ReplyDelete
  2. I constantly spent my half an hour to read this web site's posts all
    the time along with a mug of coffee.

    ReplyDelete