Guia Completo de CronJobs em Kubernetes: Agendamento e Gerenciamento de Execuções Já leu

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,

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.

Referências


Artigos relacionados