CronJob
Kubernetes v1.21 [穩定]
CronJob 在重複排程中建立 Job。
CronJob 旨在執行定期排程的動作,例如備份、報表產生等等。一個 CronJob 物件就像 Unix 系統上 crontab (cron 表格) 檔案中的一行。它按照給定的排程定期執行 Job,排程以 Cron 格式撰寫。
CronJob 有其限制和特殊性。例如,在某些情況下,單個 CronJob 可以建立多個並行 Job。請參閱下方的限制。
當控制平面為 CronJob 建立新的 Job 和 (間接地) Pod 時,CronJob 的 .metadata.name
是命名這些 Pod 的基礎的一部分。CronJob 的名稱必須是有效的 DNS 子網域 值,但這可能會為 Pod 主機名稱產生非預期的結果。為了獲得最佳相容性,名稱應遵循更嚴格的 DNS 標籤 規則。即使名稱是 DNS 子網域,名稱長度也不得超過 52 個字元。這是因為 CronJob 控制器會自動將 11 個字元附加到您提供的名稱,並且 Job 名稱的長度限制為不超過 63 個字元。
範例
此範例 CronJob 清單每分鐘印出目前時間和 Hello 訊息
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "* * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
(使用 CronJob 執行自動化任務 將引導您更詳細地了解此範例)。
撰寫 CronJob 規格
排程語法
.spec.schedule
欄位為必要欄位。該欄位的值遵循 Cron 語法
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
# │ │ │ │ │ OR sun, mon, tue, wed, thu, fri, sat
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
例如,0 3 * * 1
表示此任務排定在每週一凌晨 3 點執行。
此格式也包含擴充的 "Vixie cron" 步進值。如 FreeBSD 手冊 中所述
步進值可以與範圍結合使用。在範圍後接
/<數字>
指定在範圍中跳過該數字的值。例如,0-23/2
可用於小時欄位中,以指定每隔一小時執行命令 (V7 標準中的替代方案為0,2,4,6,8,10,12,14,16,18,20,22
)。星號後也允許步進,因此如果您想說「每兩小時」,只需使用*/2
即可。
注意
排程中的問號 (?
) 與星號 *
的含義相同,也就是說,它代表給定欄位的任何可用值。除了標準語法外,也可以使用一些巨集,例如 @monthly
項目 | 描述 | 相當於 |
---|---|---|
@yearly (或 @annually) | 每年 1 月 1 日午夜執行一次 | 0 0 1 1 * |
@monthly | 每月第一天午夜執行一次 | 0 0 1 * * |
@weekly | 每週日早上午夜執行一次 | 0 0 * * 0 |
@daily (或 @midnight) | 每天午夜執行一次 | 0 0 * * * |
@hourly | 每小時開始時執行一次 | 0 * * * * |
若要產生 CronJob 排程運算式,您也可以使用像是 crontab.guru 之類的 Web 工具。
Job 範本
.spec.jobTemplate
定義了 CronJob 建立的 Job 的範本,而且這是必要的欄位。它與 Job 具有完全相同的結構描述,但它是巢狀的,並且沒有 apiVersion
或 kind
。您可以為範本化的 Job 指定常見的 metadata,例如 標籤(labels) 或 註解(annotations)。有關撰寫 Job 的 .spec
的資訊,請參閱撰寫 Job Spec。
延遲 Job 啟動的期限
.spec.startingDeadlineSeconds
欄位是選填的。此欄位定義了 Job 啟動的期限(以整數秒為單位),如果該 Job 因任何原因錯過了其排定的時間。
錯過期限後,CronJob 會略過該 Job 實例(未來的執行仍會排程)。例如,如果您有一個每天執行兩次的備份 Job,您可以允許它延遲最多 8 小時啟動,但不能再晚,因為之後進行的備份將沒有用處:您寧願等待下一次排定的執行。
對於錯過其設定期限的 Job,Kubernetes 將它們視為失敗的 Job。如果您沒有為 CronJob 指定 startingDeadlineSeconds
,則 Job 執行沒有期限。
如果設定了 .spec.startingDeadlineSeconds
欄位(非 null),CronJob 控制器會測量預期建立 Job 的時間與現在之間的時間差。如果差異大於該限制,它將略過此執行。
例如,如果設定為 200
,則允許在實際排程後最多 200 秒內建立 Job。
並行處理原則
.spec.concurrencyPolicy
欄位也是選填的。它指定如何處理由此 CronJob 建立的 Job 的並行執行。此規格可能僅指定以下並行處理原則之一
Allow
(預設):CronJob 允許並行執行 JobForbid
:CronJob 不允許並行執行;如果到了新的 Job 執行時間,而先前的 Job 執行尚未完成,則 CronJob 會略過新的 Job 執行。另請注意,當先前的 Job 執行完成時,仍然會考慮.spec.startingDeadlineSeconds
,並可能導致新的 Job 執行。Replace
:如果到了新的 Job 執行時間,而先前的 Job 執行尚未完成,則 CronJob 會以新的 Job 執行取代目前正在執行的 Job 執行
請注意,並行處理原則僅適用於同一 CronJob 建立的 Job。如果有多個 CronJob,則始終允許它們各自的 Job 並行執行。
排程暫停
您可以透過將選填的 .spec.suspend
欄位設定為 true,來暫停 CronJob 的 Job 執行。此欄位預設為 false。
此設定**不**會影響 CronJob 已啟動的 Job。
如果您將該欄位設定為 true,則所有後續執行都會暫停(它們仍然會排程,但 CronJob 控制器不會啟動 Job 來執行任務),直到您取消暫停 CronJob 為止。
Job 歷史記錄限制
.spec.successfulJobsHistoryLimit
和 .spec.failedJobsHistoryLimit
欄位指定應保留多少已完成和失敗的 Job。這兩個欄位都是選填的。
.spec.successfulJobsHistoryLimit
:此欄位指定要保留的成功完成 Job 的數量。預設值為3
。將此欄位設定為0
將不會保留任何成功的 Job。.spec.failedJobsHistoryLimit
:此欄位指定要保留的失敗完成 Job 的數量。預設值為1
。將此欄位設定為0
將不會保留任何失敗的 Job。
如需自動清除 Job 的另一種方法,請參閱自動清除已完成的 Job。
時區
Kubernetes v1.27 [穩定]
對於未指定時區的 CronJob,kube-controller-manager 會根據其本地時區解譯排程。
您可以透過將 .spec.timeZone
設定為有效的時區名稱,來為 CronJob 指定時區。例如,設定 .spec.timeZone: "Etc/UTC"
會指示 Kubernetes 根據協調世界時(Coordinated Universal Time)解譯排程。
Go 標準程式庫中的時區資料庫包含在二進位檔中,並在系統上沒有外部資料庫時用作後備。
CronJob 限制
不支援的時區規格
在 .spec.schedule
內使用 CRON_TZ
或 TZ
變數指定時區**並非官方支援**(而且從未支援過)。
從 Kubernetes 1.29 開始,如果您嘗試設定包含 TZ
或 CRON_TZ
時區規格的排程,Kubernetes 將無法建立資源,並出現驗證錯誤。對於已使用 TZ
或 CRON_TZ
的 CronJob 的更新,將繼續向用戶端報告警告。
修改 CronJob
依設計,CronJob 包含*新的* Job 的範本。如果您修改現有的 CronJob,您所做的變更將適用於在您的修改完成後開始執行的新 Job。已經啟動的 Job(及其 Pod)會繼續執行,而不會變更。也就是說,即使現有的 Job 仍在執行,CronJob 也**不**會更新它們。
Job 建立
CronJob 大約在其排程的每個執行時間建立一個 Job 物件。排程是近似的,因為在某些情況下可能會建立兩個 Job,或者可能不會建立任何 Job。Kubernetes 嘗試避免這些情況,但並不能完全防止它們。因此,您定義的 Job 應為*等冪*的。
從 Kubernetes v1.32 開始,CronJob 會將註解 batch.kubernetes.io/cronjob-scheduled-timestamp
套用至其建立的 Job。此註解表示 Job 的原始排程建立時間,並以 RFC3339 格式格式化。
如果 startingDeadlineSeconds
設定為較大的值或保持未設定(預設值),且 concurrencyPolicy
設定為 Allow
,則 Job 將始終至少執行一次。
注意
如果startingDeadlineSeconds
設定為小於 10 秒的值,則 CronJob 可能不會排程。這是因為 CronJob 控制器每 10 秒檢查一次。對於每個 CronJob,CronJob 控制器會檢查從上次排程時間到現在這段期間內錯過多少排程。如果錯過的排程超過 100 個,則它不會啟動 Job 並記錄錯誤。
Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew.
務必注意,如果設定了 startingDeadlineSeconds
欄位(非 nil
),控制器會計算從 startingDeadlineSeconds
的值到現在,而不是從上次排程時間到現在,發生了多少錯過的 Job。例如,如果 startingDeadlineSeconds
為 200
,則控制器會計算過去 200 秒內發生了多少錯過的 Job。
如果 CronJob 未能在其排程時間建立,則視為錯過。例如,如果 concurrencyPolicy
設定為 Forbid
,並且當先前的排程仍在執行時嘗試排程 CronJob,則將計為錯過。
例如,假設 CronJob 設定為從 08:30:00
開始每分鐘排程一個新的 Job,並且未設定其 startingDeadlineSeconds
欄位。如果 CronJob 控制器碰巧從 08:29:00
到 10:21:00
停機,則 Job 將不會啟動,因為錯過排程的錯過 Job 數量大於 100 個。
為了進一步說明這個概念,假設 CronJob 設定為從 08:30:00
開始每分鐘排程一個新的 Job,並且其 startingDeadlineSeconds
設定為 200 秒。如果 CronJob 控制器碰巧與前一個範例(08:29:00
到 10:21:00
)停機相同的時間段,則 Job 仍將在 10:22:00 啟動。發生這種情況是因為控制器現在檢查過去 200 秒內發生了多少錯過的排程(即 3 個錯過的排程),而不是從上次排程時間到現在。
CronJob 僅負責建立符合其排程的 Job,而 Job 則負責管理其代表的 Pod。
下一步
- 瞭解 Pod 和 Job,CronJob 依賴的兩個概念。
- 閱讀有關 CronJob
.spec.schedule
欄位的詳細格式。 - 有關建立和使用 CronJob 的說明,以及 CronJob 資訊清單範例,請參閱使用 CronJob 執行自動化任務。
CronJob
是 Kubernetes REST API 的一部分。請閱讀 CronJob API 參考文件以取得更多詳細資訊。