1. 程式人生 > 其它 >Job/CronJob的理解(chrono《kubernetes入門實戰課》筆記整理)

Job/CronJob的理解(chrono《kubernetes入門實戰課》筆記整理)

【k8s所有的服務是否都可以整合在一個個pod裡?】

pod裡,已經可以直接排程其內部所有的容器,來一起提供一個整體的應用。為什麼k8s還有其他額外的物件來做k8s的其他服務呢,直接都整合在pod裡不是更好麼?這裡可以參考k8s對自己API物件的設計思路來理解:1)單一職責:每個物件盡力做好一件事兒,不貪大求全,小粒度更好管理和複用;2)組合優於整合:儘量讓物件只是在執行時再產生聯絡,而不是用硬編碼的方式直接固定物件之間的關係。

所以,pod本身既然已經是一個相對完善的物件,專門負責管理容器,那麼基於第一條設計思路,就不應該繼續給他擴充其它的功能了,同時,可基於上述第二條規則,在需要pod能力的時候,把pod作為一個成員,組合進去。這樣既有分工,又有協作,為k8s高效又靈活的運作奠定了基礎。

【為什麼要有Job/CronJob】

pod裡的業務,可以分為兩大類:

1、長時間執行的“線上業務”(如nginx、mysql等)。特點是永遠線上,是常駐業務;

2、短時間執行的“離線業務”(如busybox等)。特點是僅僅服務於內部使用者,比如日誌分析、視訊轉碼等,雖然計算量大,但只執行短短的一下就一定會退出。根據執行的方式,又可以分為臨時任務和定時任務。

對於長時間 執行的業務,其實沒有太多的排程策略。但是對於短時間執行的業務,排程策略就需要比較細緻了,需要基於執行超時、狀態檢查、失敗重試、獲取計算結果等來做區分。而這些由於具體業務的不同,導致的排程分別,讓pod來進行管理細化,就不太合適了,pod更多應該是基於應用需要,做好容器的編排執行。所以,這樣的功能,我們使用其他的物件來進行管理。上面說,離線業務裡面,又分了臨時和定時任務。這裡臨時任務就是API物件Job,定時任務,就是API物件CronJob。使用這兩個物件,就可以幫助Pod細化任務排程的工作了。

【如何使用YAML描述Job】

定義:YAML中,必要的格式,在YAML和pod的筆記中已經有了描述,這裡只記錄對於Job特別關注的部分。想不起的部分,可以用kubectl explain job來看欄位說明。但要生成YAML樣板不能用kubtctl run,因為run只能建立pod,建立pod以外的其他API物件,要用命令kubectl create,再加物件名。

  • apiversion:不是v1,是batch/v1;
  • kind:Job;
  • metadata:需要有name,lables做好標記。

示例:使用busybox建立一個“echo-job”,命令如下:

 這裡我第一次輸入錯了create,少寫了一個e,所以有了如下報錯,但這個報錯,根本理解不到是我寫錯名字了,寫到這裡大家一起注意。所以注意經常用tab鍵來補齊輸入,雖然有些單詞你覺得很簡單想直接輸入:

關於這個YAML的理解,還有幾個要點:

1、相對於Pod的“spec”欄位,Job的spec裡,多了一個 template 欄位,然後裡面又有一個“spec”。這是因為job物件裡,應用了組合模式,template是一個應用模板,裡面可以又嵌入一個pod,所以又會有一個spec,這樣,job就可以建立一個pod出來。那麼可能又會想,pod的yaml,完整的不應該是有apiversion,kind等麼,這裡只有一個spec呀。這是有因為這個pod是job管理的,不直接和apiserver聯絡,所以apiversion等頭欄位,就不用寫了,只要定義好關鍵的spec就可以了,job自己會理解這個pod怎麼用。結合下圖就很好理解了,這裡的 Pod 工作非常簡單,在 containers 裡寫好名字和映象,command 執行 /bin/echo,輸出“hello world”:

2、因為 Job 業務的特殊性,所以我們還要在 spec 裡多加一個欄位 restartPolicy,確定 Pod 執行失敗時的策略,OnFailure 是失敗原地重啟容器,而 Never 則是不重啟容器,讓 Job 去重新排程生成一個新的 Pod。

【如何在k8s裡操作Job】

1、建立一個job物件:

 2、檢視job和pod的狀態。建立之後 Kubernetes 就會從 YAML 的模板定義中提取 Pod,在 Job 的控制下執行 Pod,你可以用 kubectl get job、kubectl get pod 來分別檢視 Job 和 Pod 的狀態。因為 Pod 被 Job 管理,它就不會反覆重啟報錯了,而是會顯示為 Completed 表示任務完成,而 Job 裡也會列出執行成功的作業數量,這裡只有一個作業,所以就是 1/1:

另外,Pod 被自動關聯了一個名字,用的是 Job 的名字(echo-job)再加上一個隨機字串(lln8x),這是 Job 管理時,直接幫忙給pod起的名字,這樣我們就可以使用命令 kubectl logs 來獲取 Pod 的執行結果:

【Job裡如何靈活排程Pod】

通過YAML描述物件的框架,增加了很多的靈活性。如下 4 個欄位是離線作業中常用的幾個,它們並不在 template 欄位下,而是在 spec 欄位下,所以它們是屬於 Job 級別的,用來控制模板裡的 Pod 物件:

  • activeDeadlineSeconds:設定 Pod 執行的超時時間;
  • backoffLimit:設定 Pod 的失敗重試次數;
  • completions:Job 完成需要執行多少個 Pod,預設是 1 個;
  • parallelism:它與 completions 相關,表示允許併發執行的 Pod 數量,避免過多佔用資源。

 示例:如下YAML描述了一個job物件,名字叫“sleep-job”,它隨機睡眠一段時間再退出,模擬執行時間較長的作業(比如 MapReduce)。Job 的引數設定成 15 秒超時,最多重試 2 次,總共需要執行完 4 個 Pod,但同一時刻最多併發 2 個 Pod:

使用kubectl apply 建立job後,用get pod -w來實時觀察pod狀態,看到pod不斷被排隊、建立、執行的過程:

 等到 4 個 Pod 都completed,用 kubectl get 來看看 Job 和 Pod 的狀態。就會看到 Job 的完成數量如同我們預期的是 4,而 4 個 Pod 也都是完成狀態:

 “宣告式”的 Job 物件讓離線業務的描述變得非常直觀,簡單的幾個欄位就可以很好地控制作業的並行度和完成數量,不需要我們去人工監控干預,Kubernetes 把這些都自動化實現了。

【如何使用YAML描述CronJob】

“臨時任務”使用 Job 物件,“定時任務”使用 CronJob 物件描述。這一節可以類比job的部分來理解。

create的時候,有幾個要點要注意:

1、因為 CronJob 的名字有點長,所以 Kubernetes 提供了簡寫 cj,這個簡寫也可以使用命令 kubectl api-resources 看到;

2、CronJob 需要定時執行,所以我們在命令列裡還需要指定引數 --schedule:

 關於這個YAML,有幾個點要注意

1、觀察spec有三個,這個套娃結構,可以參考下面的截圖:

1)第一個 spec: 是 CronJob 自己的物件規格宣告;

2)第二個 spec: 從屬於“jobTemplate”,它定義了一個 Job 物件;

3)第三個 spec: 從屬於“template”,它定義了 Job 裡執行的 Pod。

2、CronJob 還有一個新欄位就是“schedule”,用來定義任務週期執行的規則。它使用的是標準的 Cron 語法,指定分鐘、小時、天、月、周,和 Linux 上的 crontab 是一樣的。像在這裡我就指定每分鐘執行一次,格式具體的含義你可以課後參考 Kubernetes 官網文件。

【如何在k8s裡操作CronJob】

CronJob 和 Job 的用法幾乎是一樣的,使用 kubectl apply 建立 CronJob,使用 kubectl get cj、kubectl get pod 來檢視狀態。