Y si usamos los CronJobs en Kubernetes

Y si usamos los CronJobs en Kubernetes

Introducción

Kubernetes se ha convertido rápidamente en la herramienta estándar para la gestión de infraestructuras containerizadas. Kubernetes cuenta con variedad de recursos de carga de trabajo disponibles para controlar y administrar pods y contenedores, los más comunes siendo:

  • Deployments
  • ReplicaSets
  • StatefulSets

Éstos se utilizan tanto para crear sistemas como para controlar el comportamiento deseado de las diferentes partes. Aunque estos recursos tienen diferentes propósitos y funcionalidades, todos comparten la operativa de mantener los sistemas levantados en caso de fallo, evaluando el estado de contenedores, y reiniciando o reprogramando (“rescheduling”) las partes relevantes en caso necesario.

No obstante, hay otros recursos de carga de trabajo disponibles:

  • Job
  • Cronjobs

En esta entrada de blog, nos centramos en los Cronjobs: su función y las opciones de customización disponibles.

Cómo funcionan los CronJobs en Kubernetes

CronJob ayuda a ejecutar su tarea en un horario determinado para que pueda definir a qué hora debe ejecutarse para completar su tarea.

Puede ser por hora, semanal, mensual o puede establecer cualquier otro horario que prefiera.

Cuando agrega un CronJob para su aplicación, hay un área separada en el archivo de configuración para que configure su horario. Además, obtendrá una sección JobTemplate separada en CronJobs que no encontrará en Jobs.

Cabe además mencionar que los Jobs pueden crear uno o más Pods (permitiendo concurrencia/paralelismo) a la vez que se aseguran que las tareas se completan satisfactoriamente. Sin embargo, este último comportamiento podría crear complejidades adicionales ya que los contenedores ya incorporan su propia funcionalidad de gestión de fallos y reinicios.

image.png

Fuente Imagen

Creemos un CronJob para una aplicación que se ejecuta en Kubernetes.

apiVersion: batch/v1          
kind: CronJob                        
metadata:
  name: cron-test
spec:
  schedule: "*/1 * * * *"            
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: cron-test
            image: busybox   
            command: ["/bin/sh"]
            args: ["-c", "date; echo Hello this is Cron test"] 
          restartPolicy: Never

Recomiendo usar crontab.guru para calcular tiempos para nuestros cron

Vamos aplicarlo en el cluster , taran taran ven CronJob

con el ejemplo anterior lo guardamos con el nombre: cron-test.yaml

ahora aplicamos el CronJon en el cluster

$ kubectl apply -f cron-test.yaml
 cronjob.batch/cron-test created

Verificamos que el cronJob se ha creado con la definición de scheduler

$ kubectl get cronjob cron-test
 NAME        SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
 cron-test   */1 * * * *   False     0        <none>          10s
$ kubectl get pod -A
NAMESPACE     NAME                                      READY   STATUS      RESTARTS       AGE
kube-system   metrics-server-ff9dbcb6c-w5dvd            1/1     Running     11 (11h ago)   11d
default       cron-test-27427638--1-bz64v               1/1     Running     0

Después de unos segundos, puede encontrar los pods programado y ver los logs de uno de los pods:

$ kubectl logs cron-test-27427638--1-bz64v
Wed Feb 23 23:18:10 UTC 2022
Hello this is Cron test

Ha creado un CronJob de Kubernetes que crea un objeto una vez por ejecución según la programación schedule: "/1 *".

Cambio schedulede CronJob

* * * * * 
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

schedule: "0 0 /2 " schedule: "30 8 * 0"

ExitosoJobsHistoryLimit & FailJobsHistoryLimit

En el escenario habitual, Kubernetes mantiene el registro de los últimos 3 cronjobs exitosos y el último cronjob fallido para que cuando ejecute el comando kubectl get all , vea este registro en el historial. Pero en el archivo de configuración de CronJob, puede editar este valor y tener más registros en el historial.

apiVersion: batch/v1          
kind: CronJob                        
metadata:
  name: cron-test
spec:
  schedule: "*/1 * * * *"  
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1          
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: cron-test
            image: busybox   
            command: ["/bin/sh"]
            args: ["-c", "date; echo Hello this is Cron test"] 
          restartPolicy: Never

Suspender el CronJob

Cuando se ejecuta la tarea programada sin tener una suspend sección en su archivo de configuración, se establecerá automáticamente el suspend en false y continuamente ejecutar el trabajo de acuerdo con el programa dado. Además, cuando ejecute el

kubectl get cronjob

comando, verá una salida como la siguiente.

NAME       SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob    * * * * *    False      0         <none>        3s
apiVersion: batch/v1          
kind: CronJob                        
metadata:
  name: cron-test
spec:
  schedule: "*/1 * * * *"  
  suspend: true        
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: cron-test
            image: busybox   
            command: ["/bin/sh"]
            args: ["-c", "date; echo Hello this is Cron test"] 
          restartPolicy: Never
NAME       SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob   * * * * *     True       0        <none>        19s

En un escenario real, no se edita el archivo de configuración de CronJob para agregar el suspend: true , en lugar de editar el archivo de configuración, puede usar el kubectl patch comando en su terminal para cambiar este valor.

//patch the cronjob
$ kubectl patch cronjob <cronjob-name> -p '{"spec":{"suspend":true}}'
- OR -
//path the configuration file
$ kubectl patch -f <file-name> -p '{"spec":{"suspend":true}}'
$ kubectl patch cronjob <cronjob-name> -p '{"spec":{"suspend":false}}'
- OR -
$ kubectl patch -f <file-name> -p '{"spec":{"suspend":false}}'

Otras cosas que debe saber

Los servicios en Kubernetes, no puede cambiar el mismo archivo de configuración del trabajo y volver a aplicarlo a la vez. Cuando realiza cambios en el archivo de configuración del trabajo, debe eliminar el trabajo anterior del clúster antes de aplicarlo.

En general, la creación de un trabajo crea un solo pod y realiza la tarea dada, como en el ejemplo anterior. Pero al usar paralelismo , puede iniciar varios pods, uno tras otro.

Mi trabajo de Cron no comenzó a tiempo. ¿Qué tengo que hacer?

En algunos casos, es posible que el CronJob no se active en el momento especificado.

En tal caso, hay dos escenarios:

  • Necesitamos ejecutar el job que no comenzó, incluso si se retrasó.
  • Necesitamos ejecutar el job que no comenzó solo si no se cruzó un límite de tiempo específico.

Necesito ejecutar el trabajo de Cron solo una vez

En Linux, tenemos el comando. El comando at le permite programar un programa para que se complete, pero solo una vez. Esta funcionalidad se puede lograr usando el recurso CronJob en Kubernetes usando el .spec.suspend

¿Mantiene Cron Job un historial de los trabajos que tuvieron éxito y fallaron?

La mayoría de las veces, necesita saber qué sucedió la última vez que se ejecutó el cronjob. Si no se produjo una actualización de la base de datos, no se actualizó un servidor API o cualquier otra acción que se suponía que debía ocurrir como resultado de la ejecución de CronJob, necesitaría saber por qué. De forma predeterminada, CronJob recuerda los últimos tres trabajos exitosos y el último fallido. Sin embargo, esos valores se pueden cambiar según sus preferencias configurando los siguientes parámetros:

  • spec.successfulJobsHistoryLimit: si no se establece, el valor predeterminado es 3. Especifica la cantidad de trabajos exitosos que se mantendrán en el historial.

  • spec.failedJobsHistoryLimit: si no se establece, el valor predeterminado es 1. Especifica la cantidad de trabajos fallidos que se mantendrán en el historial.

Si no necesita mantener ningún historial de ejecución, puede establecer ambos valores en 0.

Conclusión

Puede usar Kubernetes Jobs y CronJobs para administrar sus aplicaciones en contenedores. Los trabajos son importantes en los patrones de implementación de aplicaciones de Kubernetes, donde se necesita un mecanismo de comunicación junto con interacciones entre los pods y las plataformas. Esto puede incluir casos en los que una aplicación necesita un "controlador" o un "observador" para completar tareas o debe programarse para ejecutarse periódicamente.

La pagina Oficial de Kubernetes cuenta con una excelente documentación

Documentacion:

Y como Bonus Track

Usando CronJob puede ahorrarte mucho billing si usas AWS EKS Fargate

Usando AWS EKS con Fargate podemos ejecutar pods sin configurar ningún servidor, y también podemos configurar opciones de escalado basadas en el tráfico (usando, por ejemplo, métricas de CPU/Memoria con HPA).

Entonces, al usar esta técnica de escalado, podemos escalar en horas laborales y reducir nuestras implementaciones para ejecutarlas con al menos 1 pod en horas no laborales para ahorrar dinero; este artículo le muestra cómo.

Pero esos pods tienen un costo asociado y en algunos entornos, como DEV, TEST, UAT, esto significa dinero desperdiciado cuando nadie lo está usando.

Ahorrar dinero con Fargate

sin nombre2.gif

¡No olvides volver por el blog para comprobar qué hay nuevo por aquí!