GPU telemetry at scale generates high-cardinality metric series:
per-GPU metrics × GPUs/node × nodes × per-rank NCCL × per-model inference = millions of series
A 1,000-node cluster with 8 GPUs each, running 4 models with tensor parallelism, produces ~200,000+ unique time series at 15s scrape intervals.
Enable downsampling in values.yaml:
otelCollector:
enabled: true
intervalSeconds: 60 # aggregate to 1-minute resolutionThis reduces data volume by 4x (from 15s scrape interval).
Drop high-cardinality attributes when not needed:
gpu.uuid: Unique per GPU; usegpu.indexwithin a node (sufficient for dashboards). Only keepgpu.uuidfor fleet-wide deduplication.gpu.model: Same for all GPUs on a node — move to resource attribute, not data-point.nccl.rank: Keep for straggler analysis; drop in production cost-saving mode.
Configure in the OTel Collector filter/drop_noisy processor.
Enable only the monitors you need in Helm:
collectors:
nvidia: true # always on
amd: false # only on AMD nodes
gaudi: false # only on Gaudi nodes
vllm: true # only on inference nodes
triton: false
sglang: false
tgi: false
fleetHealth:
enabled: true # always on (lightweight)
costMonitor:
enabled: false # only on nodes where cost tracking mattersL9GPUTrainingMonitor emits per-step metrics. For long training runs:
- Set export interval to 30s (default) — this aggregates ~100 steps into one export
- Gradient norm: track only the max per export window
- MFU: track the average per window (stable metric)
Pre-aggregate at the backend to reduce query-time cardinality:
# Per-node GPU utilization average (aggregates away gpu.index)
avg by (host.name) (gpu.utilization)
# Fleet-wide health score histogram
histogram_quantile(0.05, sum by (le) (gpu.health.score))
| Deployment Size | Estimated Series | Recommended intervalSeconds |
|---|---|---|
| < 100 GPUs | ~10K | 0 (disabled) |
| 100–1,000 GPUs | ~100K | 30 |
| 1,000–10,000 GPUs | ~1M | 60 |
| > 10,000 GPUs | ~10M+ | 60 + dimension pruning |