Kubernetes Job & CronJob - 排程與一次性任務
與長期運行的 Service (如 Web Server) 不同,有些任務是 一次性 的,執行完畢就結束(Exit Code 0)。 Kubernetes 提供了 Job 與 CronJob 來處理這類工作負載。
Job (一次性任務)
Job 會建立一個或多個 Pod,並確保指定數量的 Pod 成功終止 (Successfully Terminate)。 如果 Pod 失敗 (Exit Code 非 0),Job 會依照設定重試建立新的 Pod,直到成功為止。
定義 Job
建立 pi-job.yaml (計算圓周率):
# pi-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ['perl', '-Mbignum=bpi', '-wle', 'print bpi(2000)']
restartPolicy: Never
backoffLimit: 4 # 重試次數限制
- restartPolicy: Job 的 Pod 只能設為
Never或OnFailure(不能用Always,因為 Job 預期會結束)。- Never: 當 Pod 失敗 (Exit Code != 0) 時,K8s 會 建立一個全新的 Pod 來重試。舊的失敗 Pod 會被保留(便於查看 logs 或除錯),但同時也會留下較多紀錄。
- OnFailure: 當 Pod 失敗時,K8s 會 原地重啟該 Pod 內的容器。Pod 的 IP 和連接的 Volume 保持不變,適合資料量大或初始化成本高的任務。
- backoffLimit: 如果失敗,最多重試幾次。
執行 Job
將上述內容儲存為 pi-job.yaml 後,執行:
kubectl apply -f pi-job.yaml
查看執行狀態與結果:
# 查看 Job 狀態 (COMPLETIONS 顯示 1/1 代表成功)
kubectl get job pi
# 查看產生的 Pod (名稱會是 pi-xxxx)
kubectl get pods
# 查看執行結果 output (因為是計算圓周率,會印出結果)
kubectl logs job/pi
Job 控制參數 (批次處理)
如果你有一個很大的任務需要處理(例如:處理 100 張圖片),你可以讓一個 Job 建立多個 Pod 來分工合作。
- completions: 總共需要成功幾次。
- 例如設定
10,代表這個 Job 必須要有 10 個 Pod 成功執行完畢,整個 Job 才算完成。
- 例如設定
- parallelism: 同時跑幾個 Pod (並行數)。
- 例如設定
2,代表 K8s 會隨時保持 2 個 Pod 在執行,直到湊滿 10 次成功為止。
- 例如設定
範例情境:你需要處理 10 筆資料,但為了避免瞬間資源飆高,你希望一次只處理 2 筆。
spec:
completions: 10 # 總共要完成 10 個 Pod
parallelism: 2 # 同一時間最多 2 個 Pod 在跑
流程會是:
- 啟動 2 個 Pod。
- 其中 1 個跑完了 -> 再補 1 個新的 (維持 2 個)。
- 直到總共有 10 個 Pod 成功跑完為止。
CronJob (排程任務)
CronJob 就是 K8s 版本的 Crontab。它會根據設定的時間表 (Schedule) 定期建立 Job。
定義 CronJob
建立 hello-cronjob.yaml (每分鐘印一次 Hello):
# hello-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: '*/1 * * * *'
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
執行 CronJob:
kubectl apply -f hello-cronjob.yaml
Cron 表達式
格式與 Linux Crontab 相同:
分 時 日 月 週
*/1 * * * *: 每分鐘0 0 * * *: 每天午夜0 9 * * 1: 每週一早上 9 點
常用指令
# 查看 CronJob 設定
kubectl get cronjob
# 查看由 CronJob 產生的 Jobs (可見歷史執行紀錄)
kubectl get jobs
# 刪除 CronJob (也會清理相關的 Jobs 與 Pods)
kubectl delete cronjob hello
手動觸發 CronJob
有時候我們不想要等到排程時間,想立刻執行一次測試(例如測試備份腳本)。
可以使用 create job --from 指令,從現有的 CronJob Template 建立一個 Job:
# 從 CronJob "hello" 建立一個名為 "hello-manual-001" 的 Job
kubectl create job --from=cronjob/hello hello-manual-001
這會立即啟動一個 Job,內容完全參照 CronJob 裡的設定。
CronJob 重要參數
這些參數位於 spec 層級下,用來控制排程行為:
spec:
schedule: '*/1 * * * *'
startingDeadlineSeconds: 100
concurrencyPolicy: Forbid
jobTemplate: ...
- startingDeadlineSeconds:
- 如果到了預定時間因為某些原因 (如資源不足、Control Plane 忙碌) 沒跑,錯過多久就不跑了。
- 例如設定
100秒,如果超過 100 秒還沒排程成功,這次就放棄。
- concurrencyPolicy (並發策略):
- 這決定了「如果上一次 Job 還沒跑完,下一次時間到了該怎麼辦」。
Allow(預設): 允許並發。不管上一次跑完沒,新的照樣跑 (可能同時有好幾個 Job)。Forbid: 禁止並發。上一次沒跑完,這一次就跳過 (Skip)。Replace: 取代。停掉上一次還沒跑完的 Job,強制跑新的。
總結
使用 Job 處理批次運算、資料庫遷移 (Migration);使用 CronJob 處理定期備份、報表生成等任務。