k8s集群Job負載 支援多個 Pod 可靠的並發執行,如何權衡利弊選擇適合的並行計算模式?
k8s的Job負載 支援多個 Pod 可靠的並發執行,如何權衡利弊選擇適合的並行計算模式?
簡單聊聊你對工作負載Job的理解?
Job 支援多個 Pod 可靠的並發執行,如何權衡利弊選擇適合的並行計算模式?
Job控制並行了解嗎?為什麼線上實際並行性可能比並行性請求略大或略小?
囧么肥事-胡說八道
簡單聊聊你對工作負載Job的理解?
在說工作負載Job執行原理之前,先了解下為什麼會需要Job負載?
對於ReplicaSet
、ReplicationController
等持久性負載來說,它們的職責是讓Pod保存預期的副本數量,穩定持久運行。
除非主動去更改模板,進行擴縮操作,否則這些Pod一直持久運行,並且運行的是持久性任務,比如Nginx,MySQL
等。
咦?持久任務,那麼萬事萬物有相對面,太極分陰陽,同樣,任務除了持久任務外,也有非持久任務。
身邊哪些是非持久任務呢?
我們在日常的工作中經常都會遇到一些需要進行批量數據處理和分析、或者是根據時間調度的需求,這些屬於短期性質的任務。不需要持久運行,僅執行一次就結束。例如進行資料庫跨庫同步,熱點數據統計分析等。也可以在特定時間調度單個任務,例如你想調度低活躍周期的任務。
這些執行完成就結束,完成了我們設定的某個目標就可以終止的,我們劃分為非持久任務。
好了,既然知道了任務劃分,而且k8s中ReplicaSet
、ReplicationController
等持久性負載是保證Pod穩定持久運行,那麼對立的,Job負載的職責就是保證非持久任務在生命周期內達成使命後體面終止。
需要Job負載,其實就是對持久性負載的補充。
簡單來說:「Pod,你去完成你的任務,完成之後我給你個體面的結束」。
曇花一現這個成語形容Job負載管理的Pod非常合適。曇花的目標是綻放,綻放完畢後立刻凋零。Job Pod 完成任務,終結,剛剛好😂。
接下來說說Job負載工作原理
Job 負載會創建一個或者多個 Pods,執行目標任務,在節點硬體失效或者重啟情況下將繼續重試 Pods 的執行,直到指定數量的 Pods 成功終止。
隨著 Pods 成功結束,Job 跟蹤記錄成功完成的 Pods 個數。 當數量達到指定的成功個數閾值時,任務(即 Job)結束。
刪除 Job 的操作會清除所創建的全部 Pods。
掛起 Job 的操作會刪除 Job 的所有活躍 Pod,直到 Job 被再次恢復執行。
Job 支援多個 Pod 可靠的並發執行,如何權衡利弊選擇適合的並行計算模式?
並行計算的模式有好多種,每種都有自己的強項和弱點,如何權衡選擇?
講個小故事,你是團隊組長,手底下有三個得力助手,囧囧,大肥,阿三。
某天,有個重要的項目需要派遣一位助手去洽談,你需要從中選擇一位,他們三個各有優缺點,你需要權衡利弊選擇一位。
囧囧,優點:工作負責,技能純熟,技術型人才,缺點,內向
大肥,優點:工作久,經驗豐富,為人圓滑,經驗型人才,缺點:太傲嬌
阿三,優點:社交能力強,能說會道,社交天花板型人才,缺點:技能相對差些
如果你作為組長,這次是跟客戶洽談合作事宜,你會派遣哪位小可愛呢?😁😁😁
好了,說完小故事,接下來話題回到Job負載。
Kubernetes Job 可以用來支援 Pod 的並發執行,但是呢?需要注意的是,Job 對象並非設計為支援需要緊密相互通訊的Pod的並發執行,例如科學計算。
Job 對象支援並發處理一系列相互獨立但是又相互關聯的工作任務,例如:文件轉碼,發送郵件,渲染影片幀等
延伸:Job有三種執行方式,能簡單說說是什麼嗎?
第一種:非並行Job
特點😈
通常只啟動一個 Pod,除非該 Pod 失敗,會啟動替代副本,當 Pod 成功終止時,立即視 Job 為完成狀態。
簡單理解非並行Job,Job啟動後,只運行一個Pod,Pod成功運行結束後整個Job也就立刻結束
可以不設置 spec.completions
和 spec.parallelism
。 這兩個屬性都不設置時,均取默認值 1。
第二種:具有確定完成計數的並行Job
特點😈
Job 用來代表整個任務,當成功的 Pod 個數達到 .spec.completions
時,Job 被視為完成
對於 確定完成計數 類型的 Job,應該設置 .spec.completions
為所需要的完成個數,.spec.completions
欄位設置為非 0 的正數值, 你可以設置 .spec.parallelism
,也可以不設置,其默認值為 1。
第三種:帶工作隊列的並行Job
特點😈
多個 Pod 之間必須相互協調,或者藉助外部服務確定每個 Pod 要處理哪個工作條目
對於一個工作隊列 Job,不設置 spec.completions
,默認值為 .spec.parallelism
,但要將.spec.parallelism
設置為一個非負整數。
例如,任一 Pod 都可以從工作隊列中取走最多 N 個工作條目
每個 Pod 都可以獨立確定其它 Pod 是否已完成,進而確定 Job 是否完成
當感知到 Job 中任何一個Pod成功終止,Job負載不再創建新Pod
一旦至少 1 個 Pod 成功完成,並且所有 Pod 都已終止,即可宣告 Job 成功完成
一旦任何 Pod 成功退出,任何其它 Pod 都不應再對此任務執行任何操作或生成任何輸出,所有 Pod 都應啟動退出過程
了解完Job常規執行方式,下面回歸正題,如何權衡利弊選擇適合的並行計算模式?
先看看常見並行模式方案
第一種模式,從Job負載的角度對比考慮
單對單
每個工作任務分配一個Job負載
單對多
一個Job負載負責所有工作任務
對比結果:
單對單,每個工作任務一個 Job 對象,可以專註任務,但是會給用戶帶來一些額外的負擔,系統需要管理大量的 Job 對象;
單對多,每個工作任務一個 Job 對象,更適合處理大量工作任務的場景,節約開銷;
第二種模式,從Pod數量對比考慮
單對單
創建與工作任務相等的Pod
單對多
每個Pod可以處理多個工作任務
對比結果
單對單,Pod的數量與工作任務的數量相等,通常不需要對現有程式碼和容器做較大改動;
單對多,每個Pod可以處理多個工作任務,更適合處理大量工作任務的場景,節約開銷;
第三種模式,結合隊列服務
需要運行一個隊列服務
需要對已有的程式或者容器做修改,以便其可以配合隊列工作
如果是一個已有的程式,改造時可能存在難度
與之比較,其他方案在修改現有容器化應用以適應需求方面可能更容易一些
總結:通過三種模式的簡單對比,首先在分配Job個數的時候,如果考慮到任務量較小,而且需要專註於每個任務的進行,那麼選擇單Job,如果任務量較多,考慮節約資源的情況下,選擇使用一個Job來處理大量任務。從Pod層次考慮,則要多分析一下現有應用的程式碼改動成本和容器的改造成本,如果改動較大,任務數量還能接收的情況下,那麼建議選擇單對單,為每個任務分配一個Pod即可,任務執行完畢資源回收。但是如果任務量巨大,在短期要求完成,資源儲備量有限的情況下,建議單對多,每個Pod處理多個任務。
至於結合隊列服務,通常對現有程式的改動量較大,而且隊列消費分配上需要根據實際情況進行佔比考慮,是否存在順序消費問題,是否存在一致性問題等等,非特殊業務需要,建議不輕易考慮,成本較高(時間,工作量,改造難度,資源分配等等綜合都較高)。
Job控制並行了解嗎?為什麼線上實際並行性可能比並行性請求略大或略小?
Job並行性:指定是同一時刻處於運行狀態,處理任務的 Pods 個數。
並行性請求(.spec.parallelism
)可以設置為任何非負整數。
如果未設置,則默認為 1。
如果設置為 0,則 Job 相當於啟動之後便被暫停,直到設置>0
實際並行性(在任意時刻運行狀態的 Pods 個數)可能比並行性請求略大或略小, 原因如下:
- 對於確定完成計數 Job,實際上並行執行的 Pods 個數不會超出剩餘未完成的任務數。
- 對於 工作隊列 Job,有任何 Job 成功結束之後,不會再有新的 Pod 啟動。 不過,剩下的 Pods 會繼續執行完畢。
- Job 控制器沒有來得及作出響應, Pods 個數可能比請求的數目大,也可能小。
- Job 控制器因為任何原因(例如,缺少
ResourceQuota
或者沒有許可權)無法創建 Pods。 - Job 控制器可能會因為之前同 一 Job 中 Pod 失效次數過多而壓制新 Pod 的創建。
- 當 Pod 處於體面終止進程中,需要一定時間才能停止。
Kubernetes 推薦學習書
Kubernetes權威指南PDF
鏈接://pan.baidu.com/s/11huLHJkCeIPZqSyLEoUEmQ 提取碼:sa88
k8s系列所有問題更新記錄:[GitHub](