Stack de monitorização: Prometheus, Grafana, DCGM e Loki para servidores de IA
Um servidor de IA que ninguém está a vigiar é um servidor que faz throttling em silêncio, que perde VRAM, que acumula erros ECC ou que é morto pelo OOM killer às 03:00 — e só se dá conta três dias depois, quando alguém pergunta porque é que o fine-tune produziu lixo. A maioria dos piores modos de falha numa máquina com GPU é invisível do lado da aplicação: o throttling térmico não escreve para o stderr, as correções ECC não fazem rebentar nada de imediato, o OOM killer come um processo e o orquestrador reinicia-o sem alarde. Sem métricas do próprio hardware, nada disto é visível até já ter custado uma semana.
O conjunto habitual de ferramentas de sysadmin (htop, df, uptime, syslog) não chega. A GPU é o componente mais caro do chassis e o mais propenso a falhar, e tem uma stack de telemetria própria que exige ligações explícitas. Este artigo é a proposta assumida para essa stack — Prometheus, Grafana, DCGM-exporter, node_exporter, Loki e Alertmanager — empacotada numa única implementação docker-compose que corremos em todos os servidores de IA Kentino que expedimos.
O público é quem está a pôr de pé um servidor de IA de 4 ou 8 GPU, sabe escrever um ficheiro docker-compose e quer a resposta a "o que devo realmente monitorizar e a partir de que limiar devo gerar alarme."
A stack padrão em 2026
Cinco componentes fazem quase todo o trabalho. Tudo o resto é acessório.
| Componente | Função | Consumo em repouso |
|---|---|---|
| Prometheus | Base de dados de séries temporais + orquestrador de recolha | ~150 MB RAM, ~3 MB/s |
| Grafana | Dashboards, interface de alertas | ~120 MB RAM |
| DCGM-exporter | Métricas da GPU (temperatura, utilização, consumo, memória, ECC, XID) | ~30 MB RAM, <0.1% CPU |
| node_exporter | Métricas do sistema (CPU, RAM, disco, rede, hwmon) | ~15 MB RAM |
| Loki + Promtail | Agregação de registos e respetivo expedidor | ~100 MB RAM |
| Alertmanager | Encaminhamento de alertas (e-mail, Slack, PagerDuty, webhook) | ~25 MB RAM |
No total, bem abaixo de 0.5% de um núcleo de CPU num EPYC de 96 núcleos e cerca de 700 MB de RAM. Num servidor de 256 GB com 8 GPU, isto é um erro de arredondamento. O argumento de que "a monitorização rouba ciclos ao treino" deixou de ser verdade por volta de 2019.
A única decisão de arquitetura que vale a pena tomar à partida: coloque a stack numa VM de gestão separada ou numa máquina pequena, e não no próprio servidor de GPU. Um mini-PC dedicado, um NUC, um nó de serviço EPYC ou uma VM no hipervisor do laboratório — qualquer coisa que não seja a máquina com as GPU. Por duas razões: quando o servidor de GPU vai abaixo (kernel panic por falta de memória, disparo da fonte de alimentação, encerramento térmico) continua a querer o histórico de métricas para diagnosticar o que aconteceu, e não quer um treino descontrolado a competir pela memória com o Prometheus e a disparar o alerta do próprio. O DCGM-exporter e o node_exporter correm no anfitrião com GPU (têm de correr — leem dispositivos locais); o Prometheus, o Grafana, o Loki e o Alertmanager correm na VM de gestão e recolhem para dentro.
DCGM-exporter — a peça que não se pode dispensar
O Data Center GPU Manager (DCGM) da NVIDIA é a fonte suportada e autoritativa de telemetria da GPU. O contentor dcgm-exporter expõe as métricas do DCGM em formato Prometheus na porta 9400. É o componente mais importante de toda a stack e é aquilo que fazer polling com nvidia-smi nunca irá substituir.
Instale a partir do contentor NGC (nvcr.io/nvidia/k8s/dcgm-exporter, atualmente na versão 4.x em meados de 2026) ou do Helm chart oficial para Kubernetes. Em Docker simples, basta um docker run --gpus all --rm; o daemon passa então a publicar ~80 métricas em :9400/metrics. As que realmente importam, por ordem da frequência com que apanham problemas reais:
| Métrica | O que indica | Limiar de alarme |
|---|---|---|
DCGM_FI_DEV_GPU_TEMP |
Temperatura do núcleo da GPU (°C) | > 80 °C aviso, 87 °C crítico |
DCGM_FI_DEV_MEMORY_TEMP |
Temperatura da VRAM / junção de memória (°C) | > 95 °C aviso, 105 °C crítico |
DCGM_FI_DEV_GPU_UTIL |
Utilização de cálculo dos SM (%) | < 5% com VRAM alocada → processo bloqueado |
DCGM_FI_DEV_FB_USED |
Frame buffer (VRAM) utilizado, em MiB | > 95% do total |
DCGM_FI_DEV_POWER_USAGE |
Consumo atual (W) | > TDP × 0.98 de forma sustentada |
DCGM_FI_DEV_PCIE_TX_THROUGHPUT |
Largura de banda PCIe TX (KiB/s) | teto sustentado = regressão de riser/pistas |
DCGM_FI_DEV_ECC_SBE_VOL_TOTAL |
Contagem de erros ECC corrigíveis | aumento da taxa > 10× face à linha de base |
DCGM_FI_DEV_ECC_DBE_VOL_TOTAL |
Contagem de erros ECC não corrigíveis | qualquer |
DCGM_FI_DEV_THERMAL_VIOLATION |
ns acumulados em throttling térmico | taxa > 0 |
DCGM_FI_DEV_POWER_VIOLATION |
ns acumulados em throttling por consumo | taxa > 0 |
DCGM_FI_DEV_XID_ERRORS |
Contagem de erros XID (falhas de driver / hardware) | qualquer |
Os contadores de throttling são a funcionalidade decisiva. DCGM_FI_DEV_THERMAL_VIOLATION é um contador monotónico dos nanossegundos que a GPU passou em throttling. Calcule a sua taxa numa janela de 5 minutos e tem a resposta exata a "o meu servidor está neste momento limitado termicamente." Sem isso, está a adivinhar apenas pela temperatura, que engana — uma 4090 entra em throttling aos 83 °C numa carga sustentada, independentemente do que o painel de temperatura mostre.
Duas particularidades conhecidas do DCGM-exporter a ter em conta em 2026: alguns códigos XID (nomeadamente o XID 62) nem sempre aparecem através de DCGM_FI_DEV_XID_ERRORS e a métrica é um gauge do último XID observado — pelo que pode não voltar a zero após uma recuperação sem reiniciar o exporter. A mitigação é vigiar também o kernel ring buffer através do Loki, à procura da string literal NVRM: Xid (mais sobre isto abaixo). Cinto e suspensórios.
Em placas puramente de consumo (RTX 4090, 5090) algumas funcionalidades de centro de dados do DCGM só funcionam em parte — não existe MIG, o NVLink está ausente nos modelos Blackwell de consumo e certos contadores ECC devolvem zero. O DCGM continua a funcionar e reporta o que está exposto; a alternativa leve da comunidade, nvidia_gpu_exporter (que faz scraping de nvidia-smi), é uma solução de recurso viável se não quiser a cadeia de dependências do DCGM. Para as Pro 6000 Blackwell, L40 e L4 — tudo o que seja da linha de centro de dados / pro — use o DCGM e não o wrapper.
node_exporter — a metade do sistema
As métricas da GPU contam apenas metade da história. O node_exporter cobre o resto:
| Família de métricas | Porque importa numa máquina de IA |
|---|---|
node_cpu_seconds_total |
Saturação do CPU — os tokenizers e dataloaders do vLLM adoram CPU |
node_memory_MemAvailable_bytes |
RAM do sistema — os fluxos de treino e de inferência têm fugas |
node_disk_io_time_seconds_total |
Saturação do NVMe — carregamento de datasets, escrita de checkpoints |
node_filesystem_avail_bytes |
Espaço em disco — os pesos dos modelos ocupam 50–150 GB cada (ver também L04) |
node_network_receive_bytes_total |
Débito de rede — treino multinó, clientes de inferência |
node_load_average |
Indicador rápido do estado de saúde |
node_hwmon_temp_celsius |
Temperaturas do CPU e do chipset e, em algumas placas, da fonte de alimentação |
node_vmstat_oom_kill |
O OOM killer disparou — o alerta mais esquecido em qualquer implementação |
O modo de falha "RAM do sistema esgotada, o OOM killer leva o vLLM, o contentor reinicia sem alarde" é apanhado aqui, e não pelo DCGM. Vigie node_memory_MemAvailable_bytes e gere alarme quando descer abaixo de 5% do total. Em Linux, o killer dispara perto dos 0% por predefinição, mas a essa altura o processo já morreu.
Prometheus — configuração, retenção, dimensionamento
O Prometheus é a base de dados de séries temporais e o orquestrador de recolha. As predefinições são razoáveis; as duas definições que vale a pena mudar logo no primeiro dia são o intervalo de recolha e a retenção.
Um intervalo de recolha de 15 segundos é o ponto de partida certo para um servidor de IA: rápido o suficiente para apanhar um pico térmico antes de se tornar um throttling sustentado, lento o suficiente para o custo das séries temporais se manter contido. A retenção está predefinida em 15 dias; 30 dias é um número melhor num contexto de guia de construção, em que pode querer comparar o comportamento de hoje com uma afinação do mês passado.
Orçamento de armazenamento com recolha a 15 s, ~80 métricas DCGM × N GPU + ~400 métricas do node_exporter + ~50 métricas do vLLM: cerca de 1.5–2 GB por semana, ou seja, 30 dias ficam em 6–10 GB numa máquina de 8 GPU. Defina a retenção por tempo e por tamanho, como salvaguarda:
command:
- "--storage.tsdb.retention.time=30d"
- "--storage.tsdb.retention.size=20GB"
Qualquer um dos limites desencadeia a compactação; vence o que for atingido primeiro. Uma alocação de 100 GB dá-lhe mais de um ano de folga sem ter de pensar no assunto.
Dashboards do Grafana — comece pelos já feitos
Não construa dashboards de raiz. A comunidade já o fez.
| Dashboard | ID em Grafana.com | O que cobre |
|---|---|---|
| NVIDIA DCGM Exporter Dashboard | 12239 | O oficial da NVIDIA — todas as métricas da GPU |
| Node Exporter Full | 1860 | CPU / RAM / disco / rede |
| Registos Loki / Promtail | 13639 | Pesquisa e exploração de registos |
| Serviço vLLM (comunidade) | varia | TTFT, TPOT, profundidade da fila, cache KV |
Importe primeiro o 12239 e o 1860. Cobrem ~90% daquilo que realmente quer ver e foram refinados ao longo de anos. Construa os seus próprios só ao fim de um mês, quando já souber que painéis abre de facto. As pequenas alterações que vale a pena fazer para o hardware de IA Kentino são: ajustar os painéis de limiar de temperatura da GPU para intervalos adequados ao Blackwell (a 5090 entra em throttling perto dos 87 °C, a RTX Pro 6000 mais perto dos 90 °C) e acrescentar um painel por slot PCIe a mostrar DCGM_FI_DEV_PCIE_LINK_GEN e DCGM_FI_DEV_PCIE_LINK_WIDTH para ver num relance se um riser desceu de x16 para x8.
Loki — registos que explicam o que as métricas mostram
As métricas dizem-lhe o que mudou; os registos dizem-lhe porquê. O Loki é a base de dados de registos do Grafana; o Promtail é o expedidor que segue os ficheiros e os envia. Aponte o Promtail para:
-
/var/log/syslogejournalctl -k— mensagens OOM do kernel, queixas do driver NVIDIA, dumps de XID -
/var/log/nvidia-installer.log— estado da instalação do driver - stdout do contentor vLLM (através do log driver JSON do Docker)
- Registos de aplicação de tudo o que o cliente executar
A consulta mais valiosa de todas no separador Explore do Grafana é:
{job="syslog"} |= "NVRM:"
Isto traz à superfície todas as mensagens do driver NVIDIA no kernel ring buffer — erros XID, falhas de ventoinha, eventos de placa caída do barramento, timeouts de RPC do GSP. Combine-a com o alerta Prometheus DCGM_FI_DEV_XID_ERRORS e tem a métrica estruturada e o detalhe não estruturado no mesmo painel.
Por predefinição, não enviamos os registos para fora do anfitrião. O Loki guarda-os localmente com retenção de 30 dias; quem está de piquete abre um túnel SSH para o Grafana quando é preciso. Os clientes que queiram registos centralizados de vários servidores podem apontar o Loki para S3 ou correr uma instância regional — isso é uma questão de implementação, não de arquitetura.
Métricas do vLLM e do SGLang — instrumente a aplicação, não apenas o metal
O DCGM diz-lhe que a GPU está ocupada. Não lhe diz se os pedidos de inferência respondem em 200 ms ou em 2 s. Para isso, instrumenta-se a camada de serviço.
O vLLM expõe /metrics nativamente na mesma porta da API OpenAI. Com as definições predefinidas, o endpoint em :8000/metrics publica métricas Prometheus com o prefixo vllm: (que passa a vllm_ após a recolha do Prometheus). As que vale a pena recolher:
| Métrica do vLLM | Significado |
|---|---|
vllm:e2e_request_latency_seconds |
Latência ponta a ponta do pedido (histograma) |
vllm:time_to_first_token_seconds |
TTFT — o número que os utilizadores realmente sentem |
vllm:time_per_output_token_seconds |
Velocidade de geração de tokens (histograma) |
vllm:num_requests_running |
Pedidos ativos em curso |
vllm:num_requests_waiting |
Profundidade da fila |
vllm:gpu_cache_usage_perc |
Utilização da cache KV (0–1) |
vllm:request_prompt_tokens |
Distribuição do comprimento do prompt |
A combinação vllm:num_requests_waiting > 0 e DCGM_FI_DEV_GPU_UTIL < 90% significa que a fila está a acumular enquanto a GPU está parada — normalmente um estrangulamento do tokenizer ou do escalonador, não de cálculo. Só se vê isso com ambas as métricas no mesmo dashboard, que é precisamente a razão de unificar a telemetria da aplicação e do hardware num só Prometheus.
O NVIDIA NIM expõe as mesmas métricas do vLLM em /v1/metrics sem lhes mudar o nome, pelo que os seus dashboards e regras de alerta de vLLM passam sem alterações para uma implementação servida por NIM. O SGLang publica um conjunto semelhante na sua própria porta (30000 por predefinição); o servidor HTTP do llama.cpp expõe um subconjunto mais pequeno. O Triton publica a sua própria taxonomia. Seja qual for o que servir, faça scraping da aplicação — e não apenas do hardware.
Regras do Alertmanager — as que realmente expedimos
Os dashboards são bonitos. Os alertas são úteis. As regras abaixo são as que apanharam problemas reais em hardware real de clientes.
groups:
- name: gpu
interval: 30s
rules:
- alert: GPUTempCritical
expr: DCGM_FI_DEV_GPU_TEMP > 87
for: 30s
labels: { severity: critical }
annotations:
summary: "GPU {{ $labels.gpu }} thermal critical ({{ $value }} °C)"
- alert: GPUThermalThrottling
expr: rate(DCGM_FI_DEV_THERMAL_VIOLATION[5m]) > 0
for: 1m
labels: { severity: warning }
- alert: GPUECCUncorrectable
expr: increase(DCGM_FI_DEV_ECC_DBE_VOL_TOTAL[10m]) > 0
labels: { severity: critical }
annotations:
summary: "GPU {{ $labels.gpu }} uncorrectable ECC — schedule replacement"
- alert: GPUXIDError
expr: increase(DCGM_FI_DEV_XID_ERRORS[5m]) > 0
labels: { severity: critical }
- alert: GPUPowerEnvelopeExceeded
expr: DCGM_FI_DEV_POWER_USAGE > 590 # 5090 nominal 575 W; alarm above sustained ceiling
for: 5m
labels: { severity: warning }
- alert: GPUIdleDuringWork
expr: DCGM_FI_DEV_GPU_UTIL < 5 and DCGM_FI_DEV_FB_USED > 1024
for: 10m
labels: { severity: warning }
annotations:
summary: "GPU {{ $labels.gpu }} idle with VRAM allocated — likely hung"
- name: system
interval: 30s
rules:
- alert: HostMemoryLow
expr: (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) < 0.05
for: 2m
labels: { severity: critical }
- alert: OOMKillerFired
expr: increase(node_vmstat_oom_kill[5m]) > 0
labels: { severity: critical }
- alert: ContainerRestartLoop
expr: rate(container_start_time_seconds[15m]) > 3
for: 10m
labels: { severity: warning }
- name: serving
interval: 30s
rules:
- alert: vLLMQueueBacklog
expr: vllm:num_requests_waiting > 10
for: 5m
labels: { severity: warning }
- alert: vLLMHighLatency
expr: histogram_quantile(0.95, rate(vllm:e2e_request_latency_seconds_bucket[5m])) > 10
for: 5m
labels: { severity: warning }
Decisões assumidas nessas regras:
- 87 °C como crítico para a temperatura da GPU. Na maioria das placas, uma 5090 entra em throttling na casa dos 80 e muitos graus. Se a sua sala não consegue manter as placas abaixo dos 80 °C em carga sustentada, tem um problema de AVAC e não de software.
- Qualquer ECC não corrigível chama quem está de piquete. Um único evento ECC de duplo bit invalida o que estiver nessa página de VRAM — um passo de treino fica errado, um resultado de inferência fica errado. A placa precisa de substituição, não de reinício.
-
GPUIdleDuringWorké o detetor de deadlock. > 1 GiB alocado e < 5% de utilização durante 10 minutos significa que alguma coisa está presa. Apanha bloqueios do lado do CUDA que a aplicação ignora alegremente. - O alerta do OOM killer é a regra mais esquecida em qualquer implementação. O Linux a matar o seu treino em silêncio e o Docker a reiniciá-lo sem alarde é o modo de falha que mais horas de engenharia desperdiça por ano. Torne-o bem audível.
- O ciclo de reinícios do contentor apanha ciclos de reinício do NIM e do vLLM que parecem saudáveis vistos de fora (o contentor está "a correr") mas que na realidade rebentam a cada carregamento do modelo.
Chassis e armazenamento — IPMI e SMART
O DCGM fica-se pela GPU. O node_exporter fica-se pelo sistema operativo. O resto do chassis — ventoinhas, fontes de alimentação, temperatura ambiente, saúde do armazenamento — exige mais dois exporters.
ipmi_exporter (prometheus-community) fala com o BMC através de IPMI/RMCP e expõe telemetria ao nível do chassis: RPM de cada ventoinha, tensão e corrente de entrada da fonte de alimentação, entradas do registo de eventos do sistema, temperatura ambiente à entrada, estado do watchdog do BMC. Num chassis Supermicro ou Bone64c com um BMC funcional, isto é meio dia de trabalho e apanha coisas que o DCGM literalmente não consegue ver — uma fonte de alimentação a falhar na configuração de 8 GPU com fonte dupla aparece como uma quebra de tensão nos dados dos sensores ipmi minutos antes de a GPU saltar para o XID 79. Corra-o no anfitrião (precisa de /dev/ipmi0) ou remotamente, com credenciais do BMC guardadas, segundo o padrão de exporter multi-alvo.
smartctl_exporter (ou o mais antigo smart_exporter) lê os atributos SMART de NVMe e SATA: indicador de desgaste do suporte, reserva disponível, temperatura, contagem de erros. As cargas de trabalho de IA são brutais para o NVMe — carregadores de datasets, escrita de checkpoints e caches do HuggingFace esgotam em meses os objetivos de desgaste empresariais em discos de gama de consumo. A métrica para alarme é nvme_available_spare a descer abaixo de 20% e nvme_percentage_used (o indicador de desgaste) a subir acima de 80%. A falha de disco é a segunda avaria de hardware mais comum num servidor de IA em carga, logo a seguir à categoria riser/fonte de alimentação.
Uma implementação completa de monitorização de IA da Kentino inclui ambos. O custo marginal é de minutos; o valor, da primeira vez que uma ventoinha falha em silêncio ou que um Samsung 990 Pro chega ao seu teto de DWPD, é de horas.
Um docker-compose real para a VM de gestão
O que realmente implementamos na máquina de gestão. Ajuste host.docker.internal (ou use o hostname/IP do servidor de GPU) para apontar o Prometheus às portas dos exporters do anfitrião com GPU.
version: "3.8"
networks:
monitoring: { driver: bridge }
volumes:
prometheus_data:
grafana_data:
loki_data:
services:
prometheus:
image: prom/prometheus:v3.0.0
restart: unless-stopped
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./rules:/etc/prometheus/rules:ro
- prometheus_data:/prometheus
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
- "--storage.tsdb.retention.time=30d"
- "--storage.tsdb.retention.size=20GB"
- "--web.enable-lifecycle"
ports: ["9090:9090"]
networks: [monitoring]
grafana:
image: grafana/grafana:11.4.0
restart: unless-stopped
environment:
- GF_SECURITY_ADMIN_PASSWORD__FILE=/run/secrets/grafana_pw
- GF_USERS_ALLOW_SIGN_UP=false
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning:ro
secrets: [grafana_pw]
ports: ["3000:3000"]
networks: [monitoring]
alertmanager:
image: prom/alertmanager:v0.28.0
restart: unless-stopped
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
ports: ["9093:9093"]
networks: [monitoring]
loki:
image: grafana/loki:3.3.0
restart: unless-stopped
command: -config.file=/etc/loki/loki.yml
volumes:
- ./loki.yml:/etc/loki/loki.yml:ro
- loki_data:/loki
ports: ["3100:3100"]
networks: [monitoring]
secrets:
grafana_pw: { file: ./secrets/grafana_pw.txt }
No próprio anfitrião com GPU (compose separado, no servidor de GPU):
services:
dcgm-exporter:
image: nvcr.io/nvidia/k8s/dcgm-exporter:4.5.1-4.8.0-ubuntu22.04
restart: unless-stopped
runtime: nvidia
environment: [NVIDIA_VISIBLE_DEVICES=all]
cap_add: [SYS_ADMIN]
ports: ["9400:9400"]
node-exporter:
image: prom/node-exporter:v1.9.0
restart: unless-stopped
pid: host
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- "--path.procfs=/host/proc"
- "--path.sysfs=/host/sys"
- "--path.rootfs=/rootfs"
ports: ["9100:9100"]
ipmi-exporter:
image: prometheuscommunity/ipmi-exporter:v1.10.0
restart: unless-stopped
privileged: true
volumes: ["/dev/ipmi0:/dev/ipmi0"]
ports: ["9290:9290"]
smartctl-exporter:
image: prometheuscommunity/smartctl-exporter:v0.13.0
restart: unless-stopped
privileged: true
ports: ["9633:9633"]
promtail:
image: grafana/promtail:3.3.0
restart: unless-stopped
volumes:
- /var/log:/var/log:ro
- ./promtail.yml:/etc/promtail/promtail.yml:ro
command: -config.file=/etc/promtail/promtail.yml
A configuração de recolha do Prometheus na VM de gestão:
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- /etc/prometheus/rules/*.yml
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
scrape_configs:
- job_name: dcgm
static_configs:
- targets: ["k-ai-01.lan:9400", "k-ai-02.lan:9400"]
- job_name: node
static_configs:
- targets: ["k-ai-01.lan:9100", "k-ai-02.lan:9100"]
- job_name: ipmi
static_configs:
- targets: ["k-ai-01.lan:9290", "k-ai-02.lan:9290"]
- job_name: smart
static_configs:
- targets: ["k-ai-01.lan:9633", "k-ai-02.lan:9633"]
- job_name: vllm
metrics_path: /metrics
static_configs:
- targets: ["k-ai-01.lan:8000"]
Esta é uma stack funcional para um laboratório de um a três servidores. A partir de quatro ou cinco servidores, mude a configuração de recolha do Prometheus para service discovery baseado em ficheiros ou — se estiver em Kubernetes — para o Helm chart do DCGM-exporter incluído no GPU Operator e para os CRD ServiceMonitor do Prometheus Operator.
OpenTelemetry, Pixie, eBPF — o panorama em 2026
Uma nota sobre as peças em movimento, porque a pergunta surge sempre.
OpenTelemetry é a norma da CNCF para instrumentação de observabilidade e, desde o início de 2026, os três tipos de sinal (métricas, traces, registos) estão estáveis. O pipeline do OTel Collector está a substituir agentes específicos de fabricante em muitas organizações, como router universal de telemetria. Para um servidor de IA, a resposta pragmática em 2026 é: manter o Prometheus para métricas (o DCGM-exporter e o node_exporter falam Prometheus nativamente, e as suas regras de alerta estão escritas em PromQL) e acrescentar um OTel Collector se e quando precisar de tracing distribuído ao longo de um grafo de serviço de inferência (pedido → gateway de API → vLLM → chamada de ferramenta → base de dados vetorial → resposta). Numa instalação de servidor único com um modelo por trás do nginx, o OTel acrescenta custo sem valor. Os 71% de organizações que "usam ambos" usam o Prometheus para o metal e o OTel para traces de aplicação — uma divisão sensata.
O Pixie é uma ferramenta de observabilidade nativa de Kubernetes que usa eBPF para recolher métricas, traces e registos ao nível do kernel sem alterações de código. O desenvolvimento de 2026 que vale a pena acompanhar é o trabalho de eBPF-on-GPU (bpftime, eGPU, módulos de kernel abertos da NVIDIA) que estende a instrumentação eBPF aos kernels de GPU via injeção de PTX em tempo de execução. Hoje está ao nível de investigação e não faz parte de nenhuma stack de produção que expedimos. Por agora, o DCGM é a resposta suportada.
O profiling contínuo (Grafana Phlare, Pyroscope) é um terceiro acessório que vale a pena conhecer. Em cargas de inferência em que controla o código da framework (patches próprios ao vLLM, otimizações de tokenizer), diz-lhe que funções consomem o CPU. Para puro serviço de modelos com contentores de origem, é exagero.
O que corre mal (edição monitorização)
Modos de falha previsíveis da própria stack, por ordem da frequência com que incomodam:
- O disco do Prometheus enche. A retenção predefinida é de 15 dias; nós definimos 30 com um teto de 20 GB. Acima de 60 dias numa máquina em carga, conte com dezenas de GB. Defina a retenção por tempo e por tamanho.
-
O DCGM-exporter perde as GPU depois de uma atualização do driver. Sintoma: todos os painéis de GPU ficam em branco. Solução: reiniciar o contentor; voltar a correr
nvidia-ctk runtime configurese o runtime mudou de sítio. -
Alertmanager não configurado para o recetor que realmente usa. As pessoas põem o Prometheus e o Grafana de pé, esquecem-se de apontar o Alertmanager para o e-mail ou o Slack e descobrem seis meses depois que nunca disparou um único alerta. Teste disparando de propósito
GPUTempCriticalcom uma carga de stress, ou useamtool alert addpara gerar um alerta sintético logo no primeiro dia. -
Explosão de cardinalidade por causa de etiquetas por pedido. Não etiquete as métricas do vLLM com
user_idnemrequest_id. O Prometheus não foi concebido para isso — vai esgotar a memória da base de dados. -
Fuga da palavra-passe do Grafana pelo env do compose. Use secrets do Docker e não
GF_SECURITY_ADMIN_PASSWORDno bloco environment. Odocker inspecte os registos expõem os valores de ambiente. -
Gauge de XID que não volta a zero. Como referido, o gauge de XID do DCGM-exporter pode ficar preso no último valor observado após uma recuperação. Combine a métrica com a leitura contínua do syslog no Loki por
NVRM:para evitar falsa confiança.
A opinião honesta
A maioria dos laboratórios instala o Grafana uma vez, constrói um dashboard que a equipa admira durante uma semana e nunca mais lhe olha. O dashboard é um artefacto gratificante; não é o que apanha os seus problemas. São os alertas que apanham os seus problemas. Configure o Alertmanager com um recetor a sério (e-mail, Slack, PagerDuty) e um pequeno conjunto de regras de alta precisão — temperatura da GPU, ECC de duplo bit, XID, OOM killer, ciclo de reinícios do contentor — e afine-as até só dispararem quando algo está mesmo mal. Faça isto primeiro. Só depois construa dashboards para a história do diagnóstico pós-incidente.
A outra metade da opinião honesta: à escala Kentino de um único servidor, esta stack dar-lhe-á talvez um alerta por mês e, na maioria dos meses, será um falso positivo que acaba por ignorar. É o sistema a funcionar. O valor está no alerta que dispara no dia em que um riser começa a cozer, dois dias antes de a placa saltar para o XID 79, quando ainda há tempo de voltar a encaixar um cabo em vez de enviar uma GPU para RMA. Esse único acontecimento paga todo o esforço de monitorização, e paga-o muitas vezes.
O que fazer a seguir
Para um servidor construído pela Kentino que entra em produção esta semana:
-
Ponha de pé a VM de gestão ou o nó de serviço. Uma máquina de 4 núcleos / 8 GB é mais do que suficiente. Instale o Docker. Aplique o compose
prometheus + grafana + alertmanager + lokiacima. -
No anfitrião com GPU, instale o
nvidia-container-toolkit(conforme L02) e confirme quedocker run --rm --gpus all nvidia/cuda:13.0.0-base-ubuntu24.04 nvidia-smifunciona. -
Instale
dcgm-exporter,node-exporter,ipmi-exporter,smartctl-exporterepromtailno anfitrião com GPU. Confirme que cada endpoint/metricsdevolve dados. -
Aponte o Prometheus aos cinco alvos de exporter e ainda ao endpoint
/metricsdo seu vLLM. Recarregue (curl -X POST :9090/-/reload). - Importe os dashboards 12239 e 1860 do Grafana. Confirme que os painéis de GPU e de sistema se preenchem.
-
Ligue o Alertmanager ao seu recetor de e-mail ou Slack. Dispare um alerta sintético com
amtool. Se o alerta de teste não chegar, nenhum alerta real chegará. -
Corra uma carga de stress (
gpu-burndurante uma hora, ou um treino a sério) e acompanhe os dashboards. É aqui que descobre que a sua sala não consegue manter as GPU abaixo dos 80 °C, que o NVMe é o estrangulamento ou que a cache KV está subdimensionada — tudo coisas mais fáceis de corrigir no primeiro dia do que na terceira semana.
Artigos complementares: L01 sobre fixação de versões de driver, L02 sobre CUDA e o runtime de contentores, L03 sobre afinação do kernel, L04 sobre a escolha do sistema de ficheiros.
Monitorizar primeiro. Afinar depois. Tudo o resto é adivinhar.
Este artigo faz parte da Kentino Wiki, uma série de referência sobre computação de IA, robótica e os sistemas que as ligam. Comentários e correções são bem-vindos em info@kentino.com.