flujo de ry-drun

Los Job de Kubernetes ejecutan tareas finitas, como migraciones, respaldos o generación de informes. Un CronJob agrega una programación recurrente y crea un nuevo Job en cada horario previsto.

A diferencia de un Deployment, estas cargas deben finalizar. Por eso no utilizan kubectl rollout ni tienen un rollback automático: la recuperación consiste en suspender nuevas ejecuciones, corregir la plantilla y crear un nuevo Job.

Qué vas a implementar

La guía configura un CronJob que:

  • Se ejecuta diariamente a las 03:00 de Argentina.
  • Evita ejecuciones programadas superpuestas.
  • Limita reintentos y tiempo máximo de ejecución.
  • Conserva temporalmente Jobs terminados para diagnóstico.
  • Permanece suspendido hasta superar una prueba manual.

Un CronJob crea Jobs, y cada Job administra uno o más Pods hasta completar la tarea o alcanzar una condición de fallo. Incluso una tarea configurada con una sola ejecución podría iniciarse más de una vez en situaciones excepcionales; por eso su lógica debe ser idempotente. La documentación oficial describe este comportamiento.

Requisitos previos

  • Un clúster Kubernetes operativo.
  • kubectl configurado con el contexto correcto.
  • Permisos para administrar namespaces, Jobs y CronJobs.
  • Kubernetes 1.27 o posterior para utilizar .spec.timeZone.
  • Una imagen de contenedor que finalice con código 0 al completar correctamente.
  • Un entorno de ensayo y un mecanismo externo de respaldo cuando la tarea modifique datos.

Comprueba el contexto antes de continuar:

kubectl config current-context
kubectl version --client
kubectl cluster-info

Crea un namespace aislado:

kubectl create namespace donweb-lab \
  --dry-run=client -o yaml | kubectl apply -f -

Verifica los permisos:

kubectl auth can-i create jobs.batch -n donweb-lab
kubectl auth can-i create cronjobs.batch -n donweb-lab

Ambas consultas deben responder yes.

Configurar el CronJob

Guarda lo siguiente como cronjob.yaml:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: mantenimiento-diario
  namespace: donweb-lab
spec:
  schedule: "0 3 * * *"
  timeZone: "America/Argentina/Buenos_Aires"
  suspend: true
  concurrencyPolicy: Forbid
  startingDeadlineSeconds: 600
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      backoffLimit: 2
      activeDeadlineSeconds: 300
      ttlSecondsAfterFinished: 86400
      template:
        metadata:
          labels:
            app.kubernetes.io/name: mantenimiento-diario
        spec:
          restartPolicy: Never
          securityContext:
            seccompProfile:
              type: RuntimeDefault
          containers:
            - name: mantenimiento
              image: busybox:1.36.1
              imagePullPolicy: IfNotPresent
              command: ["/bin/sh", "-c"]
              args:
                - |
                  set -eu
                  echo "Inicio de la tarea"
                  date -u
                  sleep 5
                  echo "Tarea completada"
              resources:
                requests:
                  cpu: 10m
                  memory: 16Mi
                limits:
                  cpu: 100m
                  memory: 64Mi
              securityContext:
                allowPrivilegeEscalation: false
                readOnlyRootFilesystem: true
                runAsNonRoot: true
                runAsUser: 65534
                capabilities:
                  drop: ["ALL"]

El comando es deliberadamente inocuo. En una implementación real, reemplázalo por una imagen propia, revisada y preferentemente fijada mediante digest.

Controles importantes

  • suspend: true evita ejecuciones programadas durante la validación.
  • concurrencyPolicy: Forbid omite una nueva ejecución si la anterior continúa activa. Esta política solo coordina Jobs creados por el mismo CronJob.
  • startingDeadlineSeconds: 600 permite iniciar una ejecución con hasta diez minutos de retraso; después se omite.
  • backoffLimit: 2 limita los reintentos de Pods fallidos.
  • activeDeadlineSeconds: 300 detiene el Job si supera cinco minutos, aunque todavía queden reintentos.
  • ttlSecondsAfterFinished: 86400 permite limpiar el Job y sus Pods 24 horas después de finalizar.

Kubernetes admite Allow, Forbid y Replace como políticas de concurrencia. Además, un plazo inferior a diez segundos puede ser demasiado corto debido a la frecuencia de comprobación del controlador. Consulta las opciones y limitaciones de CronJob.

Insertar conceptualmente la Imagen 2 aquí.

Validar antes de aplicar

Primero solicita al API Server que valide el manifiesto sin persistirlo:

kubectl apply --dry-run=server -f cronjob.yaml

Luego revisa las diferencias:

kubectl diff -f cronjob.yaml

kubectl diff devuelve código 1 cuando encuentra diferencias y un valor mayor cuando ocurre un error. No agregues || true, porque ocultaría fallos reales.

Aplica el recurso todavía suspendido:

kubectl apply -f cronjob.yaml
kubectl get cronjob mantenimiento-diario -n donweb-lab

Confirma expresamente la programación, zona horaria y suspensión:

kubectl get cronjob mantenimiento-diario -n donweb-lab \
  -o jsonpath='{.spec.schedule}{" | "}{.spec.timeZone}{" | suspend="}{.spec.suspend}{"\n"}'

La salida esperada es:

0 3 * * * | America/Argentina/Buenos_Aires | suspend=true

No incluyas TZ= ni CRON_TZ= dentro de .spec.schedule: Kubernetes rechaza ese formato. En versiones 1.27 o posteriores debe utilizarse .spec.timeZone; sin este campo, el horario se interpreta según la zona del kube-controller-manager. Referencia oficial de zonas horarias.

Ejecutar una prueba manual

Crea un Job independiente desde la plantilla del CronJob:

JOB="mantenimiento-prueba-$(date -u +%Y%m%d%H%M%S)"

kubectl create job "$JOB" \
  --from=cronjob/mantenimiento-diario \
  -n donweb-lab

Este comando está soportado específicamente para crear un Job desde un CronJob. Referencia de kubectl create job.

Espera a que finalice:

kubectl wait --for=condition=complete \
  "job/$JOB" \
  -n donweb-lab \
  --timeout=6m

Comprueba estado, Pods y salida:

kubectl get job "$JOB" -n donweb-lab
kubectl get pods -n donweb-lab -l job-name="$JOB"
kubectl logs "job/$JOB" -n donweb-lab
kubectl describe job "$JOB" -n donweb-lab
kubectl get events -n donweb-lab \
  --sort-by=.metadata.creationTimestamp

El Job debe mostrar Complete, el Pod debe aparecer como Completed y los logs deben incluir Tarea completada.

Insertar conceptualmente la Imagen 3 aquí.

Habilitar la programación

Después de validar la tarea manual:

kubectl patch cronjob mantenimiento-diario \
  -n donweb-lab \
  --type=merge \
  -p '{"spec":{"suspend":false}}'

Comprueba el estado:

kubectl get cronjob mantenimiento-diario -n donweb-lab
kubectl describe cronjob mantenimiento-diario -n donweb-lab

Tras el siguiente horario previsto, revisa los Jobs creados:

kubectl get jobs -n donweb-lab \
  --sort-by=.metadata.creationTimestamp

Ten presente que editar un CronJob solo cambia los Jobs futuros. Los Jobs y Pods que ya comenzaron conservan su configuración anterior.

Cómo detener o revertir el cambio

Un CronJob no admite kubectl rollout undo. Para impedir nuevas ejecuciones:

kubectl patch cronjob mantenimiento-diario \
  -n donweb-lab \
  --type=merge \
  -p '{"spec":{"suspend":true}}'

La suspensión no detiene Jobs activos. Revísalos antes de decidir si deben cancelarse:

kubectl get jobs -n donweb-lab
kubectl get pods -n donweb-lab

Eliminar un Job activo termina sus Pods y puede dejar una operación incompleta:

kubectl delete job NOMBRE_DEL_JOB -n donweb-lab

Para revertir una modificación de configuración, restaura la versión anterior de cronjob.yaml, valídala y vuelve a aplicar:

kubectl apply --dry-run=server -f cronjob.yaml
kubectl diff -f cronjob.yaml
kubectl apply -f cronjob.yaml

Seguridad y confiabilidad

  • Diseña la tarea para tolerar ejecuciones duplicadas y reinicios.
  • Usa transacciones, claves de idempotencia o bloqueos con vencimiento cuando modifiques datos.
  • No almacenes contraseñas ni tokens en args, variables literales o imágenes.
  • Usa Secret, un gestor externo de secretos y una ServiceAccount con mínimo privilegio.
  • Establece solicitudes y límites de recursos para evitar competencia descontrolada.
  • Fija imágenes mediante digest en producción.
  • Conserva logs fuera del Pod si deben sobrevivir a la limpieza automática.
  • Prueba restauración, reintentos y fallos parciales antes de programar respaldos reales.

Problemas frecuentes

El CronJob no crea Jobs

Comprueba .spec.suspend, .spec.schedule, .spec.timeZone, los eventos y el reloj del control plane. Evita valores de startingDeadlineSeconds inferiores a diez segundos.

El Job falla y vuelve a intentarse

Revisa kubectl describe job, los eventos y los logs del Pod fallido. backoffLimit cuenta fallos; no corrige errores de imagen, permisos ni configuración.

pruenas ry drun

Aparecen ejecuciones duplicadas

La programación de CronJobs es aproximada y puede producir más de una ejecución en circunstancias excepcionales. Forbid reduce solapamientos del mismo CronJob, pero la tarea sigue necesitando idempotencia.

El Job queda activo demasiado tiempo

Comprueba que el proceso responda a la terminación y define activeDeadlineSeconds. Si alcanza el plazo, Kubernetes marca el Job como fallido con motivo DeadlineExceeded.

Los Jobs terminados desaparecen

Revisa successfulJobsHistoryLimit, failedJobsHistoryLimit y ttlSecondsAfterFinished. El TTL puede eliminarlos antes de que el límite histórico resulte relevante.

Cloud Serversby Donweb

Todo el poder de la nube a tus proyectos y aplicaciones.
Alojamiento ultra rápido, escalable y con alta disponibilidad.

  • Performance que te sorprenderá
  • Rápida escalabilidad y sin limitaciones
  • Arquitectura de alta disponibilidad
  • Soporte experto y ejecutivos de cuenta
  • Pagos en tu moneda y facturación local

Descubre la mejor solución de Cloud Hosting