Ansible Handlers Explained Real-World Use Cases & Examples?

Introduction

Welcome to another ansible blog post! I am Rahul, and today, we'll dive deep into Ansible Handlers. Before we jump straight into the demo, let's lay a solid foundation by understanding the 'what' and 'when' of Ansible Handlers.


Table of Content

  1. What Are Ansible Handlers?
  2. Setting Up the Ansible Handler
  3. Setting up the Ansible task
  4. Multiple Ansible Handlers using listen keyword
  5. Ansible Handler order
  6. Conclusion & Key Takeaways

1. What Are Ansible Handlers?

Imagine you're managing a website and wish to update its content. You employ an Ansible Playbook to copy the refreshed HTML file onto the server.

But there's a catch. Every time you update this HTML file on your application server, you must restart the entire server to see these changes on your site.

How can you streamline this process? - The answer is very simple using the Ansible Handlers.

Ansible hosts file containing host entry

With Ansible Handlers, you can:

  1. Copy the updated HTML content onto your application server.
  2. Automatically restart the server once the content is updated.


2. Setting Up the Ansible Handler

The aim of the Ansible handler for this blog post is to restart the nginx server. So lets create the ansible playbook which has a handler responsible for restarting the nginx server.

Here is the GitHub Project Link - Ansible Handlers

 1---
 2- name: Example Ansible playbook for Handlers
 3  hosts: all
 4  become: yes
 5  remote_user: ubuntu
 6  roles:
 7    - handlers
 8  
 9  # Ansible Handler: This will restart the Nginx server
10  handlers:
11    - name: Restart Nginx
12      service:
13        name: nginx
14        state: restarted

3. Setting up the Ansible task

In the previous step we have already define the handler now let's create tasks for the following -

  1. Installing the Nginx Application server
  2. Updating the Website Content
  3. Calling the Ansible handlers

3.1. Installing the Nginx Application Server:

The initial task installs the Nginx server.

1---
2# Step-1 : Install Nginx
3- name: Update apt cache and install Nginx
4  apt:
5    name: nginx
6    state: latest
7    update_cache: yes

3.2. Updating Website Content:

The playbook then copies the HTML file (which you want to update) to the application server.

 1---
 2# Step-1 : Install Nginx
 3- name: Update apt cache and install Nginx
 4  apt:
 5    name: nginx
 6    state: latest
 7    update_cache: yes
 8
 9# Step-2: Copy index.html
10- name: index.html copy
11  template: src=index.html dest=/usr/share/nginx/html/index.html

3.3. Calling the Ansible handlers:

The key here is the notify attribute. After copying the content, I've set it to notify a task named 'Restart nginx'. This is crucial since it informs Ansible about the subsequent task once the content update is complete.

 1# Step-1 : Install Nginx
 2- name: Update apt cache and install Nginx
 3  apt:
 4    name: nginx
 5    state: latest
 6    update_cache: yes
 7
 8# Step-2: Copy index.html
 9- name: index.html copy
10  template: src=index.html dest=/usr/share/nginx/html/index.html
11  
12## Step-3: Update the content on the website and restart server
13- name: updated.html copy
14  template: src=updated.html dest=/usr/share/nginx/html/index.html
15  notify:
16    - Restart Nginx

4. Multiple Ansible Handlers using listen keyword

If you've been dabbling with Ansible for automation, you know how powerful and flexible it can be. Today, I want to share a neat trick that's often overlooked but incredibly handy: using the listen keyword to trigger multiple handlers with a single task.

Imagine you're running a web server and a cache service. Whenever you update the web server's configuration, both the web server and the cache service need to restart.

Here's how Ansible makes this seamless:

1---
2- name: Ansible multiple handler 
3  hosts: webservers
4  tasks:
5    - name: Ensure the web server configuration is updated
6      copy:
7        src: /path/to/your/config.conf
8        dest: /destination/on/server/config.conf
9        notify: "Restart Necessary Services"

Handlers Responding to the Task:

 1handlers:
 2    - name: Gracefully restart the web server
 3      service:
 4        name: webserver
 5        state: restarted
 6      listen: "Restart Necessary Services"
 7
 8    - name: And, don't forget the cache service!
 9      service:
10        name: cacheservice
11        state: restarted
12      listen: "Restart Necessary Services"

Here's the magic: When the configuration update task runs, it sends out a "shout" – in the form of a notify. Every handler that's "listening" to this shout gets activated. Thus, both our web server and cache service restart gracefully. And that's done using just one notify!

Isn't that elegant? With Ansible's listen keyword, managing interrelated actions becomes a piece of cake. I hope this tip helps you streamline your automation tasks even further. Keep automating, and until next time, happy coding!


5. Ansible Handler order

In Ansible, handler order is not guaranteed by default. This means if you have multiple handlers being notified by tasks, they might not run in the sequence you expect.

However, there are methods to ensure handlers run in a specific order, and one of the most common ways is by using listen.

Let's take a scenario where, after deploying an application, you need to:

  1. Clear the cache.
  2. Restart the application.

You want to make sure that clearing the cache always happens before restarting the application.

Here's how you can achieve this:

Tasks in Your Playbook:

 1---
 2- hosts: app_servers
 3  tasks:
 4    - name: Deploy the application
 5      copy:
 6        src: /path/to/app/
 7        dest: /destination/on/server/
 8      notify:
 9        - "Clear Cache"     # Execution Order 1
10        - "Restart App"     # Execution Order 2

Handlers:

 1handlers:
 2  - name: handler_clear_cache
 3    command: /path/to/clear_cache_script.sh
 4    listen: "Clear Cache"
 5
 6  - name: handler_restart_app
 7    service:
 8      name: my_app_service
 9      state: restarted
10    listen: "Restart App"

Here's what happens:

  1. The "Deploy the application" task notifies two handlers.
  2. The listen keyword ensures that the "Clear Cache" handler (handler_clear_cache) runs before the "Restart App" handler (handler_restart_app), because they were listed in that order in the notify section.

This setup provides a clear mechanism to control the sequence/order of handlers, making your Ansible playbook more predictable and reliable.


6. Conclusion & Key Takeaways

Ansible Handlers offer a dynamic way to automate tasks that are dependent on others. In our example, updating a file triggered a server restart. However, the application of Ansible Handlers isn't confined to this.

You can send emails, initiate patches, and much more, all based on specific triggers.

Today, we've only scratched the surface. The potential applications of Ansible Handlers in diverse projects are vast. Do you have similar dependencies in your endeavors? If yes, then Ansible Handlers might just be the tool you need.

Posts in this Series