K8s中的批處理任務模塊主要是由Job控制器完成,今天我們就來關注下其底層的關鍵設計,包括完成狀態、并行模式、并行策略等關鍵機制
1. 基礎概念
在聊k8s的任務模塊的實作的時候,我們先看一下傳統的任務系統的設計與實作,然后聊下基于k8s的基礎的概念
1.1 傳統的任務系統設計

傳統的任務系統設計主要可以分為master(任務分配/故障感知/負載均衡)、Worker(任務執行/任務監控/任務管理)、分布式協調(etcd等存盤元資料)、任務倉庫(存盤任務的實作比如類或者介面)等幾部分, 從大的部分又可以切分為兩個部分管控端(分布式協調/master/倉庫)、執行端(Worker),傳統的任務系統大概就是這樣
通常復雜的就是如何在master如何做任務的負載均衡、任務的快速完成、依賴等管控功能,其次就是如何在worker端實作一個牛x的引擎,可以支持各種不同任務的執行環境和型別的執行
1.2 基于Pod的任務載體

k8s中的最小單元調度是Pod,同樣的job控制器調度的最小單元也是Pod, Pod里面包含容器,以容器為載體k8s屏蔽了傳統worker模塊的任務執行環境與實作兩個部分,只需要添加一些配置資料,對應的Pod就可以完成對應的任務的執行
1.3 簡化的調度層
在k8s中Pod通常被定義為一個不穩定的單元,即k8s并不保證你的pod在被調度到某一臺機器后就會一直的穩定運行,直到這臺機器下線,這與傳統的系統都不太一樣,基于該特點,Job調度器的調度層其實也是一種面向于終態的設計,
大概就先介紹這些,接下來我們去分析k8s中job的核心實作機制
2. 核心實作
Job控制器的核心實作有幾個關鍵點:并行粒度、完成狀態、并行策略、并行模式、洗掉策略,記住這些關鍵點,我們來一一剖析
2.1 并行粒度
并行的粒度是指的針對同一任務可以同時有多少個并行的Pod即同時運行的Pod,Job控制器會根據用戶設定的并行粒度確定需要同時運行的Pod
2.2 完成狀態
在一些批處理調度的系統里面可能會通過資料分片后,等待所有分片的任務都完成后,來確定任務的完成狀態,但是在k8s中Job控制器是一個通用的實作, 而且調度層本身也并不關注調度任務的具體資料

所以在k8s中里面其實是通過Completion的和backoffLimit來完成狀態轉移的,即通過Completion來確定需要等待的Pod的完成的數量,而通過backoffLimit確定到底可以允許失敗重試的次數,確定重試多少次就認為任務失敗了
2.3 并行模式
在k8s的job控制器模式介紹中提到四種并發模式, 那實作上是不是真的有四種模式呢,答案是否定的,可以說k8s的job控制器根本也就不關注是那種模式,模式是應用層自己的設計,而job控制器只負責并行粒度、當前狀態、完成狀態
這里我們主要分析下Parallel JOb with a fix completion count和Parallel Job with a work queue的實作來聊聊Job控制器是如何實作的,兩者很大的一個區別就是后者不能設定Completions,即不需要設定需要等待多少個Pod完成,為什么一個引數的設定就可以實作兩者模式呢?

答案就是期望的完成數量不同,如果Completions不設定,則實際上Job控制器發現有任一一個Pod成功并且當前活躍的Pod的數量為0,則表示當前任務完成, 該模式主要適用于單次的批任務,即本次批任務的所有Pod任務都完成,通常也意味著本次批任務是有限的集合
而Completions設定為數量則意味著只需要完成指定數量的批任務,即任務可能類似于流處理模式,本次只期望完成一部分即可,即Completions設定數量的任務
2.4 并行策略
并行策略主要是指的如果我們指定的Parallelism的數量過大,為了避免單個任務同時創建大量的Job任務對集群帶來的影響則采用分批逐次遞增的策略,逐步完成并行所需要的Pod的更新
2.5 期望計數

期望計數是k8s中控制器常見的機制,即當控制器進行Pod操作完成后,會設定當前期望的Pod的增加或者洗掉的計數,通過期望計數的統計來確定當前是否需要繼續更新對應的pod, 期望的滿足主要來源于兩個地方:informer和當前控制流,informer通過監聽apiserver來感知事件,而當前控制流則主要是在操作Pod失敗的時候,直接更新期望,因為這些操作失敗的Pod并不會從后續的informer中感知到
2.6 洗掉策略
我們提到過期望計數來決定是否更新狀態,但這個并不保證一致性,很有可能因為事件的延遲導致控制器創建了大量的Pod此時就需要基于終態的繼續調整,即需要根據當前的數量來洗掉部分的Pod, 洗掉策略主要是包含六點:1)未分配優先 2)未運行優先 3)未就緒優先 4)運行時間最短優先 5)重啟次數多優先 6)創建時間較短優先
3. 總結

Job控制器的實作設計上還是很好玩的,主要是是面向常見的批處理場景,但本身并沒有考慮優先級、關系、效率、分片等功能,只是一個通用的基礎的任務調度的實作, 當前k8s中還有很多針對不同場景的專用任務調度實作,但基于k8s的任務系統設計本身就給我們降低了很多的復雜度,這也就是云原生帶來的好處,今天就到這里,謝謝大家
kubernetes學習筆記地址: https://www.yuque.com/baxiaoshi/tyado3
微信號:baxiaoshi2020
關注公告號閱讀更多原始碼分析文章
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/31205.html
標籤:其他


