如何使用Kubernetes Job運行一次性任務
Job 概念
在 kubernetes 中,Deployment、DaemonSet會持續運行任務,這些 pod 中的進程在崩潰退出時會重新啟動,永遠達不到完成態。你也許會遇到這樣的場景,當需要運行一個一次性的可完成的任務,其進程終止后,不應該再重新啟動,那么 Job 資源類型完全符合你。Kubernetes 中通過 Job 資源提供了對此的支持,它允許你運行一種 pod,該 pod 在內部進程成功結束時,不重啟容器。一旦任務完成,pod 就被認為處于完成狀態。在發生節點故障時,該節點上由 Job 管理的 pod 將按照 ReplicaSet 的 pod 的方式, 重新安排到其他節點,以確保任務能夠成功完成,所以 Job 通常用于執行一次性任務或批處理作業。Job 還可以控制 Pod 的數量,確保一定數量的 Pod 成功完成任務。Job 的一些常用使用場景:
- 批處理作業:Job可以被用來運行需要大量計算資源的作業,例如對大量數據的處理,機器學習模型訓練等。
- 數據處理:Job也可以用來處理大量數據,例如數據的清洗、歸檔和備份等。
- 定時任務:Job可以被用來定期執行一些任務,例如定期生成報表、定期清理數據等。
- 資源分配:通過Job控制器,我們可以為特定任務分配所需的計算資源,例如CPU和內存等,以保證任務能夠順利執行。
Job 定義
下面是一個 Job 配置示例。它負責計算 π 到小數點后 2000 位,并將結果打印出來。此計算大約需要 10 秒鐘完成。job.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
創建它,查看Job 、Pods 的狀態:Pod 狀態為 Running,說明已經在執行,Job 的 COMPLETIONS 為 0/1,表示按照預期啟動了一個 Pod,還未完成。
[root@nsg]/tmp/test# kubectl apply -f job.yaml
job.batch/pi created
[root@nsg]/tmp/test# kubectl get jobs,pods
NAME COMPLETIONS DURATION AGE
job.batch/pi 0/1 39s 39s
NAME READY STATUS RESTARTS AGE
pod/pi-d5f6q 1/1 Running 0 39s
等待大概10s左右,發現狀態已經變為 Completed 了, kubectl logs 可以查看 Pod 的標準輸出:
[root@nsg]/tmp/test# kubectl get jobs,pods
NAME COMPLETIONS DURATION AGE
job.batch/pi 1/1 43s 47s
NAME READY STATUS RESTARTS AGE
pod/pi-d5f6q 0/1 Completed 0 47s
# 查看日志
[root@nsg]/tmp/test# kubectl logs -f pi-d5f6q
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275901
Job 失敗處理
Job 失敗處理
Job 的 restart 策略只有如下兩種(沒有pod的策略Always):
- Never:只要任務沒有完成,則新創建pod運行,直到job完成,會產生多個pod。(默認)
- OnFailure:只要pod沒有完成,就會重啟pod,重新執行任務。
如果失敗了會怎么樣呢?我們故意引入一個錯誤,修改 job.yaml:將執行命令修改為錯誤的。
...
command: ["per", "", "-", ""]
創建它,查看Job 、Pods 的狀態, 當 restart 策略為 Never 時,會看到只要任務沒有完成,就會新創建pod運行,直到job完成,會產生多個pod:
[root@nsg]/tmp/test# kubectl apply -f job.yaml
job.batch/pi created
[root@nsg]/tmp/test# kubectl get jobs,pods
NAME COMPLETIONS DURATION AGE
job.batch/pi 0/1 3m14s 3m14s
NAME READY STATUS RESTARTS AGE
pod/pi-9shvk 0/1 StartError 0 3m10s
pod/pi-gjwp7 0/1 StartError 0 2m
pod/pi-mp96m 0/1 StartError 0 2m40s
pod/pi-nrb64 0/1 StartError 0 3m14s
pod/pi-nznrc 0/1 StartError 0 3m
當 restart 策略為 OnFailure 時,只要pod沒有完成,就會重啟pod,重新執行任務:
[root@nsg]/tmp/test# kubectl apply -f job.yaml
job.batch/pi created
[root@nsg]/tmp/test# kubectl get jobs,pods
NAME COMPLETIONS DURATION AGE
job.batch/pi 0/1 103s 103s
NAME READY STATUS RESTARTS AGE
pod/pi-drrft 0/1 RunContainerError 4 (8s ago) 103s
回退限制
backoffLimit 表示回退限制,可以指定重試幾次后將 Job 標記為失敗。如果沒有明確指定它,則默認為6。job.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
backoffLimit: 2
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
創建它,查看Job 、Pods 的狀態, 可以看到重試了兩次,但是還是失敗了,后面就沒有再次重試了。
[root@nsg]/tmp/test# kubectl apply -f job.yaml
job.batch/pi created
[root@nsg]/tmp/test# kubectl get jobs,pods
NAME COMPLETIONS DURATION AGE
job.batch/pi 0/1 80s 80s
NAME READY STATUS RESTARTS AGE
pod/pi-6hqmr 0/1 StartError 0 76s
pod/pi-sj98k 0/1 StartError 0 80s
pod/pi-xc5k4 0/1 StartError 0 66s
并行執行 Job
同時運行多個 Pod,提高 Job 的執行效率。這個可以通過 parallelism 設置。
parallelism
job.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
parallelism: 2
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
創建它,查看Job 、Pods 的狀態, Job 一共啟動了兩個 Pod,而且 AGE 相同,可見是并行運行的。
[root@nsg]/tmp/test# kubectl apply -f job.yaml
job.batch/pi created
[root@nsg]/tmp/test# kubectl get jobs,pods
NAME COMPLETIONS DURATION AGE
job.batch/pi 2/1 of 2 8s 13s
NAME READY STATUS RESTARTS AGE
pod/pi-k9bfs 0/1 Completed 0 13s
pod/pi-ztcxv 0/1 Completed 0 13s
completions
還可以通過 completions 設置 Job 成功完成 Pod 的總數 修改 job.yaml:每次運行兩個 Pod,直到總共有 6 個 Pod 成功完成。
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
parallelism: 2
completions: 6
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
創建它,查看Job 、Pods 的狀態, 可見一共有6個Pod完成任務,符合預期。如果不指定 completions 和 parallelism,默認值均為 1。
[root@nsg]/tmp/test# kubectl apply -f job.yaml
job.batch/pi created
[root@nsg]/tmp/test# kubectl get jobs,pods
NAME COMPLETIONS DURATION AGE
job.batch/pi 6/6 25s 31s
NAME READY STATUS RESTARTS AGE
pod/pi-67vm7 0/1 Completed 0 31s
pod/pi-bb8nl 0/1 Completed 0 22s
pod/pi-fchrq 0/1 Completed 0 14s
pod/pi-k47pr 0/1 Completed 0 22s
pod/pi-rt8n8 0/1 Completed 0 14s
pod/pi-zzc96 0/1 Completed 0 31s
自動清理完成的 Job
發現 Job 完成以后,Pod 依然存在,完成的 Job 通常不需要留存在系統中,在系統中一直保留它們會給 API 服務器帶來額外的壓力。
自動清理已完成 Job (狀態為 Complete 或 Failed)的另一種方式是使用由 TTL 控制器 所提供 的 TTL 機制。通過設置 Job 的 .spec.ttlSecondsAfterFinished 字段,可以讓該控制器清理掉 已結束的資源。如果該字段設置為 0,Job 在結束之后立即成為可被自動刪除的對象。如果該字段沒有設置,Job 不會在結束之后被 TTL 控制器自動清除。嘗試一下:job.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
ttlSecondsAfterFinished: 20 ##任務完成以后,20s自動清理Pod
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
創建它,查看Job 、Pods 的狀態。
[root@nsg]/tmp/test# kubectl apply -f job.yaml
job.batch/pi created
[root@nsg]/tmp/test# kubectl get jobs,pods
NAME COMPLETIONS DURATION AGE
job.batch/pi 1/1 8s 27s
NAME READY STATUS RESTARTS AGE
pod/pi-2k4b6 0/1 Completed 0 27s
# 等待20s后 立即刪除
[root@nsg]/tmp/test# kubectl get jobs,pods
No resources found in default namespace.
定時執行 Job
Linux 中有 cron 程序定時執行任務,Kubernetes 的 CronJob 也提供了類似的功能,可以定時執行 Job。CronJob 配置文件示例如下:cronjob.yaml:
apiVersion: batch/v1
kind: CronJob
metadata:
name: pi
spec:
schedule: "* * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: OnFailure
創建它,查看 cronjobs 、Pods 的狀態, 可以看到每隔一分鐘就會啟動一個 Job:
[root@nsg]/tmp/test# kubectl apply -f cronjob.yaml
cronjob.batch/pi created
[root@nsg]/tmp/test# kubectl get cronjobs,pods
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/pi * * * * * False 1 7s 2m36s
NAME READY STATUS RESTARTS AGE
pod/pi-28255870-cd4mx 0/1 Completed 0 2m7s
pod/pi-28255871-9tv6x 0/1 Completed 0 67s
pod/pi-28255872-nl99x 0/1 Completed 0 7s
使用 Job 的注意事項
在使用 Kubernetes Job 時,需要注意以下幾點:
- Job 對象適用于一次性任務或批處理作業,不適用于長時間運行的服務。
- 需要確保 Job Spec 中定義的容器可以正常運行,并有足夠的資源和權限執行指定的操作。
- 在設計 Job 時,應考慮 Pod 失敗和重試的情況,并設置合適的重試次數和間隔時間。
- 如果 Job 執行時間過長,需要設置合適的 Pod 生命周期以避免過度消耗資源。
- 在使用 Job 控制器時,應確保控制器的版本和 Kubernetes 版本兼容。在不同版本之間可能存在語法變更和行為差異。
更多特性
參考官網:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/job/