Job
容器按照持續運行的時間可分為兩類:服務類容器和工作類容器。
服務類容器通常持續提供服務,需要一直運行,比如 http server,daemon 等。
工作類容器則是一次性任務,比如批處理程序,完成后容器就退出。
Kubernetes 的 Deployment、ReplicaSet 和 DaemonSet 都用於管理服務類容器;
對於工作類容器,我們用 Job。
先看一個簡單的 Job 配置文件 myjob.yml:
apiVersion: batch/v1 kind: Job metadata: name: myjob spec: template: metadata: name: myjob spec: containers: - name: hello image: busybox command: ["echo", "hello k8s job! "] restartPolicy: Never
① batch/v1
是當前 Job 的 apiVersion
。kubectl api-versions查看可用apiVersion
② 指明當前資源的類型為 Job
。
③ restartPolicy
指定什么情況下需要重啟容器。對於 Job,只能設置為 Never
或者 OnFailure
。
對於其他 controller(比如 Deployment)可以設置為 Always
。
通過 kubectl apply -f myjob.yml
啟動 Job。並kubectl get job
查看 Job 的狀態:
daweij@master:~/stady01/nginx$ kubectl apply -f myjob.yml job "myjob" created daweij@master:~/stady01/nginx$ kubectl get job NAME DESIRED SUCCESSFUL AGE myjob 1 1 2m daweij@master:~/stady01/nginx$ kubectl get pod --show-all NAME READY STATUS RESTARTS AGE myjob-72j2r 0/1 Completed 0 3m
DESIRED
和 SUCCESSFUL
都為 1
,表示按照預期啟動了一個 Pod,並且已經成功執行。kubectl get pod
查看 Pod 的狀態:
因為 Pod 執行完畢后容器已經退出,需要用 --show-all
才能查看 Completed
狀態的 Pod。
kubectl logs
可以查看 Pod 的標准輸出:
daweij@master:~/stady01/nginx$ kubectl logs myjob-72j2r hello k8s job!
以上是 Pod 成功執行的情況。
如果 Pod 失敗了會怎么樣呢?
修改 myjob.yml,故意引入一個錯誤。
如果將 restartPolicy
設置為 OnFailure
會怎么樣?下面我們實踐一下,修改 myjob.yml 后重新啟動。
運行新的 Job 並查看狀態,當前 SUCCESSFUL
的 Pod 數量為 0
,查看 Pod 的狀態.
可以看到有多個 Pod,狀態均不正常。kubectl describe pod
查看某個 Pod 的啟動日志:
日志顯示沒有可執行程序,符合我們的預期。
為什么 kubectl get pod
會看到這么多個失敗的 Pod?
原因是:當第一個 Pod 啟動時,容器失敗退出,根據 restartPolicy: Never
,此失敗容器不會被重啟,但 Job DESIRED
的 Pod 是 1
,目前 SUCCESSFUL
為 0
,不滿足.
所以 Job controller 會啟動新的 Pod,直到 SUCCESSFUL
為 1
。
對於我們這個例子,SUCCESSFUL
永遠也到不了 1
,所以 Job controller 會一直創建新的 Pod。為了終止這個行為,只能刪除 Job。
如果將 restartPolicy
設置為 OnFailure
會怎么樣?下面我們實踐一下,修改 myjob.yml 后重新啟動。
Job 的 SUCCESSFUL
Pod 數量還是為 0
,看看 Pod 的情況。
這里只有一個 Pod,不過 RESTARTS
為 3
,而且不斷增加,說明 OnFailure
生效,容器失敗后會自動重啟。
有時,我們希望能同時運行多個 Pod,提高 Job 的執行效率。這個可以通過 parallelism
設置。
這里我們將並行的 Pod 數量設置為 2,實踐一下:
Job 一共啟動了兩個 Pod,而且 AGE
相同,可見是並行運行的。
我們還可以通過 completions
設置 Job 成功完成 Pod 的總數:
上面配置的含義是:每次運行兩個 Pod,直到總共有 6 個 Pod 成功完成。實踐一下:
DESIRED
和 SUCCESSFUL
均為 6
,符合預期。如果不指定 completions
和 parallelism
,默認值均為 1
。
上面的例子只是為了演示 Job 的並行特性,實際用途不大。
不過現實中確實存在很多需要並行處理的場景。
比如批處理程序,每個副本(Pod)都會從任務池中讀取任務並執行,副本越多,執行時間就越短,效率就越高。這種類似的場景都可以用 Job 來實現。
如何定時執行 Job。
Linux 中有 cron 程序定時執行任務,Kubernetes 的 CronJob 提供了類似的功能,可以定時執行 Job。CronJob 配置文件示例如下:
① batch/v2alpha1
是當前 CronJob 的 apiVersion
。
② 指明當前資源的類型為 CronJob
。
③ schedule
指定什么時候運行 Job,其格式與 Linux cron 一致。這里 */1 * * * *
的含義是每一分鍾啟動一次。
④ jobTemplate
定義 Job 的模板,格式與前面 Job 一致。
接下來通過 kubectl apply
創建 CronJob。
失敗了。這是因為 Kubernetes 默認沒有 enable CronJob 功能,需要在 kube-apiserver 中加入這個功能。方法很簡單,修改 kube-apiserver 的配置文件 /etc/kubernetes/manifests/kube-apiserver.yaml:
kube-apiserver 本身也是個 Pod,在啟動參數中加上 --runtime-config=batch/v2alpha1=true
即可。
然后重啟 kubelet 服務:
systemctl restart kubelet.service
kubelet 會重啟 kube-apiserver Pod。通過 kubectl api-versions
確認 kube-apiserver 現在已經支持 batch/v2alpha1
:
再次創建CronJob:
這次成功了。通過 kubectl get cronjob
查看 CronJob 的狀態:
等待幾分鍾,然后通過 kubectl get jobs
查看 Job 的執行情況:
可以看到每隔一分鍾就會啟動一個 Job。執行 kubectl logs
可查看某個 Job 的運行日志:
小結
運行容器化應用是 Kubernetes 最重要的核心功能。
為滿足不同的業務需要,Kubernetes 提供了多種 Controller,包括 Deployment、DaemonSet、Job、CronJob 等。