在之前的章節中我們提到的pod都是需要持續執行的pod。但有時候我們也會希望執行一個在處理完成後就結束的任務,不像ReplicationController、ReplicaSet以及DaemonSet執行的是持續的、不會結束的任務,而且它們管理的pod中的程序退出時就會重啟。但是對於一個可完成的任務來說,其程序結束後不應該再重啟。
什麼是JobKubernetes中的Job資源使我們能夠執行一個pod,並且該pod中的容器不會隨著其中的程序執行完成而重啟,一旦程序結束,pod就會被認為是Completed狀態。
當某個節點發生故障時,位於該節點上由Job管理的Pod就會被重新排程到另一個節點,就像ReplicaSet管理的pod一樣。當程序本身出問題時(當程序返回一個錯誤退出碼時),可以配置Job是否重啟容器。
下圖展示了一個由Job建立的pod在節點發生故障時是如何被重新排程到一個新節點上的。該圖還顯示了一個不受管控的pod,當節點故障時它不會被重新排程,以及一個受ReplicaSet管控的pod,節點故障時,它會被重新排程:
Job對於某些特殊任務來說很有用,這些任務能否正常結束至關重要。可以在一個不受管控的pod中執行這個任務並等待它結束,但是當節點出故障或者pod在執行任務的時候從節點上被逐出時,就需要手動建立這個任務。手動建立並不合理,特別是在任務需要幾個小時才能完成的情況下。
建立Job在建立Job之前,我們先構建一個新的映象。
下面我們基於busbox映象建立一個名為batch-job的容器映象並將其釋出到阿里雲映象倉庫,該映象了每隔兩分鐘呼叫一次sleep命令,Dockerfile內容如下:
FROM busyboxENTRYPOINT echo "$(date) Batch job starting"; sleep 120; echo "$(date) Finished succesfully"
映象的具體構建和釋出過程此處不再贅述。
製作併發布的映象名為:registry.cn-shanghai.aliyuncs.com/david-ns01/batch-job:1.0
建立Job的YAML定義檔案batch-job.yaml:
apiVersion: batch/v1kind: Jobmetadata: name: batch-jobspec: template: metadata: labels: app: batch-job spec: restartPolicy: OnFailure containers: - name: main image: registry.cn-shanghai.aliyuncs.com/david-ns01/batch-job:1.0
該檔案定義了一個型別為Job的資源,它會執行指定的batch-job映象,該映象呼叫一個執行120秒的程序,然後退出。
在pod定義資訊中的spec區域中,我們可以指定當執行在這個容器中的程序結束後Kubernetes應該採取的操作,透過pod的spec區域的restartPolicy屬性(預設為Always)可以達到這個目的。Job所管理的pod不能使用預設策略,因為設計Job的目的不是為了無限期地執行。因此我們需要明確地設定restartPolicy為OnFailure或者Never,這樣可以防止容器在完成任務時重新啟動。
執行如下命令建立Job:
kubectl create -f batch-job.
從上圖可以看到Job為我們自動建立並啟動了一個pod。
2分鐘過後再次執行:
kubectl get po
可以看到pod的狀態變為Completed。
執行kubectl get jobs檢視Job的狀態:
Job的COMPLETETION列由0/1變為1/1。
kubectl logs batch-job-fjjv5
kubectl delete job batch-job
在一個Job中執行多個pod例項我們可以配置Job建立多個pod例項,然後以並行或者序列的方式執行它們。可以在Job的Spec區段中設定completions和parallelism屬性達到這個目的。
以序列方式執行Job pod
如果需要Job執行多次,可以設定completions為期望pod執行的次數,例如定義如下一個YAML檔案:
apiVersion: batch/v1kind: Jobmetadata: name: multi-completion-batch-jobspec: completions: 5 template: metadata: labels: app: batch-job spec: restartPolicy: OnFailure containers: - name: main image: registry.cn-shanghai.aliyuncs.com/david-ns01/batch-job:1.0
基於該檔案建立的Job會以序列的方式前後執行5個pod。它最初建立一個pod,當pod的容器執行完成時,又會建立第二個pod,以此類推,直到五個pod都成功執行完成。如果某一個pod發生故障了,Job就會建立一個新的pod,因此Job建立的pod總數可能不止5個。
以並方式執行Job pod
與一個接一個的執行單個pod不同,我們還可以讓Job以並行的方式執行多個pod。透過Job Spec區段中的parallelism屬性,可以指定允許以並行的方式執行的pod數。如下面的YAML檔案所示:
vim multi-completion-parallel-batch-job.yaml
apiVersion: batch/v1kind: Jobmetadata: name: multi-completion-batch-jobspec: completions: 5 parallelism: 2 template: metadata: labels: app: batch-job spec: restartPolicy: OnFailure containers: - name: main image: registry.cn-shanghai.aliyuncs.com/david-ns01/batch-job:1.0
透過設定parallelism為2,Job會建立兩個pod然後以並行的方式執行它們。
執行:
kubectl create -f multi-completion-parallel-batch-job.yaml
一旦其中一個執行完成,Job就會建立並執行下一個Pod,直到5個pod成功執行完成
縮放Job
在舊版本中我們甚至可以在Job執行的過程中更改Job的parallelism屬性。這點與ReplicaSet和ReplicationController的縮放操作類似,可以透過kubectl scale命令完成:
kubectl scale job multi-completion-batch-job --replicas 3
但是在最新版本中kubectl scale job已經被廢棄掉了。
限制Job pod完成任務的時間
請思考如下問題:
1.Job需要等待一個pod多長時間完成任務?
2.如果pod卡住了並且根本無法完成任務或者不能足夠快地完成任務怎麼辦?
可以在pod spec區段透過設定activeDeadlineSeconds屬性來限制pod的時間。如果pod的執行時間超過了這個值,系統就會嘗試終止pod,並將Job標記為失敗。
在Job的定義檔案中,我們可以透過設定spec.backoffLimit屬性來配置Job在被標記為失敗之前可以重試的次數。該屬性值預設為6。
排程Job當建立Job資源後,Job就會立即執行對應的Pod。但是很多批處理任務需要在特定的時間執行或者以特定的時間間隔重複地執行。在Linux和類Unix作業系統中,這些任務通常被稱為cron任務。Kubernetes也支援這種任務。
在Kubernetes中可以透過建立CronJob資源來配置
cron任務。執行任務的排程資訊以cron格式指定,因此如果熟悉常規的cron任務的話,就能很快理解Kubernetes的CronJob了。
Kubernetes會根據配置在CronJob定義資訊中的Job模板來建立Job資源。當建立好Job時,就會根據Job的pod模板建立並啟動一個或者多個pod副本。
建立CronJob假設我們希望每隔15分鐘執行一次上面提到的批處理Job,可以建立一個CronJob資源:
apiVersion: batch/v1beta1kind: CronJobmetadata: name: batch-job-every-five-minutesspec: schedule: "0,15,30,45 * * * *" jobTemplate: spec: template: metadata: labels: app: periodic-batch-job spec: restartPolicy: OnFailure containers: - name: main image: registry.cn-shanghai.aliyuncs.com/david-ns01/batch-job:1.0
執行如下命令建立CronJob:
kubectl create -f cronjob.yaml
檢視建立的CronJob:
kubectl get cronjob
kubectl get jobs
kubectl get po
可以看到還未建立Job和Pod。
噹噹前時間處於某一個小時內的0分、15分、30分或者45分時,可以看到建立了CronJob、Job以及pod:
上面的Job在CronJob被建立後立即被建立。但是實際情況可能比較複雜,導致在CronJob被建立後,Job或者pod過一段時間之後才被建立。如果對Job的啟動時間不能太晚於排程時間有硬性的要求,可以透過在CronJob的spec中設定startingDeadlineSeconds來指定一個期限:
apiVersion: batch/v1beta1kind: CronJobmetadata: name: batch-job-every-fifteen-minutesspec: schedule: "0,15,30,45 * * * *" startingDeadlineSeconds: 15......
該檔案指定的Job按理應該在每個小時的0分、15分、30分、45分執行,例如應該在10:30:00執行,但是如果到了10:30:15由於某些原因還未執行,該Job就不會執行並被標記為Failed。
Cron表示式
Cron表示式由五部分組成: