Toda aplicación tiene tareas que necesitan ejecutarse de forma periódica: limpiar registros viejos, enviar reportes diarios, sincronizar datos con un sistema externo, renovar certificados. En el mundo pre-cloud esto se resolvía con un crontab en un servidor Linux. Simple, predecible, conocido.
Cuando tu infraestructura se muda a Kubernetes, la pregunta inevitable aparece: ¿dónde pongo mis cron jobs? La respuesta obvia son los CronJobs nativos de Kubernetes. Pero como todo en este ecosistema, “nativo” no siempre significa “simple”.
Los CronJobs de Kubernetes son una herramienta poderosa con ventajas reales, pero también con trampas que pueden convertir una tarea de 5 líneas en un dolor de cabeza operativo. Vamos a desgranar ambos lados para que puedas decidir con información.
🏠Viven donde vive tu aplicación
La ventaja más importante y la que justifica todo lo demás: tus jobs corren dentro del mismo cluster donde corre tu aplicación. Tienen acceso nativo a tus servicios internos, bases de datos, colas de mensajes, Secrets y ConfigMaps — sin necesidad de configurar VPNs, whitelists de IPs o credenciales externas.
Si tu tarea necesita conectarse a la base de datos de producción para limpiar registros, no necesitás abrir un túnel ni gestionar credenciales adicionales. El CronJob tiene el mismo acceso de red y los mismos mecanismos de autenticación que cualquier otro pod del cluster.
📈Escalan con tu infraestructura
A diferencia de un crontab en un servidor fijo, los CronJobs se benefician del autoescalado del cluster. Si un job necesita más recursos de lo habitual, Karpenter puede levantar un nodo adicional para acomodarlo. Cuando el job termina, el nodo se libera. No estás pagando por un servidor dedicado idle el 95% del tiempo esperando que llegue la hora de ejecutar una tarea.
🔁Reintentos y gestión de fallos integrados
Kubernetes maneja automáticamente qué pasa cuando un job falla. Podés configurar cuántas veces debe reintentar antes de darse por vencido, qué hacer si la ejecución anterior no terminó cuando arranca la siguiente, y cuántos registros de ejecuciones pasadas mantener. Todo esto viene de fábrica — no tenés que programar lógica de reintentos ni escribir scripts de supervisión.
📊Observabilidad unificada
Si ya tenés un stack de monitoreo (Prometheus, Grafana, Loki), los CronJobs aparecen automáticamente en tus dashboards y logs. Podés ver cuándo se ejecutó cada job, cuánto tardó, si falló, y qué pasó — en la misma interfaz que usás para monitorear el resto de tu aplicación. No necesitás una herramienta separada para saber si tu tarea de las 3 AM realmente corrió.
📁Declarativos y versionables
La definición de un CronJob es un manifiesto de Kubernetes como cualquier otro. Vive en tu repositorio de Git, pasa por code review, se despliega con tu pipeline de CI/CD, y tiene historial de cambios. Si alguien cambia el schedule de un job de diario a cada hora por error, el diff está en el pull request.
Un crontab -e donde los cambios no dejan rastro, no tienen revisión, y solo el autor sabe qué hace cada línea. El manifiesto de Kubernetes es la documentación viva del job.
🛡️Aislamiento de recursos
Cada ejecución crea un pod nuevo con sus propios requests y limits de CPU y memoria. Si un job consume más recursos de lo esperado, no afecta a los demás pods del cluster. En un servidor tradicional, un cron que se come toda la RAM puede tumbar otros procesos que corren en la misma máquina.
⏱️La precisión del schedule no es exacta
Los CronJobs de Kubernetes no garantizan ejecución al segundo. El controlador revisa periódicamente si hay jobs que deban ejecutarse, y si hay alta carga en el API server, el job puede arrancar tarde. En la mayoría de los casos no importa — si tu reporte corre a las 6:00:03 en vez de 6:00:00, nadie lo nota.
Si el controlador detecta que se perdieron más de 100 ejecuciones consecutivas (porque el cluster estuvo caído o el job suspendido mucho tiempo), deja de intentar y requiere intervención manual. Es un límite poco conocido que puede sorprender en clusters que se apagan por períodos.
⚡Ejecuciones concurrentes pueden ser peligrosas
Por defecto, Kubernetes puede lanzar una nueva ejecución de un CronJob incluso si la anterior todavía está corriendo. Si tu tarea tarda más de lo esperado y el schedule es ajustado, podés terminar con múltiples instancias del mismo job corriendo simultáneamente.
Imaginá dos instancias simultáneas de un job que procesa pagos pendientes o que envía emails a clientes. Kubernetes te da la opción de configurar la política de concurrencia (prohibir, reemplazar o permitir), pero tenés que saber que existe y configurarla explícitamente — no se resuelve solo.
🔗No hay dependencias entre jobs
Si tenés un job que necesita ejecutarse después de que otro termine (exportar datos → procesarlos → enviar reporte), los CronJobs de Kubernetes no tienen forma nativa de expresar esa dependencia. Cada CronJob es independiente.
Para orquestar cadenas de tareas con dependencias, necesitás herramientas adicionales como Argo Workflows o Apache Airflow. Los CronJobs son un cron, no un workflow engine.
🐛Debugging puede ser frustrante
Cuando un CronJob falla, el pod que lo ejecutó eventualmente se limpia. Sin logs centralizados, los logs desaparecen con él. Los errores más comunes — imagen de Docker que no se puede pullear, secrets que no existen, permisos insuficientes — producen mensajes no siempre intuitivos.
Como los CronJobs corren en horarios específicos — muchas veces de noche o madrugada — el ciclo de feedback para debuggear es lento: hacés un cambio, esperás a que se ejecute, ves si funcionó, repetís. Sin Loki u otro agregador de logs, el historial de errores simplemente no existe.
🌍La gestión de timezones es relativamente nueva
Durante años, los CronJobs usaban la timezone del nodo donde corría el controlador — y no había forma de especificar otra. Recién en versiones recientes de Kubernetes se agregó soporte para configurar la timezone del schedule, pero muchos clusters todavía corren versiones donde esto es beta o no está disponible.
Si tu equipo está en Argentina (UTC-3), tu cluster corre en UTC, y tu cron debe ejecutarse a las 8 AM hora local, necesitás hacer la conversión mental en cada cambio. Parece menor, pero es una fuente constante de errores de configuración y confusion que afecta a casi todos los equipos que no son UTC.
💸Los recursos se consumen aunque el job dure segundos
Cada ejecución crea un pod que requiere un nodo con capacidad disponible. Si tu cluster está ajustado y no hay espacio, el job queda pendiente hasta que el autoscaler levante un nodo nuevo — lo cual puede tardar minutos. Para jobs que tardan segundos en ejecutarse, esperar 2-3 minutos por un nodo es absurdo.
Si tenés muchos CronJobs que se ejecutan al mismo horario (varios jobs a medianoche), podés generar un spike de demanda que levante nodos innecesariamente. Esos nodos tardan minutos en estar listos, ejecutan jobs de segundos, y quedan idle hasta que el autoscaler los elimine. Distribuir los horarios mitiga esto.
🔧No reemplazan un scheduler real
Para tareas simples y periódicas, los CronJobs son perfectos. Pero si tus necesidades crecen — reintentos condicionales, dependencias entre tareas, ejecuciones manuales con parámetros, historial detallado, notificaciones por canal — vas a necesitar herramientas adicionales. Los CronJobs son un cron, no un workflow engine.
- La tarea es simple y autónoma — no depende de que otra termine primero
- El schedule es fijo y no necesitás precisión de subsegundos
- La tarea necesita acceso a recursos internos del cluster
- Querés que el job viva en el mismo pipeline de CI/CD que tu app
- La duración del job es predecible entre ejecuciones
- Necesitás orquestar cadenas de tareas con dependencias (Argo Workflows, Airflow)
- La tarea requiere precisión de timing al segundo
- Necesitás un historial detallado con UI de gestión y reintentos manuales con parámetros
- La tarea no tiene relación con el cluster — podría correr en Lambda o Step Functions
| Característica | ¿Viene de fábrica? | Notas |
|---|---|---|
| Acceso a servicios internos | ✓ Sí | Misma red y autenticación que el resto del cluster |
| Reintentos automáticos | ✓ Sí | Configurable con backoffLimit |
| Logs y observabilidad | ✓ Sí | Requiere agregador de logs para persistir tras el pod |
| Versionable en Git | ✓ Sí | Como cualquier manifiesto de Kubernetes |
| Control de concurrencia | ✓ Sí | Hay que configurarlo explícitamente — no es el default seguro |
| Precisión al segundo | ✗ No | El controlador puede tener delay según la carga del API server |
| Dependencias entre jobs | ✗ No | Requiere Argo Workflows u otra herramienta de orquestación |
| Timezone configurable | ✗ Parcial | Solo en versiones recientes de Kubernetes — verificar en tu cluster |
Implementar CronJobs no debería ser complicado
Para el 80% de los casos — limpieza de datos, reportes diarios, sincronizaciones periódicas — los CronJobs de Kubernetes son la herramienta correcta. En SleakOps podés definirlos y desplegarlos de forma directa, con la configuración de recursos, secrets, schedules y políticas de concurrencia integrada en un flujo claro.
Conocé SleakOps →