Optimizing Ansible Execution: Asynchronous Modes and Performance Tuning
Command-Line Options for Asynchronous Execution
-B SECONDSor--background SECONDS: Run tasks asynchronously, failing after specified seconds (default: N/A)-P POLL_INTERVALor--poll POLL_INTERVAL: Set poll interval when using-B(default: 15 seconds)-f FORKSor--forks FORKS: Specify number of parallel processes (default: 5)
Analyzing Execution Flow with Verbose Output
Use ansible -vvv to inspect task execution. Below is a simplified trace of starting httpd on host 192.168.100.61:
# Configuration loading and handler execution
Using /etc/ansible/ansible.cfg
META: ran handlers
# First task: Gather facts via setup module
Using module: /usr/lib/python2.7/site-packages/ansible/modules/system/setup.py
# Establish SSH connection and retrieve home directory
<192.168.100.61> ESTABLISH SSH CONNECTION
<192.168.100.61> SSH: EXEC ssh ...
<192.168.100.61> (0, '/root\n', '')
# Create remote temporary directory
<192.168.100.61> ESTABLISH SSH CONNECTION
<192.168.100.61> SSH: EXEC ssh ... 'mkdir -p ...'
<192.168.100.61> (0, 'ansible-tmp-...', '')
# Transfer task file via SFTP
<192.168.100.61> PUT /tmp/tmpY5vJGX TO /root/.ansible/tmp/.../setup.py
<192.168.100.61> (0, 'sftp> put ...', '')
# Set execute permissions
<192.168.100.61> ESTABLISH SSH CONNECTION
<192.168.100.61> SSH: EXEC ssh ... 'chmod u+x ...'
<192.168.100.61> (0, '', '')
# Execute task and clean up
<192.168.100.61> ESTABLISH SSH CONNECTION
<192.168.100.61> SSH: EXEC ssh ... '/usr/bin/python ...; rm -rf ...'
<192.168.100.61> (0, '\r\n{...}', 'Connection closed.')
# Second task: Service management via service module
Using module: /usr/lib/python2.7/site-packages/ansible/modules/system/service.py
... (similar connection/task flow) ...
Execution Pattern Summary
- Load configuration and inventory data
- Execute initial fact-gathering task:
- Establish SSH connection
- Create/transfer temporary module file
- Execute module and return data
- Execute primary tasks (same connection pattern as step 2)
- Proceed to subsequent tasks
In multi-host executions:
- Tasks run in parallel across hosts (number controlled by
-f) - Default synchronous mode: Ansible occupies shell until all hosts complete all tasks
- Asynchronous mode (
-B): Tasks run in background with periodic status checks
Asynchronous Execution Details
- Without polling (
-P 0): Tasks fire-and-forget, shell returns immediately - With polling (
-P >0): Shell occupied until all background tasks complete
Example async command:
ansible servers -B200 -P 0 -m yum -a "name=dos2unix" -o -f 6
Output:
host1 | SUCCESS => {"ansible_job_id": "...", ...}
host2 | SUCCESS => {"ansible_job_id": "...", ...}
Performance Comparison Examples
# Synchronous (~10s)
ansible group -m command -a "sleep 5" -o
# Async with 5 forks, poll=1 (~10s)
ansible group -B200 -P 1 -m command -a "sleep 5" -o -f 5
# Async with 6 forks, poll=1 (~5-6s)
ansible group -B200 -P 1 -m command -a "sleep 5" -o -f 6
# Async with 5 forks, poll=10 (~20s)
ansible group -B200 -P 10 -m command -a "sleep 5" -o -f 5
Use Cases for Async Mode
Recommended:
- Long-running tasks risking SSH timeout
- No dependent tasks
- Require immediate shell return
Not recommended:
- Tasks with dependencies
- Resource-locking operations (e.g., package managers)
Handling Async Dependencies
- name: Install package asynchronously
yum:
name: nginx
state: installed
async: 1000
poll: 0
register: install_task
- name: Verify installation completion
async_status:
jid: "{{ install_task.ansible_job_id }}"
register: task_result
until: task_result.finished
retries: 30
Accelerating Execution with -t
Store results in directory for faster subsequent runs:
time ansible group -B200 -P 0 -m yum -a "name=dos2unix" -o -f 6 -t /tmp/results
Subsequent executions show improved speed even without -t.
Optimization Techniques
1. SSH Persistent Connections
Add to ansible.cfg:
[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=5d
Requirements:
- OpenSSH ≥5.6 on control node
- Creates persistent sockets in
~/.ansible/cp/
2. Pipelining
Enable in ansible.cfg:
[defaults]
pipelining = True
Requirements on managed nodes:
- Disable
requirettyin/etc/sudoers
3. Execution Strategy
Use free strategy for host-level parallelism:
- hosts: all
strategy: free
tasks:
- ...
4. Fact Caching
Configure in ansible.cfg:
[defaults]
gathering = smart
fact_caching_timeout = 86400
fact_caching = jsonfile
fact_caching_connection = /path/to/cache
View cached facts:
cat /path/to/cache/hostname | python -m json.tool