TL;DR
NVIDIA GPU monitoring needs more than a utilization chart. A production design should collect device telemetry with DCGM Exporter, scrape it with Prometheus, visualize fleet and workload behavior in Grafana, and alert on conditions that require action. The runbook must also preserve per-pod context, control metric cardinality, distinguish low utilization from genuine performance problems, and capture enough evidence to support escalation.
The safest implementation path is to use the DCGM Exporter already deployed by NVIDIA GPU Operator when one exists. Deploy a standalone exporter only when the Operator is not managing GPU telemetry. Validate the exporter, ServiceMonitor, Prometheus target, metric set, workload labels, dashboards, and alert rules as separate gates.
Introduction
A GPU can be allocated, visible to a container, and technically healthy while the application using it still performs badly.
That gap is where weak GPU monitoring designs fail. They show that a device exists and may even show a utilization percentage, but they do not explain whether the workload is compute-bound, memory-bound, input-starved, thermally constrained, power-limited, mis-scheduled, or sharing a device with another workload.
NVIDIA Data Center GPU Manager, commonly shortened to DCGM, provides the device monitoring, health, diagnostics, accounting, and behavioral data behind this operating model. DCGM Exporter converts selected DCGM fields into Prometheus metrics. Prometheus stores and evaluates those metrics, while Grafana presents the fleet, node, GPU, namespace, pod, and workload views operators need during normal operations and incidents.
This article treats the stack as an operational runbook rather than a dashboard installation exercise. The objective is not merely to make graphs appear. The objective is to build a monitoring path that can answer a production question, raise an actionable alert, and produce defensible evidence before an issue is escalated.
Scenario
Assume a Kubernetes platform team operates a mixed GPU cluster that supports model training, inference, notebooks, batch processing, and shared platform services.
The environment may include full GPUs, Multi-Instance GPU profiles, or time-sliced devices. Some teams deploy workloads through standard Deployments, while others use Jobs, queueing systems, notebook controllers, or inference operators. The cluster already has Prometheus and Grafana, but GPU visibility is incomplete or inconsistent.
Common requests arrive in several forms:
An application team reports that inference latency increased even though the pod is healthy.
A training job takes longer than expected and appears to use only part of the allocated GPU.
A GPU node experiences XID events, ECC errors, or pending page retirement.
Capacity planning shows expensive GPUs allocated for long periods with low effective usage.
The support team needs a precise evidence package before opening a vendor case.
A good monitoring design must support all of those scenarios without turning Prometheus into an uncontrolled high-cardinality database.
Why This Matters Operationally
GPU incidents cross several ownership boundaries. The platform team owns Kubernetes, the infrastructure team owns GPU nodes and drivers, the application team owns model code and data pipelines, and another team may own Prometheus, Grafana, or on-call routing.
Without a shared telemetry model, every team sees a different fragment of the problem.
The application team sees slow requests. Kubernetes sees a Running pod. The GPU node sees memory allocated. DCGM may show low engine activity, power throttling, XID events, or a rising hardware error counter. Prometheus may have the data, but a dashboard that aggregates everything at cluster level can hide the affected device and workload.
The monitoring stack therefore needs to preserve four layers of context:
Layer
Questions the monitoring design must answer
Fleet
Which nodes, GPUs, exporters, and Prometheus targets are healthy?
Device
What are utilization, memory, temperature, power, clocks, errors, and throttling signals for this GPU or MIG instance?
Workload
Which namespace, pod, container, application, team, or job is associated with the device?
Service
Did workload throughput, latency, queue depth, or job completion time change at the same time?
DCGM Exporter covers the GPU and part of the workload layer. It does not replace application metrics, request traces, storage monitoring, network telemetry, or scheduler visibility. The most useful Grafana dashboard places GPU behavior beside the service indicators that explain whether that behavior is good or bad.
Symptoms and Risks
Before changing the monitoring stack, confirm the failure mode. The remediation for a missing exporter is different from the remediation for a label mismatch, unsupported metric, or overloaded Prometheus server.
Symptom
Likely cause
Operational risk
No DCGM metrics anywhere
Exporter missing, exporter failing, GPU runtime unavailable, or Prometheus not scraping
Hardware and workload incidents are invisible
Exporter pods are Running but Prometheus has no target
ServiceMonitor is not selected, Service labels do not match, namespace selection is wrong, or CRD is missing
False confidence because collection appears deployed
Fleet metrics exist but pod labels are empty
Kubernetes mapping disabled, kubelet pod-resources path unavailable, workload no longer owns the GPU, or metadata enrichment not enabled
Operators cannot identify the affected workload
Utilization exists but ECC or retired-page metrics do not
Collector file does not include those fields, hardware does not support them, or field names differ by DCGM release
Hardware degradation may not trigger alerts
Grafana shows duplicate or confusing per-pod values
Time-slicing, shared devices, duplicated labels, or incorrect aggregation
Teams may treat device-wide activity as isolated pod accounting
Prometheus memory or storage grows rapidly
Too many pod labels, unstable label values, short-lived workloads, or excessive scrape frequency
Monitoring becomes its own reliability problem
Low utilization alert fires constantly
Alert ignores workload schedule, queue depth, application throughput, or intentional idle periods
Alert fatigue and wasted investigation effort
The first safety principle is simple: do not add another exporter until you know whether NVIDIA GPU Operator already manages one.
GPU Telemetry Architecture
The important point in the following design is that DCGM Exporter runs near the GPU, while Prometheus, Grafana, and alerting remain shared platform services. Kubernetes metadata enrichment connects device telemetry to the pod that holds the GPU allocation.
DCGM Exporter can run with an embedded host engine or connect to an existing DCGM host engine. Appliances and systems that already run nv-hostengine require special care because the DCGM client in the exporter must remain compatible with the host engine. Treat that as a version-controlled integration, not a casual container replacement.
Prerequisites and Safety Checks
Complete these checks before changing the cluster.
Confirm the GPU Software Path
Verify that the GPU is visible on each target node and that Kubernetes can allocate it.
kubectl get nodes -L nvidia.com/gpu.present,nvidia.com/gpu.count,nvidia.com/mig.config
kubectl get pods -A -o wide | grep -E ‘nvidia|gpu’
kubectl get daemonset -A | grep -E ‘dcgm|nvidia’
Where NVIDIA GPU Operator is installed, also confirm the ClusterPolicy resource.
kubectl get clusterpolicy
On a representative GPU node, capture the driver and device state through your approved privileged administration method.
nvidia-smi
nvidia-smi -L
Successful output should list the expected GPU or MIG devices without driver communication errors.
Confirm the Existing Monitoring Stack
Identify the Prometheus implementation, Operator release, namespace, and ServiceMonitor selection behavior.
kubectl get crd servicemonitors.monitoring.coreos.com
kubectl get prometheus -A
kubectl get servicemonitor -A
kubectl get prometheusrule -A
helm list -A | grep -E ‘prometheus|grafana|gpu-operator|dcgm’
Do not assume that every ServiceMonitor is automatically selected. Prometheus resources can filter ServiceMonitors by label and namespace. Record the selector before creating or changing telemetry resources.
kubectl get prometheus -A -o yaml | grep -A12 -E ‘serviceMonitorSelector|serviceMonitorNamespaceSelector’
Capture a Rollback Baseline
Export the current Helm values and Kubernetes objects before change.
helm get values “$GPU_OPERATOR_RELEASE” -n “$GPU_OPERATOR_NAMESPACE” -o yaml
> gpu-operator-values-before.yaml
kubectl get clusterpolicy -o yaml > clusterpolicy-before.yaml
kubectl get servicemonitor -A -o yaml > servicemonitors-before.yaml
kubectl get prometheusrule -A -o yaml > prometheusrules-before.yaml
Replace the environment variables with the actual release and namespace. If GPU Operator is not installed, omit those commands and capture the standalone exporter resources instead.
Define the Observation Window
Choose a known workload and record:
expected start and end time
namespace, workload, pod, and container
GPU UUID or MIG instance
expected throughput, latency, batch size, or job duration
whether the GPU is exclusively allocated, partitioned, or time-sliced
application owner and escalation path
This baseline prevents the team from interpreting normal idle time as a platform problem.
Runbook Stage: Choose the Correct Deployment Path
There are two valid patterns, but only one should manage the exporter on a given GPU node.
Use GPU Operator Integration When the Operator Is Present
A default GPU Operator installation deploys DCGM Exporter on GPU worker nodes. Confirm the existing DaemonSet before changing Helm values.
kubectl get daemonset -A | grep dcgm-exporter
kubectl get pods -A -l app=nvidia-dcgm-exporter -o wide
kubectl get service -A | grep dcgm-exporter
kubectl get servicemonitor -A | grep dcgm
Label keys can vary across releases, so use kubectl get daemonset -A –show-labels when the label selector returns no results.
For an Operator-managed deployment, preserve the existing release values and add only the required telemetry settings through the same Helm or GitOps workflow that owns the Operator.
dcgmExporter:
enabled: true
serviceMonitor:
enabled: true
interval: 15s
scrapeTimeout: 10s
additionalLabels:
release: kube-prometheus-stack
enablePodLabels: true
enablePodUID: true
podLabelAllowlistRegex:
– “^app\.kubernetes\.io/(name|instance|component)$”
– “^team$”
– “^environment$”
Change the release label to the value selected by your Prometheus instance. Do not copy the example blindly. In some environments, Prometheus accepts ServiceMonitors without an additional release label.
Apply the values through the controlled release process.
helm upgrade “$GPU_OPERATOR_RELEASE” nvidia/gpu-operator
-n “$GPU_OPERATOR_NAMESPACE”
–reuse-values
-f gpu-operator-monitoring-values.yaml
–version “$GPU_OPERATOR_CHART_VERSION”
Pin the chart version already approved for the environment. Do not introduce an Operator upgrade as an unplanned side effect of enabling monitoring.
Install Standalone DCGM Exporter When GPU Operator Does Not Manage It
Use the standalone chart only when no Operator-managed exporter exists on those nodes.
export DCGM_EXPORTER_HELM_REPO=”<NVIDIA DCGM Exporter Helm repository>”
export DCGM_EXPORTER_CHART_VERSION=”<validated chart version>”
helm repo add gpu-helm-charts “$DCGM_EXPORTER_HELM_REPO”
helm repo update
helm upgrade –install dcgm-exporter gpu-helm-charts/dcgm-exporter
–namespace gpu-monitoring
–create-namespace
–version “$DCGM_EXPORTER_CHART_VERSION”
-f dcgm-exporter-values.yaml
A production values file should define scrape behavior, resource requests, node placement, pod metadata policy, and the exact metric collector set.
serviceMonitor:
enabled: true
interval: 15s
scrapeTimeout: 10s
additionalLabels:
release: kube-prometheus-stack
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
kubernetes:
enablePodLabels: true
enablePodUID: true
podLabelAllowlistRegex:
– “^app\.kubernetes\.io/(name|instance|component)$”
– “^team$”
– “^environment$”
nodeSelector:
nvidia.com/gpu.present: “true”
The chart already tolerates common GPU node taints in many releases, but verify the rendered DaemonSet against your own node taints.
helm template dcgm-exporter gpu-helm-charts/dcgm-exporter
–namespace gpu-monitoring
–version “$DCGM_EXPORTER_CHART_VERSION”
-f dcgm-exporter-values.yaml
> rendered-dcgm-exporter.yaml
kubectl apply –dry-run=server -f rendered-dcgm-exporter.yaml
Successful validation means the manifests are accepted by the API server and schedule only on intended GPU nodes.
Runbook Stage: Configure a Health-Focused Metric Set
DCGM Exporter reads a collector definition that specifies which DCGM fields become Prometheus metrics. The default set is useful, but operators should inspect it rather than assume every health field is enabled.
A controlled collector set can include utilization, memory, temperature, power, clocks, XID, ECC, retired pages, remapped rows, and selected profiling fields.
customMetrics: |
# Core utilization and memory
DCGM_FI_DEV_GPU_UTIL, gauge, GPU utilization in percent.
DCGM_FI_DEV_MEM_COPY_UTIL, gauge, Memory copy utilization in percent.
DCGM_FI_DEV_FB_USED, gauge, Framebuffer memory used in MiB.
DCGM_FI_DEV_FB_FREE, gauge, Framebuffer memory free in MiB.
# Temperature, power, and clocks
DCGM_FI_DEV_GPU_TEMP, gauge, GPU temperature in Celsius.
DCGM_FI_DEV_MEMORY_TEMP, gauge, Memory temperature in Celsius.
DCGM_FI_DEV_POWER_USAGE, gauge, Board power draw in watts.
DCGM_FI_DEV_SM_CLOCK, gauge, SM clock frequency in MHz.
DCGM_FI_DEV_MEM_CLOCK, gauge, Memory clock frequency in MHz.
# Device and transport health
DCGM_FI_DEV_XID_ERRORS, gauge, Last XID error observed.
DCGM_FI_DEV_PCIE_REPLAY_COUNTER, counter, Total PCIe replay count.
DCGM_FI_DEV_ECC_SBE_VOL_TOTAL, counter, Volatile single-bit ECC errors.
DCGM_FI_DEV_ECC_DBE_VOL_TOTAL, counter, Volatile double-bit ECC errors.
DCGM_FI_DEV_ECC_SBE_AGG_TOTAL, counter, Aggregate single-bit ECC errors.
DCGM_FI_DEV_ECC_DBE_AGG_TOTAL, counter, Aggregate double-bit ECC errors.
DCGM_FI_DEV_RETIRED_SBE, counter, Pages retired for single-bit errors.
DCGM_FI_DEV_RETIRED_DBE, counter, Pages retired for double-bit errors.
DCGM_FI_DEV_RETIRED_PENDING, counter, Pages pending retirement.
DCGM_FI_DEV_UNCORRECTABLE_REMAPPED_ROWS, counter, Uncorrectable remapped rows.
DCGM_FI_DEV_CORRECTABLE_REMAPPED_ROWS, counter, Correctable remapped rows.
DCGM_FI_DEV_ROW_REMAP_FAILURE, gauge, Row remapping failure state.
# Throttling and workload behavior
DCGM_FI_DEV_POWER_VIOLATION, counter, Time throttled by power constraint.
DCGM_FI_DEV_THERMAL_VIOLATION, counter, Time throttled by thermal constraint.
DCGM_FI_DEV_RELIABILITY_VIOLATION, counter, Time throttled by reliability constraint.
DCGM_FI_PROF_GR_ENGINE_ACTIVE, gauge, Ratio of time the graphics engine is active.
DCGM_FI_PROF_PIPE_TENSOR_ACTIVE, gauge, Ratio of tensor pipe cycles active.
DCGM_FI_PROF_DRAM_ACTIVE, gauge, Ratio of time the device memory interface is active.
The exact chart key used to supply custom metrics depends on the deployment path and chart release. In the current standalone chart, customMetrics replaces the complete default collector list. It is not additive. Preserve every default metric you still need.
Some fields are hardware-dependent. A missing ECC, temperature, profiling, or interconnect series does not automatically mean the exporter is broken. Confirm support for the installed GPU model and DCGM release before treating absence as a collection failure.
Profiling fields can require elevated container capabilities. Treat changes to security context as a security review item, not merely a monitoring tweak.
Runbook Stage: Validate the ServiceMonitor
A ServiceMonitor tells Prometheus Operator which Kubernetes Service to discover and which named port to scrape. Three selectors must align:
the Prometheus resource must select the ServiceMonitor
the ServiceMonitor must select the DCGM Exporter Service
the endpoint port name must match the Service port name
Inspect the live objects first.
kubectl get service -A | grep dcgm
kubectl get servicemonitor -A | grep dcgm
kubectl describe servicemonitor -n gpu-monitoring dcgm-exporter
kubectl get service -n gpu-monitoring dcgm-exporter -o yaml
When the chart does not create a ServiceMonitor, use a manifest like the following and modify every label to match the live Service and Prometheus selectors.
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: dcgm-exporter
namespace: gpu-monitoring
labels:
release: kube-prometheus-stack
spec:
namespaceSelector:
matchNames:
– gpu-monitoring
selector:
matchLabels:
app.kubernetes.io/name: dcgm-exporter
endpoints:
– port: metrics
path: /metrics
interval: 15s
scrapeTimeout: 10s
The value under endpoints.port is a Service port name, not the number 9400. A mismatched name is one of the most common reasons an apparently correct ServiceMonitor produces no targets.
Apply and inspect the object.
kubectl apply -f dcgm-exporter-servicemonitor.yaml
kubectl get servicemonitor -n gpu-monitoring dcgm-exporter -o yaml
kubectl get endpointslice -n gpu-monitoring -l kubernetes.io/service-name=dcgm-exporter
A healthy configuration should show one endpoint for each intended exporter pod.
Runbook Stage: Prove Metrics Reach Prometheus
Validate each hop separately rather than jumping directly to Grafana.
Validate the Exporter Endpoint
Port-forward one exporter Service or pod through an approved administration session.
kubectl port-forward -n “$DCGM_NAMESPACE” service/”$DCGM_SERVICE” 9400:9400
From the same workstation, inspect representative metrics.
curl -s localhost:9400/metrics | grep -E
‘DCGM_FI_DEV_GPU_UTIL|DCGM_FI_DEV_FB_USED|DCGM_FI_DEV_GPU_TEMP|DCGM_FI_DEV_XID_ERRORS’
Expected output includes Prometheus samples with labels such as GPU index, UUID, hostname, and, when a workload owns the device, Kubernetes namespace, pod, and container metadata.
Validate the Prometheus Target
In the Prometheus targets view, confirm that the DCGM Exporter target is UP. Then query a known metric.
DCGM_FI_DEV_GPU_UTIL
Use a specific GPU UUID or node label when many series exist.
DCGM_FI_DEV_GPU_UTIL{UUID=”<gpu-uuid>”}
If the exporter endpoint works but Prometheus has no series, inspect:
ServiceMonitor labels
Service labels
namespace selectors
endpoint port name
NetworkPolicy
Prometheus target discovery
TLS or authentication configuration
scrape timeout
Do not troubleshoot Grafana until this gate passes.
Runbook Stage: Build the Grafana Dashboard
Grafana has native Prometheus support. The dashboard should be designed around operator decisions, not around the number of available metrics.
Create Useful Dashboard Variables
Recommended variables include:
cluster
namespace
node or Hostname
GPU UUID
GPU index
MIG profile and instance identifiers
pod
application
team
environment
Use low-cardinality, controlled labels for variables. Avoid pod UID as a primary human-facing selector unless it is needed for incident precision.
Build the Dashboard in Operational Rows
Dashboard row
Recommended panels
Operator question
Fleet coverage
exporter targets, GPU count, missing nodes, scrape duration
Are all intended devices being monitored?
Utilization
GPU utilization, graphics engine active, tensor activity, DRAM activity
Is the GPU executing useful work, and what resource is active?
Memory
used, free, utilization percentage, allocation by workload
Is memory pressure limiting the workload, or is memory allocated while compute is idle?
Thermals and power
GPU temperature, memory temperature, power draw, violation counters
Is the device approaching a thermal or power constraint?
Clocks
SM clock, memory clock, clock changes alongside load
Are clocks behaving as expected for the workload and power state?
Hardware health
XID, ECC, retired pages, remapped rows, PCIe replays
Is this an application issue or a device or transport issue?
Workload attribution
top namespaces, pods, applications, teams, MIG instances
Who owns the activity and who should be engaged?
Service correlation
latency, throughput, queue depth, batch size, job progress
Did GPU behavior affect the service outcome?
Use PromQL That Preserves Device Context
GPU utilization over a five-minute window:
avg_over_time(DCGM_FI_DEV_GPU_UTIL[5m])
Framebuffer memory usage percentage:
100 * DCGM_FI_DEV_FB_USED
/
(DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE)
GPU temperature by node and device:
max by (Hostname, gpu, UUID) (DCGM_FI_DEV_GPU_TEMP)
Average power draw:
avg_over_time(DCGM_FI_DEV_POWER_USAGE[5m])
Per-pod memory allocation:
sum by (namespace, pod, container) (
DCGM_FI_DEV_FB_USED{pod!=””}
)
Top workloads by average GPU utilization:
topk(
10,
avg_over_time(DCGM_FI_DEV_GPU_UTIL{pod!=””}[15m])
)
These queries assume the exporter emits the referenced labels. Inspect a live series before building variables or aggregations.
Per-Pod and Per-Workload Visibility
DCGM Exporter can use the kubelet pod-resources interface to associate an allocated GPU with Kubernetes workload metadata. Newer GPU Operator releases also support optional pod label and pod UID enrichment.
That capability is useful, but it requires discipline.
Allowlist Stable Business Labels
Good label dimensions include:
application name
application instance
component
team
environment
workload class
queue or service tier when values are controlled
Avoid labels containing request IDs, build hashes, timestamps, arbitrary user values, or other rapidly changing identifiers. Every distinct label set becomes a new Prometheus time series.
Understand Shared GPU Attribution
Per-pod labels do not magically convert a device-level counter into perfect per-process accounting.
Exclusive full GPU allocation: Device telemetry usually maps cleanly to the owning pod.
MIG: Metrics can be exposed for individual GPU instances, which improves isolation and attribution.
Time-slicing: Multiple pods may share one physical GPU, while many DCGM metrics remain device-level. Do not interpret duplicated labels as exact per-pod usage.
Short-lived Jobs: Pod labels improve incident tracing but can create high series churn.
For chargeback or precise workload accounting, combine DCGM telemetry with scheduler records, job metadata, application metrics, and platform allocation data.
Alert Thresholds That Produce Action
Alerts should identify conditions that require an operator response. Dashboards can carry far more detail than paging rules.
Use the following as starting guidance, then calibrate against the GPU model, workload pattern, thermal design, and service-level objectives.
Signal
Starting condition
Severity guidance
Required action
Exporter target missing
Target down for 5 minutes
Critical when node is expected in service
Confirm pod, Service, ServiceMonitor, network, and driver state
Uncorrectable ECC
Any increase in double-bit error counter
Critical
Quarantine affected workload and follow hardware runbook
Pending retired pages
Value greater than zero
Critical
Preserve evidence, drain when required, assess reset or replacement path
Row remap failure
Value greater than zero
Critical
Escalate as hardware health issue
New XID event
New non-zero event within observation window
Warning or critical by XID class
Correlate kernel log, workload, and recovery guidance
Sustained high temperature
Above model-approved warning threshold for 10 minutes
Warning
Check airflow, fan state, neighboring load, and clocks
Thermal violation increase
Counter increases during workload
Warning or critical if service affected
Determine whether throttling explains performance degradation
Power violation increase
Counter increases during workload
Warning
Check configured power cap, clocks, workload demand, and facility policy
Sustained low utilization
Below workload baseline for 30 minutes while a job is expected to run
Informational or ticket, not page
Investigate workload concurrency, CPU, storage, network, batching, and synchronization
Memory near capacity
Above tested workload threshold for 10 minutes
Warning
Check batch size, model footprint, fragmentation, and eviction risk
Temperature thresholds should be based on model-specific limits and local policy. A fixed cluster-wide number can be too conservative for one platform and too aggressive for another.
Example Prometheus Rules
The following rule set demonstrates the structure. Modify labels, thresholds, and hardware fields to match the collected metric set.
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: nvidia-gpu-health
namespace: monitoring
labels:
release: kube-prometheus-stack
spec:
groups:
– name: nvidia-gpu-health
rules:
– alert: NvidiaGpuHighTemperature
expr: DCGM_FI_DEV_GPU_TEMP > 85
for: 10m
labels:
severity: warning
team: platform
annotations:
summary: NVIDIA GPU temperature is above the provisional threshold
description: Review model-specific temperature limits, cooling, clocks, and workload impact.
– alert: NvidiaGpuUncorrectableEccError
expr: increase(DCGM_FI_DEV_ECC_DBE_AGG_TOTAL[15m]) > 0
labels:
severity: critical
team: platform
annotations:
summary: NVIDIA GPU reported an uncorrectable ECC error
description: Preserve evidence and follow the hardware isolation runbook.
– alert: NvidiaGpuRetiredPagePending
expr: DCGM_FI_DEV_RETIRED_PENDING > 0
for: 5m
labels:
severity: critical
team: platform
annotations:
summary: NVIDIA GPU has a page pending retirement
description: Review ECC history, row remap state, workload impact, and recovery requirements.
– alert: NvidiaGpuThermalThrottling
expr: increase(DCGM_FI_DEV_THERMAL_VIOLATION[10m]) > 0
labels:
severity: warning
team: platform
annotations:
summary: NVIDIA GPU thermal throttling increased
description: Correlate temperature, clocks, power, node cooling, and application performance.
Use for durations to avoid paging on brief transients. Validate rule syntax before promotion.
promtool check rules nvidia-gpu-rules.yaml
kubectl apply –dry-run=server -f nvidia-gpu-rules.yaml
Where possible, test rules against recorded production-like series before enabling notifications.
Diagnosing Low GPU Utilization
Low utilization is a symptom, not a root cause. It can indicate a problem, but it can also represent a bursty service, a completed batch, intentional headroom, or a workload waiting for external input.
Use the following decision path.
Confirm the Workload Owns the GPU
kubectl get pod -n “$NAMESPACE” “$POD” -o yaml | grep -A8 -E ‘resources:|nvidia.com/gpu’
kubectl describe pod -n “$NAMESPACE” “$POD”
Check for pending scheduling, missing resource requests, unexpected MIG profile, device-plugin errors, or a completed workload that still appears in a dashboard time range.
Correlate Utilization with Memory
High memory allocation with low compute activity often points to one of these conditions:
model loaded but requests are not arriving
batch size or concurrency is too small
CPU preprocessing cannot feed the device
storage or network input is slow
the application is waiting at synchronization barriers
another service owns the request queue
kernels are too small or fragmented to keep the device active
Compare DCGM_FI_DEV_GPU_UTIL, DCGM_FI_PROF_GR_ENGINE_ACTIVE, DCGM_FI_PROF_DRAM_ACTIVE, framebuffer memory, application throughput, request queue depth, and CPU utilization over the same time range.
Check for Power or Thermal Constraints
A workload can show moderate utilization while running slower than expected because clocks are reduced.
Correlate:
GPU and memory temperature
SM and memory clocks
board power draw
thermal violation counter
power violation counter
reliability violation counter
node fan, cooling, and facility alerts
Do not conclude that the application is inefficient until throttling is ruled out.
Check the Workload Shape
For inference services, inspect request concurrency, dynamic batching, queue wait time, model instances, CPU thread pools, and upstream rate limits.
For training, inspect data-loader workers, storage throughput, network fabric, gradient synchronization, collective communication, checkpoint activity, and batch size.
For notebooks, low utilization may simply mean interactive use. Capacity policy should distinguish a reserved development GPU from a production service expected to sustain throughput.
Validation Steps
The monitoring implementation is complete only when each validation gate passes.
Exporter Validation
kubectl get pods -A -o wide | grep dcgm-exporter
kubectl logs -n “$DCGM_NAMESPACE” daemonset/”$DCGM_DAEMONSET” –tail=200
Pass criteria:
one healthy exporter pod on every intended GPU node
no repeated host-engine, driver, permission, or kubelet pod-resources errors
resource usage remains within configured requests and limits
Metric Validation
Run a known GPU workload and confirm these series change:
GPU utilization
framebuffer used and free
power draw
temperature
clocks
at least one engine or profiling metric when supported
namespace, pod, and container labels when exclusive allocation is used
Hardware health counters should remain stable in a healthy test. Do not inject errors into production merely to prove an alert.
Prometheus Validation
Pass criteria:
every expected target is UP
scrape duration remains below scrape timeout
sample count and series growth are acceptable
retention and storage growth remain within platform limits
rules load without evaluation errors
Grafana Validation
Pass criteria:
variables filter to the correct node, GPU, namespace, and pod
dashboard panels retain GPU UUID and workload identity
no panel silently aggregates healthy and unhealthy devices together
missing metrics are shown as unavailable, not zero
time range and timezone are clear during incident review
Alert Validation
Test notification routing with a safe synthetic rule or approved test condition. Confirm:
severity routes to the correct receiver
alert annotations identify node, GPU UUID, namespace, and pod when available
runbook ownership is clear
resolved notifications work as intended
maintenance silences do not suppress unrelated GPU incidents
Collecting Evidence Before Escalation
A vendor or infrastructure escalation should contain enough data to identify the device, reproduce the timeline, and separate application behavior from hardware health.
Collect the following before draining, rebooting, resetting, or replacing anything, unless immediate containment is required.
Incident Identity
incident start time, timezone, and duration
affected cluster, node, namespace, workload, pod, and container
GPU model, index, UUID, and MIG profile when applicable
user-visible impact such as latency, failed requests, job delay, or data corruption risk
whether the condition cleared, persisted, or returned
Software and Platform State
kubectl version
helm list -A | grep -E ‘gpu-operator|dcgm|prometheus|grafana’
kubectl get clusterpolicy -o yaml
kubectl get pods -A -o wide | grep -E ‘dcgm|nvidia’
nvidia-smi
nvidia-smi -q
Capture the NVIDIA driver, CUDA compatibility view, GPU Operator chart, DCGM Exporter image, Kubernetes version, container runtime, and relevant workload image.
Workload and Kubernetes Evidence
kubectl get pod -n “$NAMESPACE” “$POD” -o yaml
kubectl describe pod -n “$NAMESPACE” “$POD”
kubectl logs -n “$NAMESPACE” “$POD” –all-containers –timestamps
kubectl get events -n “$NAMESPACE” –sort-by=.lastTimestamp
kubectl describe node “$NODE”
Include resource requests, limits, scheduling events, restarts, exit codes, node pressure, and device-plugin messages.
GPU and Kernel Evidence
nvidia-smi -q -x > nvidia-smi-q.xml
dcgmi discovery -l > dcgm-discovery.txt
dcgmi health -c > dcgm-health.txt
dcgmi -v > dcgmi-version.txt
sudo nvidia-bug-report.sh
journalctl -k –since “$INCIDENT_START” > kernel-incident.log
Run active DCGM diagnostics only under the approved maintenance procedure. Diagnostic workloads can stress GPUs and interfere with production applications. Drain or isolate the device first when the test requires exclusive access.
Time-Series Evidence
Export or capture a consistent time window that includes at least:
30 minutes before the incident
the complete incident period
30 minutes after recovery or containment
Include raw or exported data for:
GPU utilization and engine activity
memory used and free
temperature and power
SM and memory clocks
XID and ECC signals
retired pages and row remapping
PCIe or NVLink errors when relevant
application latency, throughput, queue depth, and error rate
CPU, storage, network, and node pressure
A screenshot is useful for context, but raw query data is stronger evidence because it preserves values, labels, timestamps, and device identity.
Rollback and Fallback Guidance
Monitoring changes should be reversible without deleting historical data.
Roll Back a Helm Change
Inspect release history and return to the last known-good revision.
helm history “$RELEASE” -n “$NAMESPACE”
helm rollback “$RELEASE” “$REVISION” -n “$NAMESPACE”
Validate exporter pods and Prometheus targets after rollback.
Restore the Previous Collector Set
If custom metrics create unsupported-field errors, excessive scrape time, or unexpected cardinality, restore the prior values file or collector ConfigMap. Remember that a custom collector can replace the entire default set, so rollback must restore the complete previous list.
Disable Metadata Enrichment Without Disabling Device Monitoring
When pod label enrichment causes cardinality growth, first disable enablePodLabels or tighten podLabelAllowlistRegex. Preserve base device telemetry while the label policy is corrected.
Remove a Duplicate Standalone Exporter
When GPU Operator already manages DCGM Exporter, remove the unintended standalone release after confirming the Operator-managed targets are healthy.
helm uninstall dcgm-exporter -n gpu-monitoring
kubectl get daemonset -A | grep dcgm-exporter
Fallback When Prometheus Operator Is Unavailable
DCGM Exporter still exposes a Prometheus-formatted endpoint. A temporary static scrape configuration can be used where platform policy permits, but the long-term design should return to declarative target discovery and controlled rule management.
Do not disable GPU health monitoring as a troubleshooting shortcut. Replace a failing collection path with a validated fallback and document the visibility gap.
Operational Handoff Checklist
Before handing the stack to operations, confirm:
GPU Operator or standalone exporter ownership is documented
chart and image versions are pinned through the platform release process
ServiceMonitor selection rules are recorded
custom collector fields are version-controlled
pod label allowlists are approved
Prometheus series growth has been measured
dashboard ownership and folder permissions are defined
alert thresholds have workload and hardware context
each alert links to an internal runbook in the monitoring platform
evidence retention meets support and incident-review needs
active DCGM diagnostic procedures require an approved maintenance state
rollback values and previous collector files are retained
The monitoring stack is ready when another operator can identify the affected GPU and workload, determine whether the problem is collection, scheduling, application behavior, throttling, or hardware health, and preserve evidence without relying on the person who built the dashboard.
Conclusion
DCGM Exporter, Prometheus, and Grafana provide a strong foundation for NVIDIA GPU observability, but the technology only becomes operationally useful when the collection path is treated as a controlled system.
Start by choosing one exporter owner per GPU node. Reuse the GPU Operator integration when it exists. Validate the ServiceMonitor and Prometheus target before building dashboards. Select a metric set that includes the hardware health indicators your support model requires, and do not assume disabled ECC or retired-page fields are already available.
Build Grafana around fleet coverage, device behavior, workload attribution, and service outcomes. Use pod metadata carefully, especially in time-sliced environments where device-wide metrics should not be presented as precise per-pod accounting. Alert on conditions that lead to action, while keeping low utilization primarily as a diagnostic and capacity signal.
Most importantly, define the evidence package before the incident. GPU UUIDs, workload identity, software versions, DCGM health, kernel logs, time-series data, and application impact are what turn a vague performance complaint into a supportable engineering case.
External References
NVIDIA: About GPU TelemetryCanonical URL: https://docs.nvidia.com/datacenter/cloud-native/gpu-telemetry/latest/index.html
NVIDIA: DCGM-ExporterCanonical URL: https://docs.nvidia.com/datacenter/dcgm/latest/gpu-telemetry/dcgm-exporter.html
NVIDIA: Installing the NVIDIA GPU OperatorCanonical URL: https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/getting-started.html
NVIDIA: Setting up PrometheusCanonical URL: https://docs.nvidia.com/datacenter/cloud-native/gpu-telemetry/latest/kube-prometheus.html
NVIDIA: Feature OverviewCanonical URL: https://docs.nvidia.com/datacenter/dcgm/latest/user-guide/feature-overview.html
NVIDIA GitHub: dcgm-exporter default-counters.csvCanonical URL: https://github.com/NVIDIA/dcgm-exporter/blob/main/etc/default-counters.csv
Prometheus Operator: API ReferenceCanonical URL: https://prometheus-operator.dev/docs/api-reference/api/
Prometheus: Alerting RulesCanonical URL: https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/
Grafana Labs: Prometheus Data SourceCanonical URL: https://grafana.com/docs/grafana/latest/datasources/prometheus/
Grafana Labs: Grafana AlertingCanonical URL: https://grafana.com/docs/grafana/latest/alerting/
How to Install and Configure VMware NSX with an NVIDIA Spectrum Network Fabric
TL;DR A reliable VMware NSX deployment on NVIDIA networking depends less on clicking through the NSX Manager wizard and more on getting…
Next PostHow to Deploy NVIDIA vGPU on VMware vSphere and Validate the ConfigurationTL;DR Deploying NVIDIA vGPU on VMware vSphere is not simply a matter of installing a driver and attaching a virtual PCI device. The server, physical GPU, ESXi build, NVIDIA vGPU…
The post How to Monitor NVIDIA GPUs with DCGM Exporter, Prometheus, and Grafana appeared first on Digital Thought Disruption.

