Kubernetes CronJob 會依照 manifest 中 schedule 欄位所定義的標準五欄位 cron 運算式,以重複排程執行 Job,而 controller-manager 會在其設定的時區中評估該運算式,以決定何時產生每個新的 pod。
那一行的定義承載了整個時間模型。CronJob 上的所有其他欄位,包括 concurrencyPolicy、startingDeadlineSeconds、successfulJobsHistoryLimit、failedJobsHistoryLimit 以及 jobTemplate,都只控制已排定執行開始時會發生什麼事,但沒有一個能決定執行何時開始。schedule 字串是唯一承載時間的地方,而寫錯它正是「我的 CronJob 從來不執行」這類支援單最常見的原因。
其格式與 Unix crontab 項目完全相同:分鐘、小時、日期、月份、星期,以單一空格分隔。五個以空白分隔的欄位,沒有秒、沒有年、沒有問號。刻意沿用經典 Unix cron 的格式。Kubernetes 選擇標準格式,讓任何寫過 crontab(5) 項目的人早已熟知大部分規則,同一個運算式也能在開發環境的 crontab 與正式叢集之間複製貼上,無需翻譯。

Kubernetes 如何讀取 schedule 欄位
Kubernetes API 在每次建立與更新時,都會依據文件化的五欄位語法驗證 spec.schedule。pod template、restart policy 與其他 Job 形狀的欄位都位於其下,但排程器只會檢查 spec.schedule 中的字串。controller-manager 會輪詢該排程,一旦符合,就從 spec.jobTemplate 建立一個新的 Job 資源;該 Job 接著會建立一或多個 pod。
由於 Kubernetes 沿襲 Unix crontab 的語法,同樣的特殊字元也都適用。星號 (*) 代表該欄位的每個有效值,斜線 (/) 表示步進值,連字號 (-) 定義包含性範圍,逗號則列舉離散值。因此,排程 */5 * * * * 表示控制器在每天的每個小時中每五分鐘執行一次;0 9 * * 1-5 則表示僅在平日 09:00 執行。該語法定義於 man7.org 上的 crontab(5),並由 cronie 的 crontab(5) 參考手冊 重述,Kubernetes 都與其對齊。
為何手寫的 cron 運算式會出錯
大多數失敗的 CronJob 排程源自三種錯誤:兩個欄位順序對調、誤讀星期欄位的編號,或是只打算設定其中之一時卻同時設定了日期與星期。標準欄位順序——分鐘、小時、日期、月份、星期——很容易在腦中翻轉,因為五個位置會混在一起;一旦分鐘與小時對調,工作就會悄悄地被移到截然不同的時間,卻不會觸發驗證錯誤。
星期採用 Unix 編號,星期日為 0、星期六為 6,並非某些行事曆函式庫所使用的 1 到 7 編號。欄位組合的陷阱最為細微:當日期與星期同時被限制時,經典 cron 使用的是 OR 語意,因此 0 9 1 * 1 會在每月 1 號以及每個星期一執行,而不是只有第一個星期一。Kubernetes 保留了這個行為,使得預期 AND 語意的讀者容易踩坑。
使用 Cron 運算式產生器建立排程
Cron 運算式產生器完全免除了背誦的負擔。你只需選擇頻率、調整該排程所對應的選項,然後複製產生的五欄位字串。相關欄位會即時更新,並以白話摘要描述同一排程的含義,讓你在運算式進入叢集之前能輕鬆再次確認其意義。
- 挑選與期望頻率相符的排程類型:每分鐘、每 N 分鐘、每小時、每天、平日、每週、每月。
- 將該排程所顯示的唯一選項——間隔、分鐘、小時、星期或日期——設定為你想要的數值。
- 閱讀產生的五欄位運算式以及顯示於選項下方的白話摘要。
- 複製運算式,然後貼入 CronJob manifest 的 spec.schedule。
- 在部署 manifest 之前,先解析該排程並列出接下來的執行時間以進行驗證。
將排程加入 Kubernetes CronJob manifest
手邊有了有效的運算式之後,manifest 本身很短。下列範例會在每天凌晨 02:30 執行資料庫備份容器,並透過產生器的每日預設得到 30 2 * * *:
apiVersion: batch/v1 kind: CronJob metadata: name: db-backup spec: schedule: "30 2 * * *" concurrencyPolicy: Forbid startingDeadlineSeconds: 300 successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 1 jobTemplate: spec: template: spec: restartPolicy: OnFailure containers: - name: backup image: backup-tools:1.4 args: ["/usr/local/bin/backup.sh"]只要五個具體步驟就能將其接入叢集:
- 將 manifest 另存為 db-backup-cronjob.yaml,放在你的工作目錄中。
- 在目標叢集上執行 kubectl apply -f db-backup-cronjob.yaml。
- 使用 kubectl get cronjob db-backup 確認註冊結果;SCHEDULE 欄位應顯示你所貼上的運算式。
- 使用 kubectl get jobs --watch 觀察首次排定執行,並透過其 pod 上的 kubectl logs 追蹤所產生的 Job。
- 使用 kubectl create job --from=cronjob/db-backup manual-1 視需要強制執行一次性任務,以便在不用等時鐘到的情況下驗證 template。
Cron 欄位範圍與允許值
Kubernetes 排程器只接受 crontab(5) 所文件化的數值。超出範圍的數字會在 apply 時通過不了 API 驗證,這算是個有用的安全網;不過從一開始就待在文件化範圍內,就能避免在 API 伺服器之間來回:
| 欄位 | 位置 | 有效範圍 | 允許的特殊語法 |
|---|---|---|---|
| Minute | 1 | 0-59 | *, */n, a-b, a,b,c |
| Hour | 2 | 0-23 | *, */n, a-b, a,b,c |
| Day of month | 3 | 1-31 | *, */n, a-b, a,b,c |
| Month | 4 | 1-12 | *, */n, a-b, a,b,c |
| Day of week | 5 | 0-6 (Sun-Sat) | *, */n, a-b, a,b,c |
MON 或 JAN 等名稱在星期與月份欄位中也可使用,與 crontab(5) 參考手冊一致。產生器會將所有輸入維持在這些範圍內,因此其產生的運算式一定能通過 Kubernetes 驗證。
在進入正式環境前驗證排程
能正確解析的排程,意思仍可能不對。兩個簡單的驗證就能抓出大多數意外。首先,把運算式貼到 Cron Parser,查看接下來幾個符合的時間。這會立即暴露出欄位順序對調、星期差一、或缺少步進等問題。其次,部署到非正式叢集,觀察前兩、三次執行是否落在預期的時間,並擷取日誌供檢�。若想更深入地了解如何解讀解析結果並確認時間,parse-and-preview 指南 完整介紹了整個工作流程。
controller-manager 的時區在此至關重要。Kubernetes 文件說明,CronJob 排程會依據傳給 kube-controller-manager 的 --time-zone 旗標進行評估,而該旗標預設為 UTC。一個「感覺像」本地時間 09:00 的排程,實際上會在 09:00 UTC 觸發,除非啟動控制器時明確指定時區,因此在信任時鐘直覺之前,請先在叢集的啟動設定中確認該旗標。日光節約時間的轉換也可能略過或重複一小時的本地時鐘時間,這也是正式環境中 UTC 是較安全預設值的原因。
Kubernetes CronJob 排程的常見陷阱
有三個陷阱會困住有經驗的維運人員。第一,排定在 29、30 或 31 日執行的每月任務,在 2 月或沒有該日期的 30 天月份中根本不會執行;控制器會跳過該月,而不是順延到下一月。第二,當排程忙碌時,將 concurrencyPolicy 設為 Allow 的運算式可能會在單次執行時間超過間隔時堆疊出重疊的 Job,因此 Forbid 或 Replace 通常是較安全的選擇。第三,運算式只描述時間,並不涵蓋等冪性、重試、鎖定或監控;這些都必須設計在容器與周邊平台之中。
產生器透過將每月排程以獨立預設形式呈現、並接受 1 到 31 的任何日期,從而避開了第一個陷阱,而上述文件化的欄位限制也讓所有輸入都落在控制器可接受的範圍內。其餘兩個陷阱屬於政策與應用程式設計層面的決策,任何排程字串都無法解決,因此應在 manifest 的 concurrencyPolicy、startingDeadlineSeconds 以及容器的錯誤處理程式碼中處理,而非寫在 cron 運算式本身。產生器對任何 cron 使用情境所提出的同樣提醒在此也適用:在部署前請先確認目標系統接受標準五欄位 cron,因為某些代管的排程器會加入秒、年的欄位、問號或廠商專屬語法。
整合運用
一旦決定排程,建立一個可運作的 Kubernetes CronJob 就是三步驟工作流程:在 Cron 運算式產生器中選擇頻率,將產生的五欄位字串貼入 spec.schedule,並在正式環境依賴該工作之前,依據 controller-manager 的時區驗證接下來的執行時間。每個步驟都很小、格式穩定、驗證自動;唯一真正的失敗模式就是手動寫錯五個欄位。產生作業完全在本機瀏覽器內進行,因此排程與任何指令參考都不會離開你的機器,直到使用 kubectl 套用 manifest 為止。