上車了!一文盡覽Scheduling Framework 應用實踐

豆芽59發表於2021-01-27

Kubernetes 是目前最受歡迎的⾃動化容器管理平臺,它提供了靈活的宣告式容器編排、自動部署、資源排程等功能。Kube-Scheduler 作為 Kubernetes 的核心元件之一,主要負責整個叢集資源的排程功能,根據特定的排程演算法和策略,將 Pod 排程到最優的工作節點上面去,從而更加合理、充分地利用叢集資源。

但是隨著 Kubernetes 部署的任務型別越來越多,原生 Kube-Scheduler 已經不能應對多樣的排程需求:比如機器學習、深度學習訓練任務對於協同排程功能的需求;高效能運算作業,基因計算工作流對於一些動態資源 GPU、網路、儲存卷的動態資源繫結需求等。因此自定義 Kubernetes 排程器的需求愈發迫切,本文討論了擴充套件 Kubernetes 排程程式的各種方法,然後使用目前最佳的擴充套件方式 Scheduling Framework,演示如何擴充套件 Scheduler。

01 自定義排程器的方式

02 Scheduling Framework 解析

如下圖所示,排程框架提供了豐富的擴充套件點,在這幅圖中,Filter 相當於之前 Predicate 預選模組, Score 相當於 Priority 優選模組,每一個擴充套件點模組都提供了介面,我們可以實現擴充套件點定義的介面來實現自己的排程邏輯,並將實現的外掛註冊到擴充套件點。

Scheduling Framework 在執行排程流程時,當執行到擴充套件點時,會呼叫我們註冊的外掛,透過執行自定義外掛的策略,滿足排程需求。此外,一個外掛可以在多個擴充套件點註冊,用以執行更復雜或有狀態的任務。

Scheduling Framework 每次排程一個 Pod ,都分為排程週期和繫結週期兩部分來執行,排程週期為 Pod 選擇一個節點,繫結週期則呼叫 Apiserver,用選好的 Node,更新 Pod 的 spec.nodeName 欄位。排程週期和繫結週期統稱為 “Scheduling Context” (排程上下文)。排程週期是序列執行的,同一時間只能有一個 Pod 被排程,是執行緒安全的;而繫結週期因為需要訪問 Apiserver 的介面,耗時較長,為了提高排程的效率,需要非同步執行,即同一時間,可執行多個 bind 操作,是非執行緒安全的。

如果 Pod 被確定為不可排程或 存在內部錯誤,那麼排程週期或繫結週期將被中止。Pod 將返回佇列並等待下一次重試。如果一個繫結週期被終止,它將觸發 Reserve 外掛中的 UnReserve 方法。

Scheduling Cycle 的擴充套件點

QueueSort

用於給排程佇列排序,預設情況下,所有的 Pod 都會被放到一個佇列中,此擴充套件用於對 Pod 的待排程佇列進行排序,以決定先排程哪個 Pod,QueueSort 擴充套件本質上只需要實現一個方法  Less(Pod1, Pod2)  用於比較兩個 Pod 誰更優先獲得排程,同一時間點只能有一個 QueueSort 外掛生效。

PreFilter

用於對 Pod 的資訊進行預處理,或者檢查一些叢集或 Pod 必須滿足的前提條件,比如 Pod 是否包含指定的 annotations 或 labels,如果 PreFilter 返回了 error ,則排程過程終止。

Filter

用於排除那些不能執行該 Pod 的節點,對於每一個節點,排程器將按順序執行 Filter 擴充套件,如果任何一個 Filter 將節點標記為不可選,則餘下的 Filter 擴充套件將不會被執行。如果對預設排程器提供的預選規則不滿意,可以在配置中禁用預設排程器的預選演算法,在這個擴充套件點只執行自己自定義的過濾邏輯。Node 節點執行 Filter 策略是併發執行的,所以在同一排程週期中多次呼叫過濾器。

PostFilter

實現此擴充套件的外掛是在 Filter 階段之後被呼叫,僅當沒有為 Pod 找到可行的節點時才呼叫。如果有任何 PostFilter 外掛將節點標記為可排程節點,則後面的 PostFilter 外掛就不會被呼叫了。一個典型的 PostFilter 實現是搶佔,它試圖透過搶佔其他 Pod 來使 Pod 可排程。

PreScore

在預選後被呼叫,通常用來在 Score 之前進行一些資訊生成或者記錄日誌和監控資訊

Score

實現此擴充套件的外掛為已透過過濾階段的所有節點進行打分,排程器將針對每一個節點呼叫 Score 擴充套件。

NormalizeScore

NormalizeScore 階段,排程器將會把每個 Score 擴充套件對具體某個節點的評分結果和該擴充套件的權重合並起來,作為最終評分結果,評分結果是一個範圍內的整數。如果 Score 或 NormalizeScore 返回錯誤,則排程週期將中止。

Reserve

此擴充套件點為 Pod 預留的在要執行節點上的資源,目的是避免排程器在等待 Pod 與節點繫結的過程中排程新的 Pod 到節點上時,發生實際使用資源超出可用資源的情況。(因為繫結 Pod 到節點上是非同步發生的)。這是排程過程的最後一個步驟,Pod 進入 Reserved 狀態以後,要麼在繫結失敗時,觸發 Unreserve 擴充套件,要麼在繫結成功時,由 PostBind 擴充套件結束繫結過程。

Permit

Permit 擴充套件,發生在 Pod 使用 Reserve 外掛預留資源之後, Bind 擴充套件點 bind 之前,主要有三種策略,批准、拒絕、等待。

1)approve(批准):當所有的 Permit 擴充套件都批准了 Pod 與節點的繫結,排程器將繼續執行繫結過程

2)deny(拒絕):如果任何一個 Permit 擴充套件 deny 了 Pod 與節點的繫結,Pod 將被放回到待排程佇列,此時將觸發 Unreserve 擴充套件

3)wait(等待):如果一個 Permit 擴充套件返回了 wait,則 Pod 將保持在 Permit 階段,直到被其他擴充套件 approve,如果超時事件發生,wait 狀態變成 deny,Pod 將被放回到待排程佇列,此時將觸發 UnReserve 擴充套件

Binding Cycle 的擴充套件點

PreBind

擴充套件用於在 Pod 繫結之前執行某些邏輯。這個外掛引入的原因,是有一些資源,是在不在排程 Pod 時,立即確定可用的節點的資源,所以排程程式需要確保,這些資源已經成功繫結到選定的節點後,才能將 Pod 排程到此節點。例如,PreBind 擴充套件可以將一個基於網路的資料卷掛載到節點上,以Pod 可以使用。如果任何一個 PreBind 擴充套件返回錯誤,Pod 將被放回到待排程佇列,此時將觸發 Unreserve 擴充套件。

Bind

Bind 擴充套件會呼叫 apiserver 提供的介面,將 Pod 繫結到對應的節點上。

PostBind

PostBind 是一個資訊擴充套件點。成功繫結 Pod 後,將呼叫 PostBind 外掛,可用於清理關聯的資源。

UnReserve

是一個通知性質的擴充套件,如果為 Pod 預留了資源,Pod 又在被繫結過程中被拒絕繫結,則 Unreserve 擴充套件將被呼叫。Unreserve 擴充套件應該釋放已經為 Pod 預留的節點上的計算資源。在一個外掛中,Reserve 擴充套件和 UnReserve 擴充套件應該成對出現。

03 使用 Scheduling Framework 自定義 Scheduler

自定義外掛需要兩個步驟:

1)實現外掛的介面

2)註冊外掛並配置外掛

3.1 實現外掛的介面

這裡我們實現 QueueSort 擴充套件點,先看看 QueueSort 擴充套件點定義的介面:

// QueueSortPlugin is an interface that must be implemented by "QueueSort" plugins.// These plugins are used to sort pods in the scheduling queue. Only one queue sort// plugin may be enabled at a time.type QueueSortPlugin interface {    Plugin    // Less are used to sort pods in the scheduling queue.    Less(*QueuedPodInfo, *QueuedPodInfo) bool}

預設的排程器會優先排程優先順序較高的 Pod , 其具體實現的方式是使用 QueueSort 這個外掛,預設的實現,是對 Pod 的 Priority 值進行排序,但當優先順序相同時,再比較 Pod 的 timestamp ,  timestamp 是 Pod 加入 queue 的時間。我們現在想先根據 Pod 的 Priority 值進行排序,當 Priority 值相同,再根據 Pod 的 QoS 型別進行排序,最後再根據 Pod 的 timestamp 排序。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69990088/viewspace-2753924/,如需轉載,請註明出處,否則將追究法律責任。

相關文章