O que significa
Um Job tenta de novo quando o pod falha. O campo .spec.backoffLimit diz quantas tentativas ele aceita antes de desistir, e o padrão é 6. Entre uma tentativa e outra, o controlador espera um intervalo que dobra (10 s, 20 s, 40 s...) até o teto de 6 minutos (documentação do Kubernetes, "Jobs", seção "Pod backoff failure policy"). Passado o limite, o Job recebe a condição Failed com motivo BackoffLimitExceeded e para de criar pods.
O Job falhado não recomeça sozinho, mesmo que a causa seja corrigida. Em CronJob, a próxima execução agendada cria um Job novo.
Causas comuns
Arquivo de entrada com formato errado, variável faltando, credencial expirada. Repetir não resolve: cada tentativa falha igual.
Banco, fila ou API externa indisponível. Aqui o retry faz sentido, mas pode esgotar o limite antes de a dependência voltar.
O pod do Job morre por memória ou o Job passa do activeDeadlineSeconds. O primeiro conta como tentativa; o segundo encerra o Job com outro motivo.
O padrão é 6. Um backoffLimit de 0 ou 1, copiado de exemplo, desiste na primeira instabilidade.
Diagnóstico em 3 comandos
Saídas reais de um Job de teste com backoffLimit: 2 que lê um arquivo sem uma coluna obrigatória.
1 · o Job e os pods que sobraram
kubectl -n loja get job importar-precos
kubectl -n loja get pods -l job-name=importar-precos NAME STATUS COMPLETIONS DURATION AGE
importar-precos Failed 0/1 109s 109s
NAME READY STATUS RESTARTS AGE
importar-precos-2qjsc 0/1 Error 0 102s
importar-precos-bxjx6 0/1 Error 0 2m2s
importar-precos-mmhq5 0/1 Error 0 2m17s Três pods: a primeira execução mais as 2 tentativas do backoffLimit. Pelas idades, o segundo pod veio 15 s depois do primeiro e o terceiro 20 s depois do segundo: o intervalo crescendo.
2 · o motivo no Job
kubectl -n loja describe job importar-precos | sed -n '/Events:/,$p' Events:
Type Reason Age From Message
Normal SuccessfulCreate 118s job-controller Created pod: importar-precos-mmhq5
Normal SuccessfulCreate 103s job-controller Created pod: importar-precos-bxjx6
Normal SuccessfulCreate 83s job-controller Created pod: importar-precos-2qjsc
Warning BackoffLimitExceeded 80s job-controller Job has reached the specified backoff limit 3 · o erro de verdade, no log
kubectl -n loja logs job/importar-precos Found 3 pods, using pod/importar-precos-mmhq5
erro: coluna sku ausente na linha 1
lendo precos.csv O logs job/ escolhe um dos pods. Para ver outro, use o nome do pod. As linhas podem vir fora de ordem quando o programa escreve em stdout e stderr.
A correção
Corrija a causa que o log mostrou e crie o Job de novo. Um Job não pode ser reexecutado; apague e aplique, ou, para um CronJob, dispare uma execução manual:
kubectl -n loja delete job importar-precos
kubectl -n loja apply -f importar-precos.yaml
# CronJob: execução manual a partir do modelo
kubectl -n loja create job importar-precos-manual --from=cronjob/importar-precos Ajuste o backoffLimit à natureza da falha. Para erro de dado, poucas tentativas bastam. Para dependência instável, mais tentativas, e um activeDeadlineSeconds para o Job não ficar dias tentando.
spec:
backoffLimit: 4
activeDeadlineSeconds: 1800
ttlSecondsAfterFinished: 86400
template:
spec:
restartPolicy: Never avisoO ttlSecondsAfterFinished apaga o Job e os pods depois do prazo. Sem ele os pods com erro ficam no cluster; com ele curto demais, o log some antes de alguém ler.
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 arquivo de preços chega sem a coluna sku. Evidência: as três tentativas saíram com erro e o log traz "erro: coluna sku ausente na linha 1". É erro de dado: novas tentativas falhariam igual. Correção sugerida: corrigir o arquivo de origem e recriar o Job; não aumentar o backoffLimit.