雲原生混部最後一道防線:節點水位線設計

語言: CN / TW / HK

簡介: 由於混部是一個複雜的技術及運維體系,包括 K8s 排程、OS 隔離、可觀測性等等各種技術。今天我們要關注的是混部在單機執行時的最後一道防線——單機水位線設計。

作者:南異

引言

在阿里集團,在離線混部技術從 2014 年開始,經歷了七年的雙十一檢驗,內部已經大規模落地推廣,每年為阿里集團節省數十億的資源成本,整體資源利用率達到 70% 左右,達到業界領先。這兩年,我們開始把集團內的混部技術通過產品化的方式輸出給業界,通過外掛化的方式無縫安裝在標準原生的k8s叢集上,配合混部管控和運維能力,提升叢集的資源利用率和產品的綜合使用者體驗。

由於混部是一個複雜的技術及運維體系,包括 K8s 排程、OS 隔離、可觀測性等等各種技術,之前的 2 篇文章:

歷經 7 年雙 11 實戰,阿里巴巴是如何定義雲原生混部排程優先順序及服務質量的?

如何在雲原生混部場景下利用資源配額高效分配叢集資源?

今天我們要關注的是混部在單機執行時的最後一道防線——單機水位線設計。

為什麼需要單機水位線

1.jpeg

如上圖所示,Pod 的執行時的三個生命週期階段,在經過配額檢查和排程後,終於,不同 Qos 等級的 Pod 執行在同一個節點上了,這個時候,高優和中優的 Pod 使用的是節點上的容器分配總量,而低優 Pod,則是基於高中優實際的資源用量,然後被排程器排程到節點上面去執行。從下圖可以看到,當一個節點上還有較多的空餘資源時,完全可以提供給低優資源使用,而當高/中優 Pod 實際資源用量高過一定的值之後,資源競爭非常激烈時,節點上再跑低優 Pod 只會導致高/中優 Pod 的服務質量受損,所以這個時候,我們將不再允許低優 Pod 在這個節點上執行。為了標識或者說判斷節點資源的競爭激烈程度,那麼非常順理成章的一個設計就是,看這個節點上的資源使用率是否過高。如果超過一定使用率,那麼我們就需要對低優 Pod 做相應的操作。這個判斷的臨界閾值,就是單機的水位線。

image.gif

2.jpeg

這裡另外能看到的一點是,水位線僅僅是為低優 Pod 所設定的,高/中優 Pod 並不會感知到水位線,他們可以自由地使用整機的所有資源,所有的系統行為都和沒有開啟混部是一樣的。

水位線的分級

對於一個資源趨向於飽和的節點來說,我們對於低優 Pod 可以有各種操作的手段,如果僅僅是簡單的殺掉低優 Pod 的話,整個混部系統也可以工作,這個動作我們稱為“驅逐”。

但如果在一定時間後,機器上的資源競爭又降低的話,那麼低優 Pod 被殺死並在別的機器上重新啟動,這裡會大大延長低優 Pod 的單個任務的執行時間,所以在設計單機水位線時,需要儘可能的讓低優 Pod 也要在可以允許的時間範圍內能夠“降級”執行。所以,我們有對低優 Pod 的第 2 種操作,就是降低對它的 CPU 供給量,這個操作我們稱為“壓制”。

同時,如果一個節點上的資源趨於飽和,另外還比較順理成章的系統行為就是不讓新的低優 Pod 被排程進來。

於是我們對於節點上低優 Pod 的行為就有 3 種:壓制、驅逐和禁止排程,由此就有三條水位線,同時,對於 CPU 這類的可壓縮資源和記憶體這類不可壓縮資源,行為還有區別。

注:可壓縮資源(例如 CPU 迴圈,disk I/O 頻寬)都是速率性的可以被回收的,對於一個 task 可以降低這些資源的量而不去殺掉 task;和不可壓縮資源(例如記憶體、硬碟空間)這些一般來說不殺掉 task 就沒法回收的。來自文章《在 Google 使用 Borg 進行大規模叢集的管理 5-6》- 6.2 效能隔離[1]

這些水位線總體列表如下:

3.png

這些水位線的合理配置值,應該是 驅逐>壓制>禁止排程。

不過在實際的混部生產中,我們一般會把禁止排程水位線和壓制水位線使用同一個配置值,來降低系統運維同學的理解成本,以及配置工作量。這樣合併後就會存在 CPU 的 2 條水位線,記憶體的一條水位線。

驅逐條件:基於滿足度的驅逐模式

4.png

image.gif這張圖展示了單機上實際的系統執行例子

  • 在 t1 時間,總資源利用率達到壓制水位線的時候,對低優先順序的任務進行壓制,保證整體資源利用率在壓制水位線之下,此時低優任務不會再被排程進來
  • 在 t3 時間,總資源利用率開始進一步上升,達到驅逐水位線時,會對低優任務進行刪除和驅逐的處理,保證高/中優的資源使用

一個容易考慮到的設計是,驅逐低優任務前去設定一個延遲時間,這樣可以讓低優 Pod 有更多的機會等到系統有足夠的資源,繼續執行,然而這個設計,會造成幾個問題:

  1. 記憶體的驅逐必須是實時的,因為節點上記憶體不足,會導致高/中優任務記憶體不足而 OOM
  2. 這個延遲時間並不好配置,配的短了沒有效果,配了長了反而會引起低優 Pod 長期“飢餓”而造成低優 Pod 執行時間更長
  3. 如果在一個節點上,有多個低優 Pod 都在執行,是否要驅逐所有的低優 Pod?是否可能儘量的少驅逐 Pod?

因此,我們發明了基於滿足度的低優 Pod 的 CPU 資源驅逐方式,定義了以下幾個概念:

  • 視窗期:獲取 CPU 利用率的時間視窗(例如 5 分鐘),在視窗時間的平均 CPU 利用率超過驅逐水位線,則開始驅逐,可以避免抖動
  • 低優 Pod 資源滿足率:= 低優 Pod 實際資源使用量/低優 Pod Request 資源量
  • 低優 Pod 滿足率下限:一個百分比值,低於這個值的認為低優 Pod 的資源供給不足

這樣,低優 Pod 的驅逐條件就變為了:

  1. 視窗期內:平均低優 Pod 資源滿足率 < 低優 Pod 滿足率下限
  2. 視窗期內:低優 Pod 平均 CPU 利用率接近 100%(如 90% 或者 80%)
  3. 當前時間:平均低優 Pod 資源滿足率 < 低優 Pod 滿足率下限
  4. 最近時間:BE CPU 利用率接近100%(如 90% 或者 80%)

而驅逐低優 Pod 的排序為:

  • 優先驅逐排程優先順序 Priority 低的 Pod(是的,即使是低優 Pod,我們還是可以按照數值來細分不同的排程優先順序)
  • 如果 2 個 Pod 排程優先順序一致,則計算驅逐哪一個 Pod 帶來的資源釋放更多,優先驅逐能釋放更多資源的

記憶體的驅逐方式和 CPU 基本類似,但沒有滿足率,到了驅逐水位線按照優先順序和記憶體大小來進行驅逐。

注:低優 Pod 的在別的節點上重建,還是依賴於低優 Pod 的管控系統(例如,離線計算的框架 Spark/Flink 等),這個重建過程往往涉及到臨時快取的檔案或者資料的遷移和一致性的校驗,這個重建操作並不適合在 K8s 層主動的去做操作,而是交給上層管控系統或者 operator 更加合適。

展望:是否有更好的設計?

在本文的開始,提到了衡量系統資源的競爭激烈程度,最簡單和直觀的就是看資源利用率。當然,在實際的大規模叢集執行過程中,我們也看到了資源利用率高和資源競爭激烈並不是完全的一一對應關係,甚至有些應用在 CPU 利用率非常高的情況下,依然穩定執行,而另外一些應用,在一個低的 CPU 利用情況下,就會非常的“卡”。

這就意味著如果我們有新的、更好的指標來衡量系統的利用率,那麼我們對相應的 Workload 就能有更“微操”的操作,在保證應用 SLO 的同時,提升叢集的資源利用率。

相關解決方案介紹

進入了 2022 年,混部在阿里內部已經成為了一個非常成熟的技術,為阿里每年節省數十億的成本,是阿里資料中心的基本能力。而阿里雲也把這些成熟的技術經過兩年的時間,沉澱成為混部產品,開始服務於各行各業。雲原生混部相關能力已經申請了多項獨立的智慧財產權。

在阿里雲的產品族裡面,我們會把混部的能力通過 ACK 敏捷版,以及 CNStack(CloudNative Stack)產品家族,對外進行透出,並結合龍蜥作業系統(OpenAnolis),形成完整的雲原生資料中心混部的一體化解決方案,輸出給我們的客戶。

參考文件:

[1]《在Google使用Borg進行大規模叢集的管理 5-6》:

https://my.oschina.net/HardySimpson/blog/517283

點選此處,立刻訪問雲原生混部整體解決方案 ACK 敏捷版!

原文連結:http://click.aliyun.com/m/1000349412/

本文為阿里雲原創內容,未經允許不得轉載。