How to handle long-running tasks in Ansible/ Ansible Asynchronous Actions and Polling
By default, Ansible runs tasks synchronously holding the connections to the remote node open until the action is completed. This means within a playbook, each task blocks the next task by default, meaning the subsequent task will not run until the current task completes.
This behavior can create challenges. For example, a task may take longer to complete than the SSH session allows for, causing a timeout or you want a long-running process to execute in the background while you perform other tasks concurrently.
Asynchronous mode provides the functionality to control how long-running tasks execute.
Asynchronous Mode
Asynchronous mode allows us to control the playbook execution flow by defining how long-running tasks complete their execution.
To enable Asynchronous mode within the playbook use parameters such as async and poll
async - async indicates the total time to complete the task or its maximum runtime of the task. The task will timeout if it exceeds the limit of this parameter
poll - poll indicates to Ansible, how often to poll to check if the command has been completed or how frequently you would like to poll for status, with the poll we keep checking whether the job is completed or not. The default value for the poll is 10 sec.
# async and poll example playbook
---
- hosts: centos
become: yes
tasks:
- name: Simulate the long-running operation
command: /bin/sleep 15
async: 45 # How long to run?
poll: 5 # How frequently to check?
Avoid connection timeout: poll > 0
- If we want to set a longer timeout limit for a certain task in your playbook use async with a poll set to a positive value. Ansible will block the next task in your playbook, waiting until the async task is either complete, fails, or timeout. However, the task will only time out if it exceeds the time limit set with the async parameter.
# Async and poll example playbook
---
- name: sleep and create a user
hosts: centos
become: yes
tasks:
- name: sleep for 15 Seconds
command: /bin/sleep 15
async: 45 # total time allowed to complete the sleep task
poll: 5
register: sleeping_node
- name: task-2 to create a test user
user:
name: CJ
state: present
Run task concurrently: poll = 0
- If we want to run multiple tasks in a playbook concurrently, use async with a poll set to 0. When we set the poll to 0 Ansible starts the task and immediately moves on to the next task without waiting for a result. Each task runs until it either completes, fails, or time-outs. The playbook run ends without checking back on async tasks.
# Playbook with poll = 0, concurrent running tasks
---
- name: sleep and create a user
hosts: centos
become: yes
tasks:
- name: sleep for 60 Seconds
command: /bin/sleep 60
async: 80
poll: 0
register: sleeping_node
- name: task-2 to create a test user
user:
name: John
state: present
Asynchronous Ad-hoc tasks
We can execute the long-running operation in the background with ad-hoc tasks.
To execute long-running operations synchronously in the background with a timeout (-B) of 3600 seconds and without polling (-P)
ansible centos -B 3600 -P 0 -a "<long_running_operation>"
I hope you enjoyed this article, if you have any questions, comments, or feedback or if I made a mistake feel free to comment down below.