Ansible

Ansible Async

Ansible is a free and open-source automation tool for DevOps, system administration, and more.

However, unlike other tools that aim to provide automated tasks, Ansible aims to automate these tasks but also perform them efficiently.

As such, Ansible provides a feature called asynchronous tasks or async tasks that allow Ansible not to wait for a task to complete. Instead, it moves on to other tasks, optimizing the run-time of a given playbook.

How Does It Work?

By default, when we run a task in Ansible using the ad hoc commands or is defined in a given playbook, Ansible executes these tasks synchronously where the connection to the remote host is held open until the task is complete.

This is a blocking mechanism as it means that each task that is defined in the playbook does not run unless the previous ones are complete. This can create challenges. For example, you may have a task that takes longer to complete than the SSH session allows which can cause a timeout. Similarly, you may have a long-running process that you can allow to run in the background while the playbook performs other tasks concurrently.

This is where the Ansible async functionality comes into play. Using Ansible async, we can control how long-running tasks need to execute.

In this tutorial, we will dive deep into the world of Ansible async and look at how to run the tasks asynchronously, poll for their status, and handle the long-running operations.

Basic Async in Ansible

In the simplest form, Ansible allows us to define the async tasks in a playbook using the async and poll parameters.

Async – The async parameter defines the duration in seconds that a given task should be allowed to run. Once the time has elapsed, Ansible kills the task regardless of the status.

Poll – The second is the poll parameter. This defines the interval in seconds that Ansible should check whether the task is complete. Setting the value of this parameter to 0 means that Ansible will not wait for the task to complete. Instead, Ansible executes the other tasks immediately.

Ansible Async Ad Hoc Tasks

The first step is learning to execute the ad hoc commands in an async manner. Ansible allows us to use the async and poll parameters in an ad hoc command as follows:

For example, suppose we wish to restart a service on all web servers, but we don’t want to wait for them all to complete synchronously:

$ ansible webservers -m service -a "name=httpd state=restarted" -B 300 -P 0

In this example, the -B parameter specifies the async value with a duration of 300 seconds. In this case, if the servers are not restarted by 5 minutes, Ansible kills the process immediately.

-P, on the other hand, specifies the poll interval to 0 seconds. Hence, Ansible starts the task and immediately moves on without waiting for its completion.

To later check the results of an asynchronous ad hoc command, we can use the “async_status” module.

ansible webservers -m async_status -a "jid=<your_job_id>"

Ensure to note the ansible_job_id from the async commands.

Ansible Async Playbooks

As defined, we can use the async and poll parameters to define an async task within a given playbook. An example is as follows:

---
- hosts: all
tasks:
- name: Execute a long-running command
command: /bin/htop
async: 3600
poll: 0

In this case, the previously-defined task runs for a maximum of 3600 seconds (1 hour), but Ansible moves on immediately after starting the task without waiting for it to complete.

Polling with Async

While we may not want to wait indefinitely for a long-running task, we may still need to know its status and perhaps take appropriate action if one is required. This is where the poll comes into play.

If we set the value of the poll parameter to a value that is greater than 0, Ansible checks at that defined interval on the task’s status.

For example: In the following illustration, we have a task that runs for a maximum of 600 seconds, but Ansible checks on its status every 60 seconds.

---
- hosts: all
tasks:
- name: Execute a long-running command
command: /bin/command
async: 600
poll: 60

Handling the Task Results

As you can guess, we can store the result of an async task and then reference it later. This is especially useful if we need to perform another task based on the result of the async task.

Consider the example playbook that is demonstrated in the following:

---
- hosts: all
tasks:
- name: Start a long-running command
command: /bin/command
async: 600
poll: 0
register: result

- name: Wait for the long-running command to complete
async_status:
jid: "{{ result.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 60

In the previous playbook example, we use the “async_status” module to check the status of our asynchronous task. The loop retries 60 times until the “job_result.finished” is true.

Conclusion

We learned how to work with the Ansible async features to run the ad hoc commands or playbook tasks asynchronously, reducing the block time of long-running tasks.

About the author

John Otieno

My name is John and am a fellow geek like you. I am passionate about all things computers from Hardware, Operating systems to Programming. My dream is to share my knowledge with the world and help out fellow geeks. Follow my content by subscribing to LinuxHint mailing list