EC2 Windows GPU: Install NVIDIA GRID and Publish CloudWatch Metrics
EC2 Windows GPU: Install NVIDIA GRID and Publish CloudWatch Metrics
A standard Windows Server AMI on g4dn or g5 may initially expose only Microsoft Basic Display Adapter, with no working nvidia-smi. After installing the driver, another gap appears: the Windows CloudWatch Agent cannot use the Linux nvidia_gpu receiver.
This guide connects both steps—installing an AWS GRID driver and publishing parsed nvidia-smi values as custom CloudWatch metrics.
Select and install the driver
GRID is appropriate for graphics, remote desktops, video encode, and WDDM workloads. Data Center/Tesla drivers are commonly used for compute/TCC workloads.
List the current files in the AWS public bucket instead of hard-coding a version from an article:
aws s3 ls s3://ec2-windows-nvidia-drivers/latest/ `
--no-sign-request --region us-east-1Choose the file matching the Windows release:
$ErrorActionPreference = 'Stop'
$driver = 'C:\ProgramData\Amazon\NVIDIA\grid-driver.exe'
New-Item (Split-Path $driver) -ItemType Directory -Force | Out-Null
aws s3 cp `
's3://ec2-windows-nvidia-drivers/latest/<selected-driver>.exe' `
$driver --no-sign-request --region us-east-1
$p = Start-Process $driver `
-ArgumentList '-s -noreboot -noeula' -Wait -PassThru
if ($p.ExitCode -ne 0) { throw "Driver installer exit code $($p.ExitCode)" }
& "$env:ProgramFiles\NVIDIA Corporation\NVSMI\nvidia-smi.exe"A reboot may be required. Before a remote reboot, verify that SSM, EC2Launch, or another recovery path is available.
IAM permission
The instance role needs cloudwatch:PutMetricData. The permission can be constrained to the custom namespace:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "cloudwatch:PutMetricData",
"Resource": "*",
"Condition": {"StringEquals": {"cloudwatch:namespace": "Custom/GPU"}}
}]
}Collector
Use IMDSv2 for region and instance dimensions, parse every GPU row, and submit multiple values in one API call per GPU:
$ErrorActionPreference = 'Stop'
$smi = "$env:ProgramFiles\NVIDIA Corporation\NVSMI\nvidia-smi.exe"
$token = Invoke-RestMethod -Method Put `
-Uri 'http://169.254.169.254/latest/api/token' `
-Headers @{'X-aws-ec2-metadata-token-ttl-seconds'='21600'}
$h = @{'X-aws-ec2-metadata-token'=$token}
$region = Invoke-RestMethod -Headers $h `
-Uri 'http://169.254.169.254/latest/meta-data/placement/region'
$instanceId = Invoke-RestMethod -Headers $h `
-Uri 'http://169.254.169.254/latest/meta-data/instance-id'
$instanceType = Invoke-RestMethod -Headers $h `
-Uri 'http://169.254.169.254/latest/meta-data/instance-type'
$rows = & $smi `
'--query-gpu=index,utilization.gpu,utilization.memory,memory.total,memory.used,temperature.gpu,power.draw' `
'--format=csv,noheader,nounits'
foreach ($row in $rows) {
$v = $row.Split(',') | ForEach-Object { $_.Trim() }
$dims = @(
@{Name='InstanceId';Value=$instanceId},
@{Name='InstanceType';Value=$instanceType},
@{Name='GPUIndex';Value=$v[0]}
)
$metrics = @(
@{MetricName='GPUUtilization';Value=[double]$v[1];Unit='Percent';Dimensions=$dims},
@{MetricName='MemoryUtilization';Value=[double]$v[2];Unit='Percent';Dimensions=$dims},
@{MetricName='MemoryTotal';Value=[double]$v[3];Unit='Megabytes';Dimensions=$dims},
@{MetricName='MemoryUsed';Value=[double]$v[4];Unit='Megabytes';Dimensions=$dims},
@{MetricName='Temperature';Value=[double]$v[5];Unit='None';Dimensions=$dims},
@{MetricName='PowerDraw';Value=[double]$v[6];Unit='None';Dimensions=$dims}
)
aws cloudwatch put-metric-data --namespace 'Custom/GPU' `
--metric-data ($metrics | ConvertTo-Json -Depth 5 -Compress) `
--region $region
}Save it as C:\ProgramData\Amazon\GPUMetrics\collect.ps1 and schedule it once per minute:
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument `
'-NoProfile -ExecutionPolicy Bypass -File "C:\ProgramData\Amazon\GPUMetrics\collect.ps1"'
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) `
-RepetitionInterval (New-TimeSpan -Minutes 1)
$principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' `
-LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName 'GPU-Metrics-Collector' `
-Action $action -Trigger $trigger -Principal $principal -ForceValidation and alerts
Get-ScheduledTaskInfo 'GPU-Metrics-Collector'
aws cloudwatch list-metrics --namespace 'Custom/GPU' --region $regionUseful alerts include sustained high temperature, prolonged saturation, memory exhaustion, and power unexpectedly dropping to zero. Thresholds must be based on the GPU model and workload baseline.
Common issues:
- Missing
nvidia-smi: driver installation is incomplete or a reboot is pending. - No metrics: inspect IAM, the namespace condition, and
LastTaskResult. - Multiple GPUs: parse every CSV row and include
GPUIndex. - System proxy: bypass
169.254.169.254or both IMDS and SSM may fail. - Custom metrics and API requests incur charges; check current regional pricing.
Summary
Treat “the driver works” and “the workload is observable” as separate acceptance criteria. Select the current matching GRID package, verify nvidia-smi, then batch custom metric data into CloudWatch for dashboards and alarms across the Windows GPU fleet.
