Asynchronous VM deployment with Ansible

If you’ve ever run into a scenario where you need Ansible to execute tasks asynchronously, there is a trick to doing this. For my use case, I wanted to provision multiple VMs at the same time, without having to wait for each VM to be deployed synchronously.

The Challenge

For one or two VMs, it’s no big deal waiting for each VM to be deployed one-at-a-time, however, when we’re deploying many more VMs, it takes too long to wait for each VM to be deployed.

The Solution

For starters, let’s look at the regular task associated with deploying a VM.

As we can see above, the task deploys a VM to vCenter and has a bunch of variables listed. These variables are either loaded from a vars yaml file or passed in as extra-vars.

Now, if we have an array / collection of VM data, used to deploy, we can iterate that array and kick off the same task for every item in the array.

Naturally, this is typically done in a loop, as follows:

loop: "{{ vms_to_deploy }}"

And now, in order to ensure that we kick off each task and associated those tasks with a job, we use the following Ansible functionality:

async: 600
poll: 0

If you want to run multiple tasks in a playbook concurrently, use async with poll set to 0. When you set poll: 0, Ansible starts the task and immediately moves on to the next task without waiting for a result. Each async task runs until it either completes, fails or times out (runs longer than its async value). The playbook run ends without checking back on async tasks.
So, to include this logic in the tasks, the following YAML should help to convey the message:

Looking above, at lines 40-41, we include async: 600 and poll: 0.
Note that we are looping through a collection of objects called vmstodeploy.
Then, from line 46, we are monitoring the status of this job every 5 seconds (implied by delay: 5).
Of specific importance is line 50 - until: deployment _status.finished.

This means that Ansible will check the status of the job every 5 seconds, 100 times, and then either pass or fail.

Hopefully this helps - it helped me a great deal!