ASDI - Streamlining VMTools Deployment Using a Dockerised Ansible Workflow

An ASDI Example

DOCKER

Jack Jalali

5/2/20255 min read

Managing large fleets of virtual machines (VMs) can become a daunting task, especially when it comes to repetitive deployments like updating or installing VMTools, replacing antivirus application, deploying CVEs and deploying zero days patches. Things become even more complicated when your virtual estate is predominantly Microsoft Windows based.

To simplify this process, I’ve implemented a clean, repeatable, and containerised approach using Docker and Ansible and based on the framework explained in my previous post. This article walks through the architecture and flow of deploying VMTools to multiple VMs using an Application Specific Docker Image.

Overview

At the heart of this solution is an ASDI built on an Ubuntu base, pre-packaged with all the necessary software and payloads. This image is first built and tested on an Imager VM before being pushed to a Deployment Server, where it’s executed against the target VMs.

Prerequisites

Before jumping into the process, make sure the following components are in place:

  • Linux Imager VM:
    This VM must be capable of running Docker and Ansible-vault. Ansible-vault here is primarily used to encrypt sensitive files that are later deployed.

  • Deployment Linux VM:
    Only has docker installed, this machine will run the actual deployment containers.

  • vSphere Environment:
    Ensure that your VM infrastructure supports pre-defined custom attribute tags for tracking and updating VM metadata.

Workflow Breakdown

  1. Build Phase
    On the Imager VM:

    • A custom Docker image is created on the imager server.

    • The image includes all the necessary files, scripts, and dependencies required for VMTools deployment.

    • Sensitive files are encrypted using Ansible Vault.

    • Imager's file structure is shown below:

  • group_vars contains all necessary info for ansible to be able to connect to windows VMs using WINRM. The folder contains one file, all.yml which is encrypted:

  • All the logs are written to the logs folder, this folder is shared between the host, the deployment VM and the container.

  • The software folder contains the payload to be deployed to the VMs. This folder is shared between the host, the deployment VM and the container.

  • dockerfile copies ansible.cfg file to /etc/ansible/ - ansible always checks this folder by default. This way I don't need to care where I run Ansible from - it'll always pick up my config.

  • DeployVMtoolsSilently.yml is my ansible playbook that received two inputs, filename and inventory_group where the target VMs are listed.

  • ramz.yml and secrets.yml files contain encrypted sensitive data like usernames and passwords etc.

  • krb5.conf file is used in Ansible to configure Kerberos authentication, which enables secure single sign-on (SSO) for Windows systems using Active Directory (AD). Here’s a simple explanation:

    • Purpose: krb5.conf defines settings for Kerberos, a protocol that authenticates users and services in a network. In Ansible, it helps Ansible connect to Windows hosts via Kerberos for tasks like running playbooks or managing systems.

    • Role in Ansible: When Ansible manages Windows hosts, it often uses WinRM (Windows Remote Management) with Kerberos for authentication. The krb5.conf file tells Ansible how to communicate with the AD domain to validate credentials.

    • Key Contents:

      • Realms: Specifies the AD domain (e.g., EXAMPLE.COM) and the Kerberos Key Distribution Centre(KDC) server (usually the domain controller).

      • Domain-Realm Mapping: Maps domain names to Kerberos realms for proper routing.

      • Default Settings: Defines encryption types, ticket lifetimes, or other Kerberos behaviours.

    • Windows Authentication: On Windows, Kerberos is the default for AD authentication. Ansible uses the credentials (username and password or keytab) provided in the playbook or inventory, and krb5.conf ensures these are validated against the AD domain’s KDC.

    • Setup in Ansible:

      • Place krb5.conf (typically in /etc/krb5.conf on Linux) on the Ansible control node.

      • Configure it with the correct AD domain, KDC, and realm details.

      • Ensure Ansible’s inventory file specifies Kerberos as the authentication method (e.g., ansible_winrm_transport=Kerberos).

      • Use valid AD credentials in Ansible playbooks or vault.

    • Example krb5.conf:

Building and Transferring the Docker Image

While inside the imager and within the directory containing the Dockerfile (as shown during the build phase), we initiate the image build process using the following command:

sudo docker build --no-cache -t vmtoolz .

Once the image is successfully built, we use the docker save command to create a compressed archive of the image. This makes it portable for transfer to the deployment server:

sudo docker save -o vmtoolz.tar vmtoolz

Next, copy the vmtoolz.tar file to the deployment server using your preferred method (e.g., scp, rsync, etc.). At this point, the imager’s job is complete and it can be safely powered down. Then, log into the deployment server and load the image:

sudo docker load -i vmtoolz.tar

You can verify the image has been successfully imported with:

sudo docker images

Running the Installation Script

Now let’s review the installVMTools.sh script.

This script launches a container named vmtoolsinstaller from the Docker image we just imported. It mounts a volume from the deployment server (in this case, a playbooks directory) to the container’s /shared folder:

sudo docker run --name vmtoolsinstaller -itd -v /home/ansible/playbooks/deployVMToolsSilently_new:/shared vmtoolz

Within this container, the script runs the DeployVMtoolsSilently.yml Ansible playbook from the working directory /etc/ansible/playbooks. It passes in two variables: inventory_group and filename, which correspond to the target VM group in the inventory prod.ini and the installer executable, respectively:

sudo docker exec -w /etc/ansible/playbooks vmtoolsinstaller ansible-playbook DeployVMtoolsSilently.yml -e "inventory_group=staging" -e "filename=VMware-tools-12.5.1-24649672-x64.exe" > ./logs/tools.log

What the Playbook Does

The Ansible playbook performs the following actions:

  • Copies the specified executable (via the filename variable) to all VMs listed in the [staging] group in the prod.ini inventory.

  • Executes the installer locally on each VM.

  • Logs each processed VM into a file named attachments.txt.

  • Emails this attachment to the intended recipients.

  • Updates custom attributes on each virtual machine, indicating successful VMware Tools installation.

After successful deployment, the code will stop and delete the container:

sudo docker stop vmtoolsinstaller

sudo docker rm vmtoolsinstaller

All relevant files can be found here: github