Deploy VMware Virtual machines with Ansible for lazy admins

Introduction

In Today’s guide, Let’s see how to Deploy VMware Virtual machines with ansible. I’m tired of creating virtual machines again and again for deploying Kubernetes clusters. Let’s automate the process by creating a single Ansible playbook.

We are about to use VMware_guest Ansible module to do the same. To start using it, we need to install Python SDK for the VMware vSphere API that allows you to manage ESX, ESXi, and vCenter.

Resolving Prerequisites

The required prerequisites for using vmware_guest are

  • Python 2.6 >
  • pyvmomi

These prerequisites need to be resolved on VCenter server. To install the pyvmomi we need pip.

root@vcenter [ ~ ]# easy_install-3.7 pip
Searching for pip
Reading https://pypi.org/simple/pip/
Downloading https://files.pythonhosted.org/packages/4e/5f/52839/pip-20.2.3-py2.py3-none-any.whl#sha256=0fc26
Best match: pip 20.2.3
Processing pip-20.2.3-py2.py3-none-any.whl
Installing pip-20.2.3-py2.py3-none-any.whl to /usr/lib/python3.7/site-packages
Adding pip 20.2.3 to easy-install.pth file
Installing pip script to /usr/bin
Installing pip3 script to /usr/bin
Installing pip3.8 script to /usr/bin

Installed /usr/lib/python3.7/site-packages/pip-20.2.3-py3.7.egg
Processing dependencies for pip
Finished processing dependencies for pip
root@vcenter [ ~ ]# 

Install pyvmomi on VCenter server using pip.

root@vcenter [ ~ ]# sudo pip install pyvmomi
Collecting pyvmomi
  Downloading pyvmomi-7.0.tar.gz (587 kB)
     |████████████████████████████████| 587 kB 7.4 MB/s 
Requirement already satisfied: requests>=2.3.0 in /usr/lib/python3.7/site-packages (from pyvmomi) (2.19.1)
Requirement already satisfied: six>=1.7.3 in /usr/lib/python3.7/site-packages (from pyvmomi) (1.11.0)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/lib/python3.7/site-packages (from requests>=2.3.0->pyvmomi) (3.0.4)
Requirement already satisfied: idna<2.8,>=2.5 in /usr/lib/python3.7/site-packages (from requests>=2.3.0->pyvmomi) (2.7)
Requirement already satisfied: urllib3<1.24,>=1.21.1 in /usr/lib/python3.7/site-packages (from requests>=2.3.0->pyvmomi) (1.23)
Requirement already satisfied: certifi>=2017.4.17 in /usr/lib/python3.7/site-packages (from requests>=2.3.0->pyvmomi) (2018.8.24)
Using legacy 'setup.py install' for pyvmomi, since package 'wheel' is not installed.
Installing collected packages: pyvmomi
    Running setup.py install for pyvmomi ... done
Successfully installed pyvmomi-7.0
root@vcenter [ ~ ]# 

Define Ansible Inventory

Right after installing Python SDK lets configure Inventory in our Gateway/Centralized server to prepare for VMware Virtual machines deployment using ansible.

I’m going to perform all actions using an account named “ansible”. The interpreter used by ansible on the VCenter server needs to be configured in our inventory.

Inventory file will looks like below.

[ansible@gateway ~]$ sudo cat /etc/ansible/hosts 

[users]
k8mas1.linuxsysadmins.local
k8nod1.linuxsysadmins.local
k8nod2.linuxsysadmins.local

[masters]
master ansible_host=k8mas1.linuxsysadmins.local ansible_user=ansible

[workers]
worker1 ansible_host=k8nod1.linuxsysadmins.local ansible_user=ansible
worker2 ansible_host=k8nod2.linuxsysadmins.local ansible_user=ansible

[vcenter]
vcenter.linuxsysadmins.local ansible_user=ansible ansible_python_interpreter=/usr/bin/python

[ansible@gateway ~]$

These are the VM names we are going to create in VMware VCenter.

[ansible@gateway ~]$ 
[ansible@gateway ~]$ host k8mas1.linuxsysadmins.local
k8mas1.linuxsysadmins.local has address 192.168.0.26
[ansible@gateway ~]$ 
[ansible@gateway ~]$ host k8nod1.linuxsysadmins.local
k8nod1.linuxsysadmins.local has address 192.168.0.27
[ansible@gateway ~]$ 
[ansible@gateway ~]$ host k8nod2.linuxsysadmins.local
k8nod2.linuxsysadmins.local has address 192.168.0.28
[ansible@gateway ~]$ 

If you have installed with the ansible-doc run it to print all the available parameters for vmware_guest module.

$ ansible-doc -s vmware_guest

Creating the Playbook for VMware Virtual machines

Customize to match your environment and save the playbook in a file with .yaml extension.

---
- name: Provisioning a Virtual Machine on VMware from an existing template.
  hosts: vcenter
  connection: ssh
  gather_facts: no

  vars_prompt:

   - name: "vm_templ"
     prompt: "Which OS you need? CentOS 8.2 (centos82template) or Ubuntu 18.04 (ubuntu1804template)"
     private: no

   - name: "master_vm_name"
     prompt: "Name of the virtual Master virtual machine"
     private: no

   - name: "worker1_vm_name"
     prompt: "Name of the Worker 1 virtual machine"
     private: no

   - name: "worker2_vm_name"
     prompt: "Name of the Worker 2 virtual machine"
     private: no

   - name: "master_vm_ip"
     prompt: "Master Virtual Machine IP Address"
     private: no

   - name: "worker1_vm_ip"
     prompt: "Worker1 Virtual Machine IP Address"
     private: no

   - name: "worker2_vm_ip"
     prompt: "Worker2 Virtual Machine IP Address"
     private: no

   - name: "vm_smask"
     prompt: "Subnetmask for Virtual Machine"
     private: no

   - name: "vm_gw"
     prompt: "Gateway of the Virtual Machine"
     private: no

   - name: "net_name"
     prompt: "Port Group Name, VLAN, Network Name"
     private: no

   - name: "vm_memory"
     prompt: "Memory size required?"
     private: no

  vars:
    vc_name: "vcenter.linuxsysadmins.local"
    vc_user: "administrator@vsphere.local"
    vc_pass: "xxxxxxxxxxxxxx"
    dc: "homelab-dc"
    cls: "homelab-cls" 
    datast: "vsanDatastore"
    disk_size: 100
    vm_dns: 192.168.0.21
    notes: This VM Provisioned using ansible.
    dumpfacts: False
  tasks:
    - name: Clone the {{ vm_templ }} Virtual machine from an existing template.
      vmware_guest:
        validate_certs: False
        hostname: "{{ vc_name }}"
        username: "{{ vc_user }}"
        password: "{{ vc_pass }}"
        cluster: "{{ cls }}"
        datacenter: "{{ dc }}"
        folder: "/{{ dc }}/vm"
        name: "{{ master_vm_name }}"
        template: "{{ vm_templ }}"
        disk:
          - size_gb: "{{ disk_size }}"
            type: thin
            datastore: "{{ datast }}"
        networks:
        - name: "{{ net_name }}"
          type: static
          device_type: vmxnet3
          ip: "{{ master_vm_ip }}"
          netmask: "{{ vm_smask }}"
          gateway: "{{ vm_gw }}"
          dns_servers: "{{ vm_dns }}"
        hardware:
          memory_mb: "{{ vm_memory }}"
        wait_for_ip_address: true
        customization:
          domain: linuxsysadmins.local
          dns_servers:
          - 192.168.0.21
          - 192.168.0.22
          dns_suffix:
          - linuxsysadmins.local
        state: present
      register: created_master_vm

    - debug:
         var: created_master_vm.instance.ipv4

    - name: Clone the {{ vm_templ }} Virtual machine from an existing template.
      vmware_guest:
        validate_certs: False
        hostname: "{{ vc_name }}"
        username: "{{ vc_user }}"
        password: "{{ vc_pass }}"
        cluster: "{{ cls }}"
        datacenter: "{{ dc }}"
        folder: "/{{ dc }}/vm"
        name: "{{ worker1_vm_name }}"
        template: "{{ vm_templ }}"
        disk:
          - size_gb: "{{ disk_size }}"
            type: thin
            datastore: "{{ datast }}"
        networks:
        - name: "{{ net_name }}"
          type: static
          device_type: vmxnet3
          ip: "{{ worker1_vm_ip }}"
          netmask: "{{ vm_smask }}"
          gateway: "{{ vm_gw }}"
          dns_servers: "{{ vm_dns }}"
        hardware:
          memory_mb: "{{ vm_memory }}"
        wait_for_ip_address: true
        customization:
          domain: linuxsysadmins.local
          dns_servers:
          - 192.168.0.21
          - 192.168.0.22
          dns_suffix:
          - linuxsysadmins.local
        state: present
      register: created_worker1_vm

    - debug:
         var: created_worker1_vm.instance.ipv4

    - name: Clone the {{ vm_templ }} Virtual machine from an existing template.
      vmware_guest:
        validate_certs: False
        hostname: "{{ vc_name }}"
        username: "{{ vc_user }}"
        password: "{{ vc_pass }}"
        cluster: "{{ cls }}"
        datacenter: "{{ dc }}"
        folder: "/{{ dc }}/vm"
        name: "{{ worker2_vm_name }}"
        template: "{{ vm_templ }}"
        disk:
          - size_gb: "{{ disk_size }}"
            type: thin
            datastore: "{{ datast }}"
        networks:
        - name: "{{ net_name }}"
          type: static
          device_type: vmxnet3
          ip: "{{ worker2_vm_ip }}"
          netmask: "{{ vm_smask }}"
          gateway: "{{ vm_gw }}"
          dns_servers: "{{ vm_dns }}"
        hardware:
          memory_mb: "{{ vm_memory }}"
        wait_for_ip_address: true
        customization:
          domain: linuxsysadmins.local
          dns_servers:
          - 192.168.0.21
          - 192.168.0.22
          dns_suffix:
          - linuxsysadmins.local
        state: present
      register: created_worker2_vm

    - debug:
         var: created_worker2_vm.instance.ipv4

Running the Playbook

Once the playbook created, Check for any syntax error.

$ ansible-playbook vm_provisioning.yaml --syntax-check

Run the playbook to create the Vritual machines from an existing Ubuntu 18.04 template.

$ ansible-playbook vm_provisioning.yaml

Playbook have ran without any errors.

TASK [Clone the ubuntu1804template Virtual machine from an existing template.] *****************************************************
changed: [vcenter.linuxsysadmins.local]

TASK [debug] ***********************************************************************************************************************
ok: [vcenter.linuxsysadmins.local] => {
    "created_worker2_vm.instance.ipv4": "192.168.0.28"
}

PLAY RECAP *************************************************************************************************************************
vcenter.linuxsysadmins.local : ok=6    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[ansible@gateway ~]$

Finally, Server’s are deployed.

Deploy VMware Virtual machines with ansible
Created Virtual Machines

We have successfully deployed Virtual machines on VCenter using Ansible.

If you are looking for how to install and configure Kubernetes cluster find from here. The above playbook for provisioning virtual machines and installing Kubernetes can put inside a single playbook as well. Give a try and provide your feedback in below comment section.

Conclusion

To conclude on Deploy VMware Virtual machines with ansible we have used pyvmomi Python SDK with VMware_guest ansible module which helps to deploy the virtual machines on VMware VCenter. This reduces time and more manual intervention. Subscribe without newsletter for more automation-related articles.

One thought on “Deploy VMware Virtual machines with Ansible for lazy admins

  1. That’s really great article 👍

    Can you please create article or share me link patching RHEL/Ubuntu systems with help of Ansible.

Comments are closed.