1、失敗任務
apiVersion: batch/v1
kind: Job
metadata:
name: bad
spec:
template:
metadata:
name: bad
spec:
restartPolicy: Never
containers:
- name: box
image: busybox
command: ["/bin/sh", "-c", "exit 1"]
如果你嘗試在你的cluster里面創建以上的Job,你可能會碰到如下的狀態。
$ kubectl describe jobs
Name: bad
Namespace: default
Image(s): busybox
Selector: controller-uid=18a6678e-11d1-11e7-8169-525400c83acf
Parallelism: 1
Completions: 1
Start Time: Sat, 25 Mar 2017 20:05:41 -0700
Labels: controller-uid=18a6678e-11d1-11e7-8169-525400c83acf
job-name=bad
Pods Statuses: 1 Running / 0 Succeeded / 24 Failed
No volumes.
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: bad-fws8g
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: bad-321pk
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: bad-2pxq1
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: bad-kl2tj
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: bad-wfw8q
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: bad-lz0hq
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: bad-0dck0
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: bad-0lm8k
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: bad-q6ctf
1m 1s 16 {job-controller } Normal SuccessfulCreate (events with common reason combined)
因為任務快速失敗。Kubernetes認為任務沒能成功啟動,嘗試創建新的容器以恢復這個失敗,導致的Cluster會在短時間創建大量的容器,這樣的結果可能會消耗大量的計算資源。
2、問題處理
apiVersion: batch/v1
kind: Job
metadata:
name: bad
spec:
# 指定失敗時可以重試5次
backoffLimit: 5
# 指定存活時長
activeDeadlineSeconds: 100
template:
metadata:
name: bad
spec:
restartPolicy: Never
containers:
- name: box
image: busybox
command: ["/bin/sh", "-c", "exit 1"]
在Spec中使用.spec.activeDeadlineSeconds來避免這個問題。這個參數定了等待多長時間重試失敗的Job。
其他的差不多,Job對象需要apiVersion、kind和metadata字段,同樣需要.spec:
- Pod Template:
.spec.template是.spec必要的字段,是創建Pod的模板,和pod中的模式一樣,除了它是嵌套的沒有apiVersion或kind,此外還需要Pod的字段,Job中的pod template必須指定合適的標簽和重啟策略,RestartPolicy只能設置為Never或OnFailure; - Pod Selector:
.spec.selector是可選參數,一般不需要指定; - Parallel Jobs:主要有3種類型的task合適作為Job運行:
- 非並行Job(Non-parallel):正常只有一個Pod啟動(除非Pod失敗),一旦pod成功終止,Job就完成了;
- 固定計數的並行Job:為
.spec.completions指定一個非0整數,一個Job代表多個task,在1到.spec.completions范圍內的每個值都有一個成功的pod時完成;
- 具有work queue的並行Job:不需要指定
.spec.completions(默認為.spec.parallelism),Pod之間自我協調或通過額外的Service決定在哪個Pod上運行,一個pod可以從work queue中獲取一批最多n個元素。每個Pod能夠獨立決定是否完成了對等的任務,因此整個Job完成。當Job中的任意一個Pod完成task成功結束,將不會再創建新的Pod,當最后一個Pod結束時,就意味着所有的Pod都停止了,這時Job完成。
注:
- 對於
non-parallelJob,可以不設置.spec.completions和.spec.parallelism參數(此時它們的默認值為1); - 對於
fixed completion countJob,需要設置對應的.spec.completions,此外也可以設置.spec.parallelism(不設置默認為1); - 對於
work queueJob,.spec.completions參數不能設置,.spec.parallelism對應設置為非負整數; .spec.parallelism表示並行度(默認為1),當指定為0時,Job將停止直到這個數值增加,但實際的並行度可能會和請求的不一樣。在固定計數的並行Job中,實際並行的Pod數量不會超過剩余數量,.spec.parallelism將會被忽略;在work queue的並行Job中在Job完成后將不會在啟動新的Pod,但允許剩余Pod執行完成;此外如果Controller創建Pod失敗可能會導實際的Pod比請求的少。
【Pod和Container失敗】
如果Pod失敗了且.spec.template.spec.restartPolicy = "OnFailure",Pod將會殘留在節點上,但container是會重新運行的,因此當本地重啟可能需要解決這樣的問題或者指定.spec.template.spec.restartPolicy = "Never"。對於失敗的策略,比如由於配置文件錯誤的原因在重試過指定次數后直接讓整個Job失敗,back-off限制值.spec.backoffLimit默認為6,和Job相關的失敗Pod會由Job Controller進行back-off(每次back-off的時間間隔會逐漸增大10s、20s、40s,封頂6min)。
【自動清理已完成的Job】
通常已完成的Job對象需要進行清理,否則會對API Server造成壓力,如果Job是由更高級別的controller管理(比如CronJobs),那Job將會基於指定的容量清理策略被CronJobs清理
3、Cronjob
Cron Job是基於時間進行調度的,CronJob對象就像一行crontab文件,它會在給定的時間定期(以cron格式編寫)地運行一個Job。一個Cron Job創建Job對象基於它的調度執行時間,當然也有可能0個或2個Job會被創建,這些目前都不是確定的,因此Job之間應該保證冪等性,startingDeadlineSeconds設置為大一點的值或者不設置讓其默認且concurrencyPolicy設置為Allow,Job應該至少運行一次。對於CronJob,CronJob Controller將會檢查從上一次調度到現在將會錯過多少調度,如果錯過超過了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,Controller從startingDeadlineSeconds開始計算直到現在(即之前的時間內,並不是上次調度到現在)。比如,如果startingDeadlineSeconds設置為200,控制器將會計算在剛剛過去的200s中錯失了多少Job。
CronJob是從它在調度時間內創建失敗進行計算的,比如,concurrencyPolicy設置為Forbid,CronJob將會嘗試調度,如果之前的調度仍在運行,那么它將被視為錯過。
