Ansible Deploy Multiple VM from Template VMware

0

Ansible is a tremendously powerful tool for automation across the board. When it comes to VMware, Ansible has a large array of modules that allow you to effectively interact with your vSphere environment. This includes managing VMware vSphere virtual machines. A task that Ansible can make much easier is cloning virtual machines from a template. You can also clone more than one virtual machine at a time. For me, this is extremely useful in labs and test environments where you may need to spin up multiple clones of servers or workstations for various purposes. You can essentially have a fully automated solution for cloning, powering on, provisioning, and even destroying VMs when needed. Let’s take a look at ansible deploy multiple vm from template VMware vSphere and see how this can be easily done.

Ansible modules for deploying multiple VM from template

With Ansible and VMware vSphere, there are a couple of different modules you can use for deploying your VMware vSphere VMs. These are the following:

  • vsphere_guest
  • vmware_guest

The vmware_guest module is the newer of the two modules and provides several more options for deploying your virtual machines. Additionally, I would steer to using vmware_guest since vspher_guest is removed in Ansible 2.9. Also, vsphere_guest uses the now deprecated Pysphere instead of VMware’s officially supported Python binding, Pyvmomi.

With vmware_guest Ansible module, you have the following requirements:

  • python >= 2.6
  • PyVmomi

If you are not running the PyVmomi module, you can easily install this using the following command:

pip install pyvmomi

Playbook to Deploy Multiple VM from Template

So in the following walk through and detail of how to deploy multple VMs from a VMware vSphere template, you will need the following:

I like to use a vars file for Ansible playbooks since you can simply update the vars file and potentially change a value across the board for a number of playbooks. This is much more efficient than hard coding your variables in the playbook itself.

However, there is nothing wrong with putting your variables in the playbook also. I just want to mention this as being something you may want to steer towards as you write more playbooks for efficiency.

Below, I have the playbook for creating a number of VMs from a template that is specified. Note the following highlights:

  • var_files – The var_files allows us to specify a variables file with the variables used in the playbook
  • template – Here we specify the template in VMware vSphere we are using as the source of the clone job
  • state – Do you want to power on the VMs after they are cloned into your inventory?
  • customization_spec – Specify the customization_spec. This allows you to fully customize out the VM, joining domain, setting network information, running ad-hoc commands, etc.
  • with_items – This is a loop in Ansible that allows us to run this playbook for the multiple items/servers we are specifying in the “servers” variable.
---

- name: Clone multiple VMs
  hosts: localhost 
  gather_facts: false
  vars_files: 
    multiple_vms.yml
  tasks: 
  - name: Clone multiple VMs from template
    local_action:
      module: vmware_guest
      hostname: "{{ vcenter_hostname }}"
      username: "{{ username }}"
      password: "{{ password }}"
      validate_certs: no      
      folder: "{{ folder }}"
      template: "{{ vmtemplate }}"
      name: "{{ item }}"
      cluster: "{{ vmcluster }}"
      datacenter: CloudLocal
      state: poweredon
      customization_spec: "{{ customization_spec }}"
    with_items: "{{ servers }}"

Now, let’s look at the variables file. This is the multiple_vms.yml file referenced in the playbook above. Note the following details:

  • vmtemplate – This is where we specify the template name
  • servers – This is a listing of the names of the VMs we want to create
---
vcenter_hostname: <FQDN or IP of your vCenter Server>
username: [email protected]
password: <your password>
folder: testansible
datastore: vsanDatastore
vmtemplate: Win2019clone
customization_spec: <your customization spec>
vmcluster: vsancluster
servers:
  - test19_01
  - test19_02

After kicking the playbook off, you will see the activity reflected in your vSphere Client.

Ansible-deploy-multiple-vm-from-template-tasks-kicking-off-in-vSphere Ansible Deploy Multiple VM from Template VMware

After running the playbook, my two VMs are successfully created (cloned from template), powered on, and customized according to the customization spec.

Newly-created-virtual-machine-using-Ansible-boots-and-is-customized Ansible Deploy Multiple VM from Template VMware
Newly created virtual machine using Ansible boots and is customized

Running Ansible template Synchronously or Asynchronously

I wanted to describe a slight difference in your playbook that will allow you to decide whether or not you want to run your Ansible playbooks synchronously or asynchronously.

Using the Ansible playbook example above to deploy mulple vms from template in VMware vSphere, the with_items entry allows you to run your playbook synchronously.

In other words, you will see in your vSphere Client, the first VM will clone. The next VM clone operation of your template will not start until the first clone operation has finished and so on.

What if you want to see all the clone operations kick off and begin simultaneously? You can do that with a different loop operator in Ansible. Note the difference below with:

  • loop
  • async
  • poll
---

- name: Clone multiple VMs
  hosts: localhost 
  gather_facts: false
  vars_files: 
    multiple_vms.yml
  tasks: 
  - name: Clone multiple VMs from template
    local_action:
      module: vmware_guest
      hostname: "{{ vcenter_hostname }}"
      username: "{{ username }}"
      password: "{{ password }}"
      validate_certs: no      
      folder: "{{ folder }}"
      template: "{{ vmtemplate }}"
      name: "{{ item }}"
      cluster: "{{ vmcluster }}"
      datacenter: CloudLocal
      state: poweredon
      customization_spec: "{{ customization_spec }}"
    loop: "{{ servers }}"
    async: 60
    poll: 0

By adding these instead of with_items, you will see Ansible simply blast through kicking off the clone operation and the playbook will finish before the clone is completed. This is a “fire and done” method.

You can adjust the async and poll intervals to time out kicking off one clone operation and waiting for a minute or so and then kicking the other off as well. You could do that with something like:

    loop: "{{ servers }}"
    async: 60
    poll: 10

This will make Ansible poll status every 10 seconds and the next clone operation will kick off 60 seconds later. You can read about the loop, async, and poll operators in greater detail here:

A quick note about running synchronously and asynchronously. You may not get expected results for operations such as state which defines the power On state of the VM. If you set the playbook to fire and done, it will simply kick off the clone operation and will quit. You won’t see any errors for the “state” parameter, however, it won’t power on your virtual machine.

So, you need to keep this in mind when kicking off operations in mass parallel instead of as a serial operation.

Final Words

Ansible is a great tool to automate VMware vSphere and provides a powerful way to interact with your vSphere environment. You can easily and simply create playbooks to create multiple virtual machines either from scratch or by using a preexisting template.

This can allow you to forego many manual tasks in the vSphere Client to provision a VM, power it on, and customize it.

StarWind VSAN