O que é CronJob em Kubernetes e Por Que Usar
Um CronJob é um objeto nativo do Kubernetes que permite agendar a execução de tarefas em momentos específicos, seguindo o formato de agendamento cron tradicional do Linux. Diferentemente de um Pod comum que executa uma vez e termina, um CronJob cria automaticamente Jobs em intervalos predefinidos, permitindo automação de tarefas periódicas como backups, limpeza de dados, relatórios e sincronizações.
A principal vantagem é que o Kubernetes gerencia a vida útil dessas execuções, garantindo que falhas sejam tratadas automaticamente, que o agendamento seja confiável mesmo durante reinicializações do cluster, e que você tenha histórico de execuções. Sem CronJobs, você precisaria manter um servidor cron externo ou implementar lógica de agendamento na aplicação, aumentando a complexidade.
Estrutura e Componentes de um CronJob
Anatomia do CronJob
Um CronJob no Kubernetes é composto por um agendador (schedule), uma especificação de Job (jobTemplate) e políticas de execução. O schedule define quando o Job será criado, usando a sintaxe padrão cron (5 campos: minuto, hora, dia do mês, mês, dia da semana). O jobTemplate descreve qual trabalho será executado a cada acionamento, incluindo a imagem do container, argumentos, variáveis de ambiente e configurações de reinicialização.
apiVersion: batch/v1
kind: CronJob
metadata:
name: exemplo-limpeza-diaria
namespace: default
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: limpar-logs
image: ubuntu:latest
command:
- /bin/sh
- -c
- echo "Limpando logs antigos..." && find /var/log -type f -mtime +30 -delete
restartPolicy: OnFailure
backoffLimit: 3
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
concurrencyPolicy: Forbid
No exemplo acima, o agendamento 0 2 * * * significa que o Job será executado todos os dias às 2 da manhã. O backoffLimit: 3 permite até 3 tentativas de execução em caso de falha. Os limites de histórico definem quantos Jobs bem-sucedidos e falhados serão mantidos para auditoria.
Políticas de Execução
A política de concorrência (concurrencyPolicy) controla o comportamento quando múltiplas execuções podem se sobrepor. Existem três opções: Allow (padrão) permite múltiplas execuções simultâneas, Forbid impede uma nova execução se a anterior ainda está rodando, e Replace cancela a execução anterior e inicia uma nova. Para tarefas críticas como backups, use Forbid para evitar conflitos.
Implementação Prática e Casos de Uso
Caso Real: Backup Diário de Banco de Dados
Considere um cenário onde você precisa fazer backup de um banco de dados PostgreSQL a cada meia-noite. O CronJob cria um container temporário que conecta ao serviço do banco dentro do cluster, executa o dump e envia para um storage externo.
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup-postgres-diario
namespace: producao
spec:
schedule: "0 0 * * *"
timeZone: "America/Sao_Paulo"
jobTemplate:
spec:
template:
spec:
serviceAccountName: backup-account
containers:
- name: backup-db
image: postgres:15-alpine
env:
- name: PGHOST
value: "postgres-service.producao.svc.cluster.local"
- name: PGUSER
value: "backup_user"
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: postgres-credentials
key: password
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: aws-credentials
key: access_key
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: aws-credentials
key: secret_key
command:
- /bin/bash
- -c
- |
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="backup_${TIMESTAMP}.sql"
pg_dump --verbose --create --blobs > ${BACKUP_FILE}
aws s3 cp ${BACKUP_FILE} s3://meu-bucket-backups/postgres/
if [ $? -eq 0 ]; then
echo "Backup concluído com sucesso para S3"
else
echo "Falha ao fazer upload do backup" && exit 1
fi
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
restartPolicy: OnFailure
backoffLimit: 2
successfulJobsHistoryLimit: 5
failedJobsHistoryLimit: 2
concurrencyPolicy: Forbid
Este exemplo demonstra várias práticas importantes: uso de timeZone para agendamento em fuso horário específico, injeção de credenciais via Secrets, limite de recursos para evitar sobrecarga do cluster, e histórico bem configurado para auditoria de execuções.
Monitoramento de Saúde da Aplicação
Outro caso comum é criar um CronJob que verifica periodicamente a saúde de componentes críticos e envia notificações ou executa ações corretivas.
apiVersion: batch/v1
kind: CronJob
metadata:
name: health-check-api
namespace: default
spec:
schedule: "*/5 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: curl-health-check
image: curlimages/curl:latest
command:
- /bin/sh
- -c
- |
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" http://api-service:8080/health)
if [ "$RESPONSE" != "200" ]; then
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"API health check falhou. Status: '$RESPONSE'"}' \
$SLACK_WEBHOOK_URL
exit 1
fi
echo "Health check OK - Status: $RESPONSE"
env:
- name: SLACK_WEBHOOK_URL
valueFrom:
secretKeyRef:
name: slack-webhook
key: url
restartPolicy: Never
backoffLimit: 1
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
Este CronJob executa a cada 5 minutos, verifica se a API está respondendo com status 200 e notifica via Slack em caso de falha. O restartPolicy: Never evita reinicializações automáticas, e o histórico reduzido economiza recursos.
Monitoramento, Troubleshooting e Melhores Práticas
Verificando Execuções e Logs
Para inspecionar um CronJob em produção, use kubectl get cronjobs para listar todos os CronJobs no cluster. Depois, kubectl describe cronjob nome-do-cronjob mostra informações detalhadas incluindo o próximo tempo de execução e histórico de execuções recentes. Para ver os Pods criados pelos Jobs, use kubectl get jobs -l cronjob.kubernetes.io/name=nome-do-cronjob, e então visualize os logs com kubectl logs pod-id.
# Listar todos os CronJobs
kubectl get cronjobs -n producao
# Detalhar um CronJob específico
kubectl describe cronjob backup-postgres-diario -n producao
# Ver Jobs criados por um CronJob
kubectl get jobs -n producao -l cronjob.kubernetes.io/name=backup-postgres-diario
# Ver últimas 100 linhas de log de um Pod de um Job
kubectl logs -n producao -l job-name=backup-postgres-diario-1234567890 --tail=100
# Editar um CronJob em tempo real
kubectl edit cronjob backup-postgres-diario -n producao
Melhores Práticas
Sempre defina timeZone explicitamente para evitar problemas de agendamento em clusters distribuídos. Use concurrencyPolicy: Forbid para tarefas que acessam recursos exclusivos como bancos de dados. Implemente tratamento de erros robustos no script ou comando, pois um exit code diferente de 0 marca a execução como falha. Configure limites de recursos (resources.requests e limits) para que CronJobs não comprometam outros workloads. Mantenha o histórico de sucessos e falhas para auditoria, mas não em excesso para economizar etcd. Use Secrets para credenciais, nunca hardcode dados sensíveis no YAML. Por fim, considere adicionar labels de rastreamento e annotations com informações de quem criou e por quê.
apiVersion: batch/v1
kind: CronJob
metadata:
name: tarefa-critica
namespace: default
labels:
app: sistema-critico
cronjob-tipo: manutencao
annotations:
criado-por: "time-devops"
descricao: "Limpeza de dados temporários e reorganização de índices"
slack-canal: "#ops-alerts"
spec:
schedule: "0 3 * * 0"
timeZone: "America/Sao_Paulo"
startingDeadlineSeconds: 300
jobTemplate:
spec:
ttlSecondsAfterFinished: 86400
template:
spec:
containers:
- name: executor
image: minha-app:v1.2.0
imagePullPolicy: IfNotPresent
command: ["/app/manutencao.sh"]
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
securityContext:
runAsNonRoot: true
readOnlyRootFilesystem: true
restartPolicy: OnFailure
backoffLimit: 2
successfulJobsHistoryLimit: 5
failedJobsHistoryLimit: 3
concurrencyPolicy: Forbid
O parâmetro startingDeadlineSeconds: 300 garante que a execução aconteça no máximo 5 minutos após o tempo agendado, evitando execuções muito atrasadas. O ttlSecondsAfterFinished: 86400 faz o Job ser automaticamente removido após 24 horas, limpando recursos. A securityContext força a execução como usuário não-root, melhorando segurança.
Conclusão
CronJobs em Kubernetes eliminam a necessidade de gerenciar agendadores externos, fornecendo uma abordagem nativa, resiliente e auditável para automação periódica de tarefas. A chave está em configurar corretamente as políticas de concorrência, limites de recursos e tratamento de erros para que suas tarefas automáticas rodem de forma confiável em produção. Com as práticas demonstradas aqui—uso de Secrets, monitoramento de histórico e timeZone explícito—você terá um sistema de agendamento robusto e fácil de manter.