Ansible playbook to collect vSphere performance metrics
vSphere exposes CPU, memory, storage and network counters that help teams explain saturation, validate capacity and investigate incidents. Ansible can collect those values through a repeatable workflow instead of intermittent screenshots or manual checks in the vSphere Client.
This example uses VMware PowerCLI through the community.general.powershell module, producing timestamped JSON that can feed AWX, a SIEM or a time-series platform. It captures a current snapshot; historical analysis requires a performance-history pipeline or access to the vCenter Performance API.
Why automate vSphere performance data
Regular collection gives operations teams a common baseline. Host CPU and memory indicate whether the physical layer is under pressure, while VM counters reveal which workloads are responsible. The evidence supports capacity reviews, incident timelines and post-maintenance comparisons.
Australian enterprises and managed service providers often span Sydney, Melbourne, Brisbane and Perth, with vCenter endpoints hosted in major regional facilities. Australian admins commonly call a saturated VM hot, so alerts can preserve that familiar language while exposing the underlying counter. The VMware automation guides place this collection job within a broader VMware workflow.
Prepare the collection environment
Run the controller from a trusted Linux host, such as Ubuntu 24.04 LTS, with Ansible Core, the community.general collection, PowerShell 7 and VMware.PowerCLI. The controller needs outbound TCP 443 access to vCenter; virtual machines do not need an Ansible agent for this method.
Install the collection with ansible-galaxy collection install community.general and PowerCLI with Install-Module VMware.PowerCLI -Scope CurrentUser. Create a dedicated vCenter service account with read access to inventory and current performance counters. Store its credentials with Ansible Vault, then pass them to the short-lived PowerCLI session as environment values.
Record timestamps in UTC and translate them for display. New South Wales moves between AEST and AEDT, while Victoria and Queensland keep standard time; offset-aware alerts prevent an hour of misleading data each autumn. Central scheduling should also account for links to regional sites rather than assuming constant low latency.
Build the collection playbook
The inventory defines one local controller, while variables hold the vCenter address and artifact path. VMware.PowerCLI supplies current counters through Get-VMHostSummary and Get-VM, so no guest agent is required. Each record keeps the source unit explicit.
---
- name: Collect vSphere performance metrics
hosts: localhost
connection: local
gather_facts: false
vars:
vsphere_server: vcenter.au.example.com
metric_directory: /var/tmp/vsphere-metrics
tasks:
- name: Set the UTC collection timestamp
ansible.builtin.set_fact:
metric_run: "{{ now(utc=true) | strftime('%Y%m%dT%H%M%SZ') }}"
- name: Ensure the artifact directory exists
ansible.builtin.file:
path: "{{ metric_directory }}"
state: directory
mode: "0750"
- name: Collect host and virtual machine counters
community.general.powershell:
script: |
$ErrorActionPreference = 'Stop'
$password = ConvertTo-SecureString $env:VSPHERE_PASSWORD -AsPlainText -Force
$credential = [pscredential]::new($env:VSPHERE_USER, $password)
$session = Connect-VIServer -Server $env:VSPHERE_SERVER -Credential $credential
try {
$summaries = Get-VMHostSummary -VMHost (Get-VMHost)
$hosts = @(Get-VMHost | ForEach-Object {
$esxiHost = $_
$summary = $summaries | Where-Object { $_.Name -eq $esxiHost.Name }
[ordered]@{
name = $esxiHost.Name
cpu_percent = $summary.CpuUsage
memory_mb = $summary.MemUsage
power_state = [string]$esxiHost.PowerState
}
})
$vms = @(Get-VM | ForEach-Object {
$vm = $_
[ordered]@{
name = $vm.Name
host = $vm.Host.Name
cpu_mhz = $vm.CPUUsage
memory_mb = $vm.MemoryUsage
power_state = [string]$vm.PowerState
}
})
$payload = [ordered]@{
collected_at = [DateTime]::UtcNow.ToString('o')
hosts = $hosts
vms = $vms
}
$payload | ConvertTo-Json -Depth 5 |
Set-Content -Path $env:VSPHERE_ARTIFACT -Encoding utf8
}
finally {
Disconnect-VIServer -Server $session -ErrorAction SilentlyContinue
}
environment:
VSPHERE_SERVER: "{{ vsphere_server }}"
VSPHERE_USER: "{{ vault_vsphere_user }}"
VSPHERE_PASSWORD: "{{ vault_vsphere_password }}"
VSPHERE_ARTIFACT: "{{ metric_directory }}/vsphere-{{ metric_run }}.json"
no_log: true
changed_when: false
- name: Restrict artifact permissions
ansible.builtin.file:
path: "{{ metric_directory }}/vsphere-{{ metric_run }}.json"
mode: "0640"
The host payload includes processor percentage and memory usage. The VM payload adds its ESXi host, power state, CPU load in MHz and memory use in MB. The controller creates a UTC-stamped JSON file with restrictive permissions; no values are normalised without knowing the configured capacity.
Compare the viable collection methods
The right collection route depends on whether the requirement is a repeatable snapshot, historical series or continuous monitoring:
| Approach | Useful output | Operating model | Main trade-off |
|---|---|---|---|
| Ansible with PowerCLI | Current host and VM CPU and memory counters | Scheduled controller or AWX job | Simple to operate, but limited history |
| Ansible with pyVmomi | Current or historical counters from the vSphere Performance API | Custom Python module or script | Flexible, but more development |
| vCenter exporter with Prometheus | Continuous time-series metrics for hosts and VMs | Scrape and retention stack | Better trend analysis, extra infrastructure |
PowerCLI is the simplest route for a small estate or a scheduled evidence bundle. For detailed history, pyVmomi exposes the Performance API but requires custom code. A Prometheus exporter supports continuous fleet-wide metrics, adding a scrape and retention stack to operate.
Validate and operationalise the output
Start with a syntax check, then run the playbook against a non-production vCenter and inspect the JSON. Confirm object counts, null values and units before scheduling. A powered-off VM can legitimately report zero or missing counters, which should not be treated as a failed collection.
Use jq '{collected_at, host_count: (.hosts | length), vm_count: (.vms | length)}' metrics.json to validate the shape quickly, then compare trends rather than isolated readings. CPU values in MHz are not CPU percentages, and memory figures need configured capacity before a utilisation ratio is calculated. Treat authentication failures, stale timestamps or unexpected gaps as collection failures and alert operations instead of publishing empty results.
Build a repeatable monitoring workflow
Once the snapshot is reliable, AWX can run it on a short interval and forward the JSON to InfluxDB, a SIEM or an API. Keep raw counters and the collection timestamp so teams can reconcile them with Australian daylight-saving changes and regional maintenance windows.
The pattern can be extended through the VirtXpert resources and tools, including related PowerCLI utilities. Keep credential handling in Vault and avoid placing vCenter addresses or performance data in public build logs.
Copy the playbook into your repository, test it with a read-only account, verify one complete artifact, and schedule the first run from AWX. Retain that baseline for capacity reviews and make it the starting point for continuous virtualisation observability.