Ansible: Boost Task Execution Speed
Tags: ansible, devops
Published: 2020-09-21 05:06:53

Running Ansible tasks takes some time to complete. You can greatly reduce this time by using SSH multiplexing and pipelining, and by stopping or caching the fact gathering steps. Let’s discuss these optimizations in detail.

_This article originally appeared at [my blog](https://admantium.com/blog/a02_speed_up_task_execution/)_.

## Improve SSH

When a playbook is executed, Ansible opens and closes three SSH-connections:

1. Gather facts
2. Copy zipped playbook code to the node
3. Execute the playbook code

Enter the following code in the _ansible.cfg_ to do all these steps with one SSH connection:

```ini
[ssh_config]
pipelining = true
```

The second option is to use SSH multiplexing: You open one outgoing TCP connection from which different SSH-connection to other nodes are formed. Ansible uses SSH multiplexing by [default](https://docs.ansible.com/ansible/latest/user_guide/connection_details.html), but you may need to make changes to your SSH config, see this [multiplexing cookbook](https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing).

## Run more tasks parallel

You can increase how many concurrent nodes your ansible playbooks operate on. Increase the threshold of nodes with this:

```ini
[defaults]
forks = 20
```

You can also run tasks asynchronously, which means Ansible does not wait for a task to finish before the next one. This can be helpful if there is a task which lasts for some time, but is not required for subsequent tasks. Setup and usage of asynchronous task requires some thoughts, see the [official documentation](https://docs.ansible.com/ansible/latest/user_guide/playbooks_async.html).

## Use the “free” strategy

When Ansible executes a task on several hosts, it will wait until each task is finished on all hosts before executing the next one. With the following setting, tasks will be executed on the hosts as soon as the host is finished with the current task.

```ini
[defaults]
strategy = free
```

## Disable or cache fact gathering

Fact gathering for each node is a time-consuming operation that takes place every time before tasks are executed. If you don’t need the facts at all, you can disable fact gathering in playbooks like shown:

```yaml
- name: playbook
  gather_facts: false
```

To disable it globally, write this in your _ansible.cfg_ :

```ini
[defaults]
gathering = explicit
```

If you need the facts, but are sure that they don’t change too often, you can cache them. To cache facts for 24 hours in a local JSON file, write this in your _ansible.cfg_.

```ini
[defaults]
gathering = smart
fact_caching_timeout = 86400
fact_caching = jsonfile
fact_caching_connection = ./ansible_fact_cache
```

You can also use [other caching plugins](https://docs.ansible.com/ansible/latest/plugins/cache.html#plugin-list) like MongoDb, Redis or Memched.

## Conclusion

In this article, we learned how to improve the execution of Ansible tasks with four options: Reducing the number of SSH connections needed to execute tasks on a host, start task execution on more hosts, and to streamline the task execution. You achieve this by adding this to your _ansible.cfg_.

```ini
[defaults]
strategy = free
forks = 20

[ssh_config]
pipelining = true
```

And if you want to skip the time-consuming fact gathering step, then turn on smart gathering:

```ini
[defaults]
gathering = smart
fact_caching_timeout = 86400
fact_caching = jsonfile
fact_caching_connection = ./ansible_fact_cache
```

Have fun with these improvements.