Easy things you can do to speed up ansible
Maybe you have been using Ansible for some time and your playbooks have grown big enough to take a lot of time? Or maybe you are just trying it out and it feels already too slow for your taste? Whatever the reason, you may be wondering if there are quick changes you can do to speed things up a bit, so here are small modifications you can do right now to reclaim a bit of your time.
Connection parallelism
If you are targeting more than one server with your playbook, the very first thing to do is to make sure Ansible connects to multiples of them at the same time. For that, you are going to set how many forks
are going to run concurrently.
You can either configure that in your ansible.cfg
file:
|
|
Or pass the --forks 10
option to the ansible-playbook
command.
Or even set it via the environment: ANSIBLE_FORKS=10
.
Whatever solution you choose, the point is to run Ansible on as many servers as possible at the same time. The only limit is your control host performance, the more connection running concurrently there is, the more resource is going to be consumed.
And if it happens that you really need to run a part of your playbook in a serial fashion, then you can use the serial
keyword for that. Like this:
|
|
Limit Fact Gathering to a minimum
By default, Ansible will gather facts about all the machines you are deploying to at the beginning of each playbook. Even if you don’t really use those facts afterward.
If you know your play don’t use the fact automatically collected by Ansible, you can disable it on a playbook by playbook basis:
|
|
Alternatively, you can reverse the default behaviour so that you need to explicitly ask to gather facts in your playbook. This can be achieved by adding the following in your ansible.cfg
file:
|
|
Then when you need those facts you will need to explicitly ask for them in your playbook:
|
|
Finally, you may not know if you really need those facts, or you really don’t plan to go back to check all your playbooks and roles to see if it is the case. If that’s you, then use the smart
option in your ansible.cfg
:
|
|
Now Ansible will only gather the facts the first time it connects to a new host during the run, and not anymore during that run.
Activate SSH Pipelining
The pipelining option reduce the number of SSH operations Ansible does in order to execute a task on the target host. Activating this option can significantly improve the runtime performance of your playbook.
You can activate it in your ansible.cfg
with:
|
|
And, if everything work, that’s perfect, enjoy 👍.
But maybe after turning that on you get some weird sudo: no tty present
error when you run your playbook? If so, you should modify the sudoers
file on your targets. Add the following playbook to be run before anything else:
⚠️ This play modifies the /etc/sudoers
file, which is critical for sudo
to work. Breaking this file could prevent you from getting root access on your host. Run this on a test host before running it in your production environment to ensure it works ⚠️
|
|
This should ensure you won’t see the previous error. Some consider this requiretty
a security mechanism, but other don’t.
Limiting Fact Gathering Even More
OK with all that you should have had a speed boost already. But maybe running one fact gathering each time you are running your playbook is already too much for you, and your facts don’t really change much anyway.
This is when caching the facts comes in. You can configure Ansible to run the fact gathering and then cache them for a day, 12 hours, a week, whatever match your use case.
Let’s modify your ansible.cfg
again to activate caching (only work with smart
or explicit
fact gathering):
|
|
And now your facts are cached for 1 day. Nice.
Here we are using a JSON file as cache, but there are other fancy plugins, like using a yaml file, or maybe redis? Check the cache plugins documentation for more examples.
Finally
And if after all that running the playbook is still too slow, you can gather more metrics about your playbook by using two callback plugins:
- the profile_tasks plugin
- and the timer plugin
A callback plugin is a plugin that changes how Ansible respond to some internal events, and control the output of the running command.
Those can be activated by adding the following in your ansible.cfg
:
|
|
As you may guess from the name, the profile_tasks
plugin adds timing data to each task, while the timer
one shows the runtime of the full play.
And if even after all those changes, you still feel that your playbook is slow, then you may want to take a look at Mitogen, which basically swap the Ansible engine for a new one that reduces execution time drastically. But you’ll have to explore that by yourself 😉
Did you enjoy this article? Don't want to miss any new posts and get exclusive content? Then hop into my newsletter :)
You can also contact me directly via email: m [-at-] mayeu [-dot-] me