Décimo segundo post da série. No anterior, operamos Azure OpenAI com HA e retry correto. Agora: quando as coisas quebram (e vão quebrar).
Este post é organizado como cenários reais de falha. Cada um segue: Sintomas → Diagnóstico → Root Cause → Resolução → Prevenção. Leia uma vez pra reconhecimento de padrões. Depois deixe bookmarkado; você vai voltar aqui.
Cenário 1: NVIDIA driver crash após kernel update
Sintomas
Segunda de manhã. Time de ML reporta que todos os workloads GPU falharam no fim de semana. Ninguém deployou nada. Você faz SSH:
$ nvidia-smi
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver.
Make sure that the latest NVIDIA driver is installed and running.
Containers GPU não sobem. Training jobs mortos. O VM em si está normal, CPU workloads rodam.
Diagnóstico
# Verificar mensagens do kernel
dmesg | grep -i nvidia
# [ 4.212] NIST: module nvidia not found in modules.dep
# Kernel atual
uname -r
# 6.5.0-44-generic
# Driver instalado
dpkg -l | grep nvidia-driver
# nvidia-driver-535 535.183.01
# O que aconteceu
cat /var/log/apt/history.log | grep -A 5 "linux-image"
# unattended-upgrade instalou novo kernel
Root cause
unattended-upgrades do Ubuntu instalou novo kernel automaticamente. O NVIDIA kernel module é compilado contra uma versão específica. Quando o VM rebootou no novo kernel, não havia módulo NVIDIA correspondente.
Resolução
# Opção A: reinstalar driver extension (VMs Azure)
az vm extension set \
--resource-group myRG \
--vm-name myGPUVM \
--name NvidiaGpuDriverLinux \
--publisher Microsoft.HpcCompute \
--version 1.9
# Opção B: pinar versão do kernel e reinstalar driver
sudo apt-mark hold linux-image-$(uname -r) linux-headers-$(uname -r)
sudo apt install --reinstall nvidia-driver-535
sudo reboot
Prevenção
Desabilitar upgrades automáticos de kernel em todos os VMs GPU. Adicionar em /etc/apt/apt.conf.d/50unattended-upgrades:
Unattended-Upgrade::Package-Blacklist {
"linux-image";
"linux-headers";
"linux-modules";
};
Usar a Azure NVIDIA GPU Driver Extension pro lifecycle de drivers. Tratar kernel upgrades como planned maintenance.
Essa falha é silenciosa. O VM boota normal, passa health checks, responde a SSH. Só workloads GPU falham. Se você não monitora output do
nvidia-smi, só descobre quando usuários reclamam.
Cenário 2: CUDA Out of Memory durante fine-tuning
Sintomas
Job de fine-tuning começa bem, roda 10-30 minutos, então crasheia:
RuntimeError: CUDA out of memory. Tried to allocate 2.00 GiB
(GPU 0; 79.15 GiB total capacity; 77.42 GiB already allocated;
1.08 GiB free; 78.50 GiB reserved in total by PyTorch)
“Mas funcionou nos primeiros 500 steps.”
Diagnóstico
# Monitoramento contínuo de memória GPU
watch -n 1 nvidia-smi
# Log de memória pra análise
nvidia-smi --query-gpu=timestamp,memory.used,memory.free,utilization.gpu \
--format=csv -l 5 > gpu_memory.csv
Calcular memória esperada (modelo 7B com Adam em BF16):
| Componente | Memória |
|---|---|
| Parameters (BF16) | ~14 GB |
| Gradients (BF16) | ~14 GB |
| Optimizer States (FP32, Adam) | ~56 GB |
| Activations (varia com batch) | Variável |
| Mínimo total | ~84 GB + activations |
Root cause
Batch size = 8. No início do training, sequências curtas no dataset produziram tensors de activation pequenos. Conforme o data loader alcançou sequências mais longas, memória de activation cresceu até exceder o que sobrava na GPU. OOM não aconteceu no step 1 porque os primeiros batches cabiam.
Resolução
# Fix imediato: reduzir batch size, manter effective batch com accumulation
training_args = TrainingArguments(
per_device_train_batch_size=2, # Reduzido de 8
gradient_accumulation_steps=4, # Mantém effective batch = 8
)
# Fix melhor: gradient checkpointing (troca 20-30% velocidade por 60-80% menos memória)
model.gradient_checkpointing_enable()
# Pra modelos maiores: LoRA (treina <1% dos parâmetros)
from peft import LoraConfig, get_peft_model
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05,
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable params: 6.5M || all params: 6.74B || trainable%: 0.096%
Prevenção
- Sempre calcular memória requerida antes de iniciar
- Setar
max_seq_lengthexplicitamente pra limitar activation memory - Usar
gradient_accumulation_stepspra manter effective batch com per-GPU batch pequeno
Se OOM acontece em steps aleatórios (não consistentemente no step N), suspeite de sequências de comprimento variável. Sete
max_seq_lengthe pad/truncate.
Cenário 3: AKS GPU pods stuck em Pending
Sintomas
$ kubectl get pods -n ml-team
NAME READY STATUS RESTARTS AGE
training-job-7b-xyz 0/1 Pending 0 20m
Diagnóstico
$ kubectl describe pod training-job-7b-xyz -n ml-team
Events:
Warning FailedScheduling 18m 0/12 nodes are available:
3 node(s) had untolerated taint {sku=gpu:NoSchedule},
9 node(s) didn't match Pod's node affinity/selector.
A mensagem de taint é a chave. AKS GPU node pools aplicam sku=gpu:NoSchedule por default. Pod precisa toleration correspondente.
# Verificar se é problema de quota
az vm list-usage --location eastus -o table | grep -i "Standard NC\|Standard ND"
# Verificar limites de scaling do node pool
az aks nodepool show --cluster-name myAKS --resource-group myRG \
--name gpunp --query '{min:minCount, max:maxCount, current:count}'
Root cause
Pod spec sem a toleration necessária. Scheduler vê GPU nodes como ineligíveis.
Outras causas comuns:
- GPU quota esgotada (cluster autoscaler não consegue provisionar novos nós)
- Node pool no
maxCount(autoscaler quer escalar mas não pode)
Resolução
# Adicionar toleration no pod spec
spec:
tolerations:
- key: "sku"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
containers:
- name: training
resources:
limits:
nvidia.com/gpu: 1
Se quota é o problema:
az quota create \
--resource-name "StandardNDSv2Family" \
--scope "/subscriptions/{sub-id}/providers/Microsoft.Compute/locations/eastus" \
--limit-object value=48 limit-object-type=LimitValue
Prevenção
- Template todos os pod specs GPU com toleration pré-configurada
- Alertas em 80% do uso de GPU quota
- Configurar cluster autoscaler com headroom no
maxCount
Pod stuck em Pending não produz logs, porque não existe container. Sempre cheque
kubectl describe podpra events, nãokubectl logs.
Cenário 4: Azure OpenAI 429 storm
Sintomas
30%+ dos requests retornando HTTP 429. Usuários reportam lentidão ou timeouts.
{
"error": {
"code": "429",
"message": "Requests to the ChatCompletions_Create Operation under Azure OpenAI API have exceeded the token rate limit..."
}
}
Diagnóstico
Verifique o header Retry-After:
Retry-After: 1= excedeu por poucoRetry-After: 30= dramaticamente acima do limite
az monitor metrics list \
--resource "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.CognitiveServices/accounts/{account}" \
--metric "TokenTransaction" \
--interval PT1M \
--aggregation Total \
--filter "ModelDeploymentName eq 'gpt-4o-prod'"
Root cause
Deployment Standard com 80K TPM. Product launch gerou burst de 200K+ TPM. Standard enforça hard rate limits; todo request acima recebe 429.
Resolução
- Imediato: Implementar exponential backoff com jitter (código no post anterior)
- Curto prazo: Segundo deployment em outra região pra overflow
- Longo prazo: Avaliar PTU pra workloads previsíveis e de alto volume
Prevenção
- Arquitetura multi-deployment com APIM fazendo load balancing
- Alertas em 80% do TPM provisionado
- Token-aware queue no client (estimar tokens antes de enviar)
- Logging de token count por request pra forecast antes de launches
Cenário 5: Inference latency spike
Sintomas
P99 latência pula de 200ms pra 3 segundos. Nenhum deployment, nenhuma mudança de config. “A AI tá lenta.”
Diagnóstico
# GPU occupada?
nvidia-smi --query-gpu=utilization.gpu,utilization.memory,temperature.gpu \
--format=csv -l 2
# Container restartou?
kubectl get pods -n inference -w
kubectl describe pod model-serve-abc -n inference | grep -A 5 "Last State"
# Cold start? (modelo sendo recarregado)
kubectl logs model-serve-abc -n inference | grep -i "model loaded\|loading model"
# [2024-07-15 08:14:47] Model loaded in 164.2 seconds
164 segundos de model load = quase 3 minutos de latency hole a cada restart.
Root cause (geralmente uma combinação)
- Container cold start: Pod evicted (OOM, node drain, spot reclaim), modelo recarregando de Blob Storage (14+ GB over network)
- GPU thermal throttling: 100% utilização sustentada → temperatura > 83°C → clock reduction automático
- Noisy neighbor: Outro pod no mesmo nó consumindo CPU/memória/rede necessária pra pre/post-processing
Resolução
Pra cold starts: init container que baixa model weights pra NVMe local antes do serving container iniciar. Readiness probe que só marca ready após modelo carregado.
Pra thermal throttling: monitorar DCGM_FI_DEV_GPU_TEMP e alertar acima de 78°C. Reduzir batch size pra diminuir utilização sustentada.
Pra noisy neighbor: usar nodeSelector ou taints dedicados pra isolar inference pods em nós exclusivos.
Prevenção
- Readiness probe que verifica model loaded (não apenas container up)
- Cache de modelo em local NVMe (não download do Blob a cada start)
- Monitoring de temperatura GPU com alertas proativos
- Pods de inference em nós dedicados sem sharing
No próximo post
Troubleshooting coberto. No próximo, saímos do operacional pra algo mais amplo: AI use cases pra infra teams. Como usar AI pra melhorar o seu próprio trabalho de infraestrutura, desde AIOps até análise de logs e capacity planning preditivo.