Cron en Kubernetes vs crontab Linux: trampas de zona horaria

Por qué la misma cadena cron de cinco campos dispara a horas distintas en GitHub Actions, K8s CronJob y crontab de servidor, y cómo previsualizar con seguridad.

0 9 * * 1-5 parece inequívoco: minuto cero, hora nueve, días laborables. Hasta que lo despliegas en tres plataformas y los backups corren a las 09:00 local, 09:00 UTC y 09:00 en la zona del control plane, todo con la misma cadena.

Esta comparación es para ingenieros que copian líneas cron entre servidores Linux, Kubernetes y CI sin releer las reglas de zona horaria.

Misma gramática, relojes distintos

El cron Unix clásico usa cinco campos (minuto, hora, día del mes, mes, día de la semana). La gramática es familiar; el reloj no se comparte:

PlataformaComportamiento típico de zona horaria
crontab de usuario LinuxZona local del servidor (timedatectl)
CronJob de KubernetesPor defecto del controller salvo timeZone (1.25+)
schedule de GitHub ActionsSiempre UTC
Quartz / algunas reglas cloudA menudo seis campos (segundos primero)

Una línea copiada de /etc/crontab en una VM de Shanghai a un workflow de GitHub se desplazará ocho horas salvo que conviertas.

crontab Linux: conoce el servidor

crontab -e en una VM evalúa expresiones en la zona local de la máquina. Los cambios de DST pueden saltar o repetir una hora en horarios de reloj de pared como 30 2 * * *.

Los runbooks deberían registrar:

  • Expresión
  • Salida de timedatectl del servidor
  • Equivalente UTC esperado para correlación de logs

Al correlacionar con timestamps de CloudWatch o Loki, convierte con un Timestamp Converter en lugar de cálculo mental durante un incidente.

Kubernetes: define timeZone explícitamente

Desde Kubernetes 1.25, CronJob soporta:

spec:
  timeZone: "Asia/Shanghai"
  schedule: "0 9 * * 1-5"

Sin timeZone, el comportamiento depende de la configuración del controller: no asumas que coincide con tu portátil. Trata la ausencia de zona horaria en YAML como bloqueador de review.

Actualizaciones de cluster y control planes multiregión son por qué zonas IANA explícitas ganan a "siempre usamos local".

GitHub Actions: solo UTC

on:
  schedule:
    - cron: "0 9 * * 1-5"

Esto es 09:00 UTC de lunes a viernes. Para 09:00 laborable en Shanghai necesitas 0 1 * * 1-5 en UTC durante el offset estándar, o documenta la tabla de offsets en el README del workflow.

Muchos tickets de "¿por qué corrió CI de noche?" empiezan aquí.

Previsualiza antes del merge

Independientemente de la plataforma:

  1. Parsea la expresión en un Cron Expression Parser
  2. Lee la descripción humana (cuidado con la semántica día-del-mes OR día-de-la-semana)
  3. Previsualiza próximas ejecuciones en UTC y en la zona objetivo
  4. Añade zona horaria + plataforma a la línea del runbook

Fallos habituales al copiar y pegar

ErrorResultado
Cron de Actions pensado como 9am localJob a hora de pared incorrecta
K8s sin timeZoneDeriva tras mover el cluster
Quartz de seis campos pegado como cincoSchedule inválido o incorrecto
DOM + DOW ambos definidos esperando ANDEjecuciones extra inesperadas

Aprendizaje relacionado

Sintaxis de campos, tablas por plataforma y checklist completo de depuración están en el curso Cron Expressions. Para correlación de logs entre zonas, combínalo con Timestamps in logs across timezones.

Idea clave

Las cadenas cron son agnósticas de zona horaria; los schedulers no lo son. Documenta plataforma + zona junto a cada línea, previsualiza en UTC y local, y configura timeZone de Kubernetes a propósito, no por accidente.

Herramientas relacionadas

Usa las herramientas de este artículo

Analizador de expresiones croncron / cron parser / cron expression parserConversor de timestamp Unix onlinetimestamp / utc timestamp converter / unix timestamp converter

Cursos relacionados

curso de expresiones cronQué aprenderás en este curso de cron Unix.Curso de Unix time y timestampsQué aprenderás en este curso y cómo están organizadas las lecciones.

Volver a artículos