How to Configure VMware ESXi with Ansible

One way to ensure that your VMware ESXi hosts have a consistent and repeatable configuration; is with the use of Ansible. I have created an ansible playbook that can be run against a VMware ESXi host to a desired configuration and run on a weekly basis to check for configuration drift. The true power is running the ansible playbook against multiple hosts and be assured the configuration are the same on all hosts in minutes.

During this series of blog posts, I am showcasing the process of updating my outdated Ansible playbooks. By doing so, this allows me to take advantage of newer versions of Ansible along with updated vendor modules.

As I have mentioned in several of my previous blog posts, I am a huge fan of automation and use it whenever possible and I hope this motivates you as well.

Ansible Stand Outs

No Agents

Ansible is Agentless, you only need to install Ansible from where you want to run in from. (Linux based)

YAML

Ansible is YAML based, its coding / scripting as close to understandable / readable tasks.

Procedural

Ansible is Procedural, Playbooks run tasks / procedures in order (order of operations)

Ecosystem

Ansible has a large Ecosystem, not only VMware but other Vendors like Cisco and NetApp

Terminology use by Ansible

Modules

Modules are what does the magic, they are all written in Python by VMware and other vendors, and you as a user should never had to open or modify. As an end-user, you only need to know what Module to call in your Playbook.

Playbooks

Playbook is the configuration file that Ansible will reference it defines what you want to do and the order you want to run the task in.

Roles

Roles are a collection of tasks, variables and templates from playbooks.

VMware ESXI Host Configuration

Now that we have VM running Redhat RHEL9 with Ansible, along with the VMware ‘pymomi’ module installed, we can start creating a playbook to configure an ESXi host.

This playbook will consist of most commonly used configurations along with some advanced VMware security hardening settings that I wrote about in another blog post

Create Ansible Playbook

Ther are various editors when it comes to building your playbooks, I decide to use Microsoft Visual Studio Code. This allows me to ssh directly to my RHEL9 VM and create / validate my playbooks.

VARS FILE

In my playbooks I make use of a variables, this way if I need to make DNS or NTP changes for example, I only need to make those changes on my vars.yml file.

Here is a sample of what I use, feel free to make adjustments that fit your environment

# Add ESXi Hosts that you want to modify with the same information
esxi_info:
  - { name: '10.11.16.180', vmo: "10.11.17.180",  nfs_ip: "10.11.14.180", netmask: "255.255.255.0" }
 # - { name: '10.10.20.221', vmo: "10.10.40.221",  nfs_ip: "10.10.100.221", netmask: "255.255.255.0" }

#DNS and NTP
upstream_dns1: "10.11.20.11"
upstream_dns2: "10.11.20.12"
upstream_ntp1: "0.pool.ntp.org"
upstream_ntp2: "1.pool.ntp.org"

#Windows Server and Domain Controller Information
dc_hostname: DC1--CORE1
dc_address: "10.10.10.10"
domain_name: "humbledgeeks.com"
ad_user: "admin.allen"
ad_password: "P@ssw0rd"
esx_admins_group: "ESXi_Admins"

#VMware ESXi Host Infrastructure

esxi_address: "10.11.16.180"
esxi_password: "P@sw0rd"
esxi_netmask: "255.255.255.0"
esxi_netmask_cidr: "24"
esxi_gateway: "10.11.16.1"
esxi_hostname: "wcv-hst-esxi01"
esxi_username: "root"
esxi_local_datastore: "HPE_Local"
ext_storage_ds_name: 'NFS_DS01'
ext_storage_ds_type: 'nfs'
ext_storage_nfs_server: '10.11.14.10'
ext_storage_nfs_path: 'NFS_DS01'
validate_certs: "no"
service_policy: 'pressent'
tsm_policy: 'on'
tsm_state: 'present'

ESXI PLAYBOOK

The Red Hat Ansible website has various modules, along with examples on how to configure and manage your VMware environment using Ansible playbooks.  You just need to find what you are trying to accomplish, copy / modify the sample and make it your own.

Now lets start building a ESXi Conifg playbook with most commonly used settings

ESXi MANAGE SERVICES

Here in my playbook, I am calling on the vars.yml file I created in the previous step.

I am creating a playbook called ‘ESXiConfig.yml’ where I will build out the tasks that I typically configure on an ESXi host.

When configuring a VMware ESXi host, I oftentimes require SSH to be enabled but best security practices state you should disable when not required. So, I usually add this to my playbook, this was I can easily enable or disable as need and can easily use it to validate that SSH is disabled across my environment.

The “community.vmware.vmware_host_service_manager” module can be used to manage (start or stop) services on VMware ESXi hosts.

To run / validate your playbook from the terminal run the following command.

As I build out my playbook, I like to periodically test and validate, this help troubleshoot along the way.

From your RHEL9 VM, change to the directory where your playbook resides and run the following command

ansible-playbook ESXi_Config.yml

As the tasks in the playbook run, you will see a ‘green’ text for items that don’t need any modifications.

--- 
- hosts: localhost 
  name: ESXi Basic Configuration 
  gather_facts: false
  vars:
    esxi_login: &esxi_login
      hostname: '{{ item.name }}'
      username: '{{ esxi_username }}'
      password: '{{ esxi_password }}'   
      validate_certs: no 
    tsm_policy: on
    tsm_state: present 
  vars_files: 
    vars.yml
  tasks:
# Enable / Disable SSH on Host 
  - name: Enable SSH (TSM-SSH) for an ESXi Host with Service policy
    community.vmware.vmware_host_service_manager:
     <<: *esxi_login
     esxi_hostname: '{{ esxi_address }}'
     service_name: TSM-SSH
     service_policy: on
     state: present # Chnage to Absent if you want to disable SSH
    delegate_to: localhost
    loop: '{{ esxi_info }}'
  - name: Enable ESX Shell (TSM) setting for an ESXi Host with Service policy
    community.vmware.vmware_host_service_manager:
     <<: *esxi_login
     esxi_hostname: '{{ item.name }}'
     service_name: TSM
     service_policy: on
     state: present # Chnage to Absent if you want to disable SSH
    delegate_to: localhost
    loop: '{{ esxi_info }}'

ESXi Security Configuration Tasks

The vSphere Security Configuration Guide (SCG) 7 is the baseline for security hardening of VMware vSphere itself, and the core of VMware security best practices. The VMware vSphere Security Hardening Guide gives recommended guidance for vSphere Administrators looking to protect their infrastructure.

The “community.vmware.vmware_host_config_manager” module can be used to configure advanced settings on VMware ESXi hosts.

I have chosen most of the ESXi configuration options from the vSphere Security Configuration Guide (SCG) 7 along with other best practices to enforce VMware ESXi security configurations across my environment.

As I mentioned earlier, I like running and validating my playbooks as I add new taks, lets do that now.

ansible-playbook ESXiConfig.yml

As you can see, the ‘Advanced Options’ have been applied without errors and we can continue building on the playbook.

ESXi Storage Advanced Settings (NFS)

Here are some additional settings for those using NetApp NFS that can be added to your playbook.

  - name: Set Advance ESXi and NetApp VSC Values. # Apply VMware / NetApp NFS Best Practices
    community.vmware.vmware_host_config_manager:
      <<: *esxi_login
      esxi_hostname: '{{ item.name }}'
      options:
        "Net.TcpipHeapSize": 32
        "Net.TcpipHeapMax": 1536
        "NFS.MaxVolumes": 256
        "NFS41.MaxVolumes": 256
        "NFS.MaxQueueDepth": 128
        "NFS.HeartbeatMaxFailures": 10
        "NFS.HeartbeatFrequency": 12
        "NFS.HeartbeatTimeout": 5
        "Disk.QFullSampleSize": 32
        "Disk.QFullThreshold": 8
    delegate_to: localhost
    loop: '{{ esxi_info }}'

ESXi DNS / NTP Configuration Tasks

The “community.vmware.vmware_host_dns” module can be used to configure DNS settings on VMware ESXi hosts.

The “community.vmware.vmware_host_ntp” module can be used to configure NTP settings on VMware ESXi hosts.

--- 
- hosts: localhost 
  name: ESXi Basic Configuration 
  gather_facts: false
  vars:
    esxi_login: &esxi_login
      hostname: '{{ item.name }}'
      username: '{{ esxi_username }}'
      password: '{{ esxi_password }}'   
      validate_certs: no 
    tsm_policy: on
    tsm_state: present 
  vars_files: 
    vars.yml
  tasks:
  - name: Enable SSH (TSM-SSH) for an ESXi Host with Service policy # Enable SSH on ESXi Host
    community.vmware.vmware_host_service_manager:
     <<: *esxi_login
     esxi_hostname: '{{ esxi_address }}'
     service_name: TSM-SSH
     service_policy: on
     state: present # Chnage to Absent if you want to disable SSH
    delegate_to: localhost
    loop: '{{ esxi_info }}'
  - name: Enable ESX Shell (TSM) setting for an ESXi Host with Service policy # Enable SSH Service
    community.vmware.vmware_host_service_manager:
     <<: *esxi_login
     esxi_hostname: '{{ item.name }}'
     service_name: TSM
     service_policy: on
     state: present # Chnage to Absent if you want to disable SSH
    delegate_to: localhost
    loop: '{{ esxi_info }}'
# Set Advanced Options
  - name: Set Advanced Options
    community.vmware.vmware_host_config_manager:
      <<: *esxi_login
      esxi_hostname: '{{ item.name }}'
      options:
        "Config.HostAgent.log.level" : info
        "UserVars.ESXiShellInteractiveTimeOut": 900
        "UserVars.ESXiShellTimeOut": 900
        "UserVars.DcuiTimeOut": 600
        "Security.AccountLockFailures": 5
        "Security.AccountUnlockTime": 900
        "Security.PasswordHistory" : 5
        "Security.PasswordQualityControl": "similar=deny retry=3 min=disabled,disabled,disabled,disabled,15"
        "UserVars.SuppressShellWarning": 1 
        "UserVars.ESXiVPsDisabledProtocols" : "sslv3,tlsv1,tlsv1.1"
        "VMkernel.Boot.execInstalledOnly" : true
        "Mem.ShareForceSalting": 2
        "Misc.BlueScreenTimeout": 60
        "Config.HostAgent.plugins.solo.enableMob": false
       #"VMkernel.Boot.allowCoreDumpOnUsb": 'TRUE'
       #"Annotations.WelcomeMessage": 'This system is intended for the use of authorized users only'
       #'Syslog.global.logDir': '[NFS_DS01]scratch/{{ item.name }}'
    delegate_to: localhost
    loop: '{{ esxi_info }}'
  - name: Set Advance ESXi and NetApp VSC Values. # Apply VMware / NetApp NFS Best Practices
    community.vmware.vmware_host_config_manager:
      <<: *esxi_login
      esxi_hostname: '{{ item.name }}'
      options:
        "Net.TcpipHeapSize": 32
        "Net.TcpipHeapMax": 1536
        "NFS.MaxVolumes": 256
        "NFS41.MaxVolumes": 256
        "NFS.MaxQueueDepth": 128
        "NFS.HeartbeatMaxFailures": 10
        "NFS.HeartbeatFrequency": 12
        "NFS.HeartbeatTimeout": 5
        "Disk.QFullSampleSize": 32
        "Disk.QFullThreshold": 8
    delegate_to: localhost
    loop: '{{ esxi_info }}'
  - name: Configure ESXi hostname and upstream DNS servers # Configure Host DNS Settings
    community.vmware.vmware_host_dns:
      <<: *esxi_login
      domain: '{{ domain_name }}'
      type: static 
      dns_servers:
      - '{{ upstream_dns1 }}'
      - '{{ upstream_dns2 }}'
    loop: '{{ esxi_info }}'
  - name: Set NTP servers for an ESXi Host # Configure Host NTP Settings 
    community.vmware.vmware_host_ntp:
      <<: *esxi_login
      esxi_hostname: '{{ item.name }}'
      state: present
      ntp_servers:
        - '{{ upstream_ntp1 }}'
        - '{{ upstream_ntp2 }}'
    delegate_to: localhost
    loop: '{{ esxi_info }}'
  - name: Start ntpd service setting for all ESXi Host in given Cluster # Enable NTP Service

Now that you see how easy it is to put together an ESXi Configuration playbook, this can now be run on a schedule to catch any configuration drift.

For this exercise, I am going to make a NTP change, and see what happens when I run the ESXi_Config.yml playbook.

1 thought on “How to Configure VMware ESXi with Ansible”

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top