O que significa
Pending é a fase em que o pod foi aceito pelo cluster e ainda não roda. Logo depois de criado, todo pod passa por ela. Quando ele fica em Pending e não aparece nenhum nó na coluna NODE, o scheduler tentou encaixá-lo e não conseguiu. Cada tentativa gera um evento FailedScheduling com o placar: de quantos nós, quantos estavam disponíveis e por que os outros foram descartados.
O ponto que mais confunde: o scheduler decide por requests, não por uso. Ele soma os requests dos pods já alocados no nó e vê se o novo cabe no allocatable (documentação do Kubernetes, "Resource Management for Pods and Containers"). Um nó com 5% de CPU em uso e requests somando 100% recusa o pod.
Causas comuns
O scheduler soma os requests dos pods já alocados em cada nó e compara com o allocatable. Não importa o uso real: um nó quase ocioso com requests esgotados não recebe o pod.
Nós reservados (GPU, sistema, spot) carregam taints. Pod sem a toleration correspondente é recusado nesses nós, e se só eles têm espaço, fica Pending.
Um rótulo digitado errado, ou um pool que foi recriado sem o rótulo, e nenhum nó satisfaz a regra.
O PVC não encontrou PersistentVolume ou StorageClass, ou o volume existe numa zona diferente da dos nós disponíveis.
Com cluster autoscaler, o Pending pode ser só o tempo de criar a máquina. O evento TriggeredScaleUp diz que ele está a caminho; se não aparece, o autoscaler não achou pool que resolva.
Diagnóstico em 3 comandos
Saídas reais de um pod de teste que pede 16 CPUs num cluster de dois nós com 10 CPUs cada.
1 · confirme que ele não tem nó
kubectl -n loja get pod relatorios -o wide NAME READY STATUS RESTARTS AGE IP NODE
relatorios 0/1 Pending 0 7m49s <none> <none> 2 · leia o placar do scheduler
kubectl -n loja describe pod relatorios | sed -n '/Events:/,$p' Events:
Type Reason From Message
Warning FailedScheduling default-scheduler 0/2 nodes are available: 2 Insufficient cpu.
no new claims to deallocate, preemption: 0/2 nodes are available:
2 Preemption is not helpful for scheduling. "0/2 nodes are available: 2 Insufficient cpu" quer dizer: dois nós no cluster, nenhum serve, os dois por falta de CPU. Quando há motivos diferentes, eles aparecem somados na mesma linha, como "1 Insufficient memory, 2 node(s) had untolerated taint". A parte de preemption diz que nem despejando pods de prioridade menor o pod caberia.
3 · compare com o que os nós têm
kubectl get nodes -o custom-columns=NOME:.metadata.name,CPU:.status.allocatable.cpu,MEMORIA:.status.allocatable.memory NOME CPU MEMORIA
k3d-ia4code-lab-agent-0 10 8024472Ki
k3d-ia4code-lab-server-0 10 8024472Ki kubectl describe node k3d-ia4code-lab-server-0 | sed -n '/Allocated resources:/,/ephemeral/p' Allocated resources:
Resource Requests Limits
cpu 200m (2%) 0 (0%)
memory 140Mi (1%) 170Mi (2%) Nenhum nó tem 16 CPUs de allocatable. Não adianta esperar: o pod nunca vai caber sem mudar o request ou o tamanho da máquina.
A correção
- Insufficient cpu ou memory: meça o uso real e ajuste o request para ele. Se o serviço realmente precisa daquilo, o pool precisa de máquinas maiores ou de mais nós.
- Taint sem toleration: veja os taints com
kubectl describe node NOME | grep Taintse, se o pod deve mesmo ir para aquele nó, acrescente a toleration. - nodeSelector ou affinity: compare o rótulo pedido com
kubectl get nodes --show-labels. - PVC:
kubectl get pvcno namespace; um PVC em Pending tem o próprio evento dizendo o motivo.
resources:
requests:
cpu: 500m
memory: 256Mi
limits:
memory: 512Mi avisoApagar o pod não resolve Pending: o controlador cria outro com o mesmo request, que fica preso do mesmo jeito.
Como aparece no Kubepier
O Kubepier mostra os eventos do pod com os avisos primeiro, com filtro por tipo, namespace e motivo. O diagnóstico por IA explica o erro a partir dos eventos e do log, em português, com a sua chave de API (Anthropic ou OpenAI). Abaixo, uma ilustração com dados fictícios.
Causa provável: o pod pede 16 CPUs e nenhum nó tem esse espaço livre. Evidência: "0/2 nodes are available: 2 Insufficient cpu" nos eventos. O uso real dos nós é baixo, então não é falta de máquina: é o request. Correção sugerida: reduzir requests.cpu para o que o serviço usa de fato.