How to Identify VMs with Ballooned/Swapped Memory in VMware vSphere Using PowerCLI


4 views

When monitoring VMware vSphere environments, two critical memory metrics often indicate resource contention:

  • Memory ballooning (vmmemctl): When the VMkernel reclaims memory from VMs using the balloon driver
  • Memory swapping: When the hypervisor starts swapping VM memory to disk

Here's a comprehensive PowerCLI script that identifies problematic VMs across a cluster or resource pool:

# Connect to vCenter
Connect-VIServer -Server your_vcenter.example.com

# Function to get memory metrics
function Get-VMMemoryStatus {
    param(
        [Parameter(ValueFromPipeline=$true)]
        $VM
    )
    
    process {
        $memoryStats = $VM | Get-Stat -Stat 'mem.vmmemctl.average','mem.swapped.average' -Realtime -MaxSamples 1
        $ballooned = ($memoryStats | Where-Object {$_.MetricId -eq 'mem.vmmemctl.average'}).Value
        $swapped = ($memoryStats | Where-Object {$_.MetricId -eq 'mem.swapped.average'}).Value
        
        [PSCustomObject]@{
            VM = $VM.Name
            BalloonedMB = if($ballooned) {[math]::Round($ballooned,2)} else {0}
            SwappedMB = if($swapped) {[math]::Round($swapped,2)} else {0}
            Cluster = $VM.VMHost.Parent.Name
            ResourcePool = $VM.ResourcePool.Name
        }
    }
}

# Get all VMs with memory pressure
$problemVMs = Get-Cluster "Your_Cluster_Name" | Get-VM | Get-VMMemoryStatus | 
    Where-Object {$_.BalloonedMB -gt 0 -or $_.SwappedMB -gt 0} |
    Sort-Object -Property BalloonedMB -Descending

# Output results
$problemVMs | Format-Table -AutoSize

# Alternative: Export to CSV for further analysis
$problemVMs | Export-Csv -Path "C:\Temp\MemoryPressureVMs.csv" -NoTypeInformation

The script outputs several key metrics:

  • BalloonedMB: Memory reclaimed through balloon driver (in MB)
  • SwappedMB: Memory swapped to disk (in MB)
  • Cluster/ResourcePool: Location context for the VM

For large environments, you might want to filter results more precisely:

# Find VMs with significant ballooning (> 1GB)
$significantBallooning = $problemVMs | Where-Object {$_.BalloonedMB -gt 1024}

# Find VMs where swapped memory exceeds 5% of configured memory
$severeSwapping = Get-Cluster "Prod_Cluster" | Get-VM | ForEach-Object {
    $metrics = $_ | Get-VMMemoryStatus
    $totalRAM = $_.MemoryMB
    if($metrics.SwappedMB -gt ($totalRAM * 0.05)) {
        $metrics | Select-Object *,@{Name='SwappedPct';Expression={[math]::Round(($_.SwappedMB/$totalRAM)*100,2)}}
    }
}

For proactive monitoring, integrate this with your alerting system:

# Thresholds for alerting (customize as needed)
$balloonThresholdMB = 512
$swapThresholdMB = 256

$alertVMs = $problemVMs | Where-Object {
    $_.BalloonedMB -gt $balloonThresholdMB -or 
    $_.SwappedMB -gt $swapThresholdMB
}

if($alertVMs) {
    # Send email alert
    $body = $alertVMs | ConvertTo-Html | Out-String
    Send-MailMessage -From "vmmonitor@example.com" -To "vteam@example.com" 
        -Subject "Memory Pressure Alert: $($alertVMs.Count) VMs affected" 
        -BodyAsHtml $body -SmtpServer "smtp.example.com"
    
    # Alternatively, create vCenter alarms
    $alertVMs | ForEach-Object {
        New-AlarmDefinition -Name "Memory Pressure - $($_.VM)" -Description "High memory ballooning/swapping detected" 
            -Entity ($_ | Get-VM) -Action (New-AlarmAction -Snmp)
    }
}

When running these queries in large environments:

  • Use the -Realtime parameter for current data (20s interval)
  • For historical analysis, specify -Start and -Finish parameters with -IntervalMins
  • Limit scope when possible (cluster/resource pool vs entire vCenter)

For VMs identified with memory pressure:

  1. Right-size memory allocations based on actual usage
  2. Check for memory leaks in guest OS
  3. Consider vSphere Memory Reservations for critical workloads
  4. Evaluate cluster-level memory resources (DRS, HA settings)

When working with VMware vSphere clusters, memory ballooning (vmmemctl) and swapping occur when the ESXi host is under memory pressure. Ballooning is a preferred method where the VMkernel reclaims memory from guest VMs using the balloon driver, while swapping is a last-resort mechanism that can significantly impact performance.

The most efficient way to identify VMs with ballooned or swapped memory is through VMware's PowerCLI. Here's a comprehensive script that provides detailed information:


# Connect to vCenter Server
Connect-VIServer -Server your_vcenter_server -Credential (Get-Credential)

# Get all VMs with memory metrics
$report = @()
$vms = Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"}
foreach ($vm in $vms) {
    $metrics = Get-Stat -Entity $vm -Stat "mem.vmmemctl.average", "mem.swapped.average" -Realtime -MaxSamples 1
    $ballooned = ($metrics | Where-Object {$_.MetricId -eq "mem.vmmemctl.average"}).Value
    $swapped = ($metrics | Where-Object {$_.MetricId -eq "mem.swapped.average"}).Value
    
    $report += [PSCustomObject]@{
        VMName = $vm.Name
        BalloonedMB = if ($ballooned) { [math]::Round($ballooned) } else { 0 }
        SwappedMB = if ($swapped) { [math]::Round($swapped) } else { 0 }
        Cluster = $vm.VMHost.Parent.Name
        Host = $vm.VMHost.Name
    }
}

# Display results sorted by most ballooned memory
$report | Sort-Object -Property BalloonedMB -Descending | Format-Table -AutoSize

# Export to CSV for further analysis
$report | Export-Csv -Path "C:\temp\VM_Memory_Usage.csv" -NoTypeInformation

The script outputs several key metrics:

  • BalloonedMB: Shows how much memory (in MB) is currently being reclaimed through ballooning
  • SwappedMB: Indicates the amount of memory swapped to disk
  • Cluster/Host: Helps identify if issues are localized to specific hosts or clusters

For those who prefer working directly with the vSphere API, here's a Python example using pyVmomi:


from pyVmomi import vim
from pyVim.connect import SmartConnectNoSSL, Disconnect
import atexit

def get_vm_memory_stats(si):
    content = si.RetrieveContent()
    container = content.viewManager.CreateContainerView(
        content.rootFolder, [vim.VirtualMachine], True)
    
    for vm in container.view:
        if vm.runtime.powerState == vim.VirtualMachinePowerState.poweredOn:
            stats = vm.summary.quickStats
            print(f"VM: {vm.name}")
            print(f"  Ballooned Memory: {stats.balloonedMemory} MB")
            print(f"  Swapped Memory: {stats.swappedMemory} MB")
            print(f"  Guest Memory Usage: {stats.guestMemoryUsage} MB")
            print("------------------------")

# Connect to vCenter
si = SmartConnectNoSSL(
    host="vcenter.example.com",
    user="administrator@vsphere.local",
    pwd="yourpassword")
atexit.register(Disconnect, si)

get_vm_memory_stats(si)

For enterprise environments, consider setting up alerts in vRealize Operations Manager with these recommended thresholds:

  • Warning: Ballooned memory > 10% of configured VM memory
  • Critical: Swapped memory > 5% of configured VM memory
  • Immediate action: Swapped memory > 10% of configured VM memory

Once you've identified problematic VMs:

  1. Check for memory over-provisioning in the cluster
  2. Consider increasing VM memory allocation if justified by workload requirements
  3. Evaluate memory reservations for critical VMs
  4. Implement DRS rules to balance memory load across hosts
  5. Upgrade VMware Tools to ensure balloon driver is functioning optimally