Kubernetes Cron 与 Linux Crontab:时区陷阱对比

同一条五字段 cron 在 GitHub Actions、K8s CronJob 与服务器 crontab 上为何不同时刻触发——以及如何安全预览。

0 9 * * 1-5 看起来毫无歧义:第 0 分、第 9 时、工作日。直到你把它部署到三个平台——备份分别在 本地 09:00UTC 09:00控制平面时区 09:00 运行,而字符串完全相同。

本文面向在 Linux 服务器、Kubernetes 与 CI 之间复制 cron 行、却未重读时区规则的工程师。

语法相同,时钟不同

经典 Unix cron 为 五字段(分、时、日、月、周)。语法熟悉,时钟 并不共享:

平台典型时区行为
Linux 用户 crontab服务器本地时区(timedatectl
Kubernetes CronJob未设 timeZone 时用控制器默认(1.25+ 可显式指定)
GitHub Actions schedule始终 UTC
Quartz / 部分云规则常为六字段(秒在前)

从上海 VM 的 /etc/crontab 拷到 GitHub 工作流而不换算,会差八小时。

Linux crontab:先认清服务器

VM 上 crontab -e机器本地时区 求值。夏令时切换时,30 2 * * * 这类墙钟调度可能跳过或重复一小时。

运行手册应记录:

  • 表达式
  • 服务器 timedatectl 输出
  • 用于对日志的 UTC 等价时刻

与 CloudWatch、Loki 等时间戳关联时,用 时间戳转换器 换算,别在 incident 里心算。

Kubernetes:显式设置 timeZone

Kubernetes 1.25 起 CronJob 支持:

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

timeZone 时行为取决于控制器配置——勿假设 与笔记本一致。YAML 缺时区应视为评审阻塞项。

集群升级与多区域控制平面,是显式 IANA 时区优于「我们一直用本地」的原因。

GitHub Actions:仅 UTC

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

表示 UTC 周一至周五 09:00。若要上海工作日 09:00,在标准偏移下需 UTC 的 0 1 * * 1-5——或在 workflow README 写清偏移表。

许多「CI 为何半夜跑」的工单由此开始。

合并前预览

无论平台:

  1. Cron 表达式解析器 中解析
  2. 阅读人类可读描述(注意日/周 OR 语义)
  3. UTC 与目标时区预览下次执行
  4. 运行手册行注明时区 + 平台

常见复制粘贴失败

错误结果
Actions 按本地 9 点理解墙钟时刻错
K8s 未设 timeZone集群迁移后漂移
六字段 Quartz 当五字段粘贴非法或错误调度
日+周同时限制却期望 AND意外多跑

延伸阅读

字段语法、平台对照与完整检查清单见 Cron 表达式课程。跨时区日志关联可配合 日志中的时间戳与时区

小结

Cron 字符串与时区无关;调度器有关。 每条线旁注明平台与时区,在 UTC 与本地预览,Kubernetes 的 timeZone有意设置——而不是碰运气。

相关工具

使用本文提到的工具

Cron 表达式解析器cron / crontab / schedule时间戳转换器timestamp / unix / epoch

继续学习相关格式

Cron 表达式课程系统学习 Unix cron:五字段语法、范围与步长、时区陷阱、平台差异、常见任务模式与实用调试流程。Unix 时间与时间戳课程系统学习 Unix epoch、秒与毫秒、UTC、时区、ISO 8601,以及在日志与 API 中排查时间问题。

返回文章列表