云原生混部最后一道防線:節(jié)點(diǎn)水位線設(shè)計(jì)
?1.?引言
在阿里集團(tuán),在離線混部技術(shù)從 2014 年開(kāi)始,經(jīng)歷了七年的雙十一檢驗(yàn),內(nèi)部已經(jīng)大規(guī)模落地推廣,每年為阿里集團(tuán)節(jié)省數(shù)十億的資源成本,整體資源利用率達(dá)到 70% 左右,達(dá)到業(yè)界領(lǐng)先。這兩年,我們開(kāi)始把集團(tuán)內(nèi)的混部技術(shù)通過(guò)產(chǎn)品化的方式輸出給業(yè)界,通過(guò)插件化的方式無(wú)縫安裝在標(biāo)準(zhǔn)原生的k8s集群上,配合混部管控和運(yùn)維能力,提升集群的資源利用率和產(chǎn)品的綜合用戶體驗(yàn)。
由于混部是一個(gè)復(fù)雜的技術(shù)及運(yùn)維體系,包括 K8s 調(diào)度、OS 隔離、可觀測(cè)性等等各種技術(shù),之前的 2 篇文章:歷經(jīng) 7 年雙 11 實(shí)戰(zhàn),阿里巴巴是如何定義云原生混部調(diào)度優(yōu)先級(jí)及服務(wù)質(zhì)量的?如何在云原生混部場(chǎng)景下利用資源配額高效分配集群資源?今天我們要關(guān)注的是混部在單機(jī)運(yùn)行時(shí)的最后一道防線——單機(jī)水位線設(shè)計(jì)。
2.?為什么需要單機(jī)水位線
如上圖所示,Pod 的運(yùn)行時(shí)的三個(gè)生命周期階段,在經(jīng)過(guò)配額檢查和調(diào)度后,終于,不同 Qos 等級(jí)的 Pod 運(yùn)行在同一個(gè)節(jié)點(diǎn)上了,這個(gè)時(shí)候,高優(yōu)和中優(yōu)的 Pod 使用的是節(jié)點(diǎn)上的容器分配總量,而低優(yōu) Pod,則是基于高中優(yōu)實(shí)際的資源用量,然后被調(diào)度器調(diào)度到節(jié)點(diǎn)上面去運(yùn)行。從下圖可以看到,當(dāng)一個(gè)節(jié)點(diǎn)上還有較多的空余資源時(shí),完全可以提供給低優(yōu)資源使用,而當(dāng)高/中優(yōu) Pod 實(shí)際資源用量高過(guò)一定的值之后,資源競(jìng)爭(zhēng)非常激烈時(shí),節(jié)點(diǎn)上再跑低優(yōu) Pod 只會(huì)導(dǎo)致高/中優(yōu) Pod 的服務(wù)質(zhì)量受損,所以這個(gè)時(shí)候,我們將不再允許低優(yōu) Pod 在這個(gè)節(jié)點(diǎn)上運(yùn)行。為了標(biāo)識(shí)或者說(shuō)判斷節(jié)點(diǎn)資源的競(jìng)爭(zhēng)激烈程度,那么非常順理成章的一個(gè)設(shè)計(jì)就是,看這個(gè)節(jié)點(diǎn)上的資源使用率是否過(guò)高。如果超過(guò)一定使用率,那么我們就需要對(duì)低優(yōu) Pod 做相應(yīng)的操作。這個(gè)判斷的臨界閾值,就是單機(jī)的水位線。
這里另外能看到的一點(diǎn)是,水位線僅僅是為低優(yōu) Pod 所設(shè)置的,高/中優(yōu) Pod 并不會(huì)感知到水位線,他們可以自由地使用整機(jī)的所有資源,所有的系統(tǒng)行為都和沒(méi)有打開(kāi)混部是一樣的。
3?.水位線的分級(jí)
對(duì)于一個(gè)資源趨向于飽和的節(jié)點(diǎn)來(lái)說(shuō),我們對(duì)于低優(yōu) Pod 可以有各種操作的手段,如果僅僅是簡(jiǎn)單的殺掉低優(yōu) Pod 的話,整個(gè)混部系統(tǒng)也可以工作,這個(gè)動(dòng)作我們稱為“驅(qū)逐”。但如果在一定時(shí)間后,機(jī)器上的資源競(jìng)爭(zhēng)又降低的話,那么低優(yōu) Pod 被殺死并在別的機(jī)器上重新啟動(dòng),這里會(huì)大大延長(zhǎng)低優(yōu) Pod 的單個(gè)任務(wù)的執(zhí)行時(shí)間,所以在設(shè)計(jì)單機(jī)水位線時(shí),需要盡可能的讓低優(yōu) Pod 也要在可以允許的時(shí)間范圍內(nèi)能夠“降級(jí)”運(yùn)行。所以,我們有對(duì)低優(yōu) Pod 的第 2 種操作,就是降低對(duì)它的 CPU 供給量,這個(gè)操作我們稱為“壓制”。同時(shí),如果一個(gè)節(jié)點(diǎn)上的資源趨于飽和,另外還比較順理成章的系統(tǒng)行為就是不讓新的低優(yōu) Pod 被調(diào)度進(jìn)來(lái)。
于是我們對(duì)于節(jié)點(diǎn)上低優(yōu) Pod 的行為就有 3 種:壓制、驅(qū)逐和禁止調(diào)度,由此就有三條水位線,同時(shí),對(duì)于 CPU 這類的可壓縮資源和內(nèi)存這類不可壓縮資源,行為還有區(qū)別。
注:可壓縮資源(例如 CPU 循環(huán),disk I/O 帶寬)都是速率性的可以被回收的,對(duì)于一個(gè) task 可以降低這些資源的量而不去殺掉 task;和不可壓縮資源(例如內(nèi)存、硬盤(pán)空間)這些一般來(lái)說(shuō)不殺掉 task 就沒(méi)法回收的。來(lái)自文章《在 Google 使用 Borg 進(jìn)行大規(guī)模集群的管理 5-6》- 6.2 性能隔離[1]
這些水位線總體列表如下:
水位線 | 系統(tǒng)行為 | CPU | 內(nèi)存 |
禁止調(diào)度水位線 | 不讓新的低優(yōu) Pod 被調(diào)度到這個(gè)節(jié)點(diǎn)上 | 有 | 有 |
壓制水位線 | 壓制低優(yōu) Pod 的資源用量 | 有 | 無(wú) |
驅(qū)逐水位線 | 在這個(gè)節(jié)點(diǎn)上殺死低優(yōu) Pod,讓上層應(yīng)用重新拉起新 Pod 進(jìn)入重調(diào)度流程,看是否能運(yùn)行在別的節(jié)點(diǎn)上 | 有 | 有 |
這些水位線的合理配置值,應(yīng)該是 驅(qū)逐>壓制>禁止調(diào)度。不過(guò)在實(shí)際的混部生產(chǎn)中,我們一般會(huì)把禁止調(diào)度水位線和壓制水位線使用同一個(gè)配置值,來(lái)降低系統(tǒng)運(yùn)維同學(xué)的理解成本,以及配置工作量。這樣合并后就會(huì)存在 CPU 的 2 條水位線,內(nèi)存的一條水位線。
4?.驅(qū)逐條件:基于滿足度的驅(qū)逐模式
這張圖展示了單機(jī)上實(shí)際的系統(tǒng)運(yùn)行例子:
- 在 t1 時(shí)間,總資源利用率達(dá)到壓制水位線的時(shí)候,對(duì)低優(yōu)先級(jí)的任務(wù)進(jìn)行壓制,保證整體資源利用率在壓制水位線之下,此時(shí)低優(yōu)任務(wù)不會(huì)再被調(diào)度進(jìn)來(lái)
- 在 t3 時(shí)間,總資源利用率開(kāi)始進(jìn)一步上升,達(dá)到驅(qū)逐水位線時(shí),會(huì)對(duì)低優(yōu)任務(wù)進(jìn)行刪除和驅(qū)逐的處理,保證高/中優(yōu)的資源使用
一個(gè)容易考慮到的設(shè)計(jì)是,驅(qū)逐低優(yōu)任務(wù)前去設(shè)定一個(gè)延遲時(shí)間,這樣可以讓低優(yōu) Pod 有更多的機(jī)會(huì)等到系統(tǒng)有足夠的資源,繼續(xù)運(yùn)行,然而這個(gè)設(shè)計(jì),會(huì)造成幾個(gè)問(wèn)題:
- 內(nèi)存的驅(qū)逐必須是實(shí)時(shí)的,因?yàn)楣?jié)點(diǎn)上內(nèi)存不足,會(huì)導(dǎo)致高/中優(yōu)任務(wù)內(nèi)存不足而 OOM
- 這個(gè)延遲時(shí)間并不好配置,配的短了沒(méi)有效果,配了長(zhǎng)了反而會(huì)引起低優(yōu) Pod 長(zhǎng)期“饑餓”而造成低優(yōu) Pod 運(yùn)行時(shí)間更長(zhǎng)
- 如果在一個(gè)節(jié)點(diǎn)上,有多個(gè)低優(yōu) Pod 都在運(yùn)行,是否要驅(qū)逐所有的低優(yōu) Pod?是否可能盡量的少驅(qū)逐 Pod?
因此,我們發(fā)明了基于滿足度的低優(yōu) Pod 的 CPU 資源驅(qū)逐方式,定義了以下幾個(gè)概念:
- 窗口期:獲取 CPU 利用率的時(shí)間窗口(例如 5 分鐘),在窗口時(shí)間的平均 CPU 利用率超過(guò)驅(qū)逐水位線,則開(kāi)始驅(qū)逐,可以避免抖動(dòng)
- 低優(yōu) Pod 資源滿足率:= 低優(yōu) Pod 實(shí)際資源使用量/低優(yōu) Pod Request 資源量
- 低優(yōu) Pod 滿足率下限:一個(gè)百分比值,低于這個(gè)值的認(rèn)為低優(yōu) Pod 的資源供給不足
這樣,低優(yōu) Pod 的驅(qū)逐條件就變?yōu)榱耍?/p>
- 窗口期內(nèi):平均低優(yōu) Pod 資源滿足率 < 低優(yōu) Pod 滿足率下限
- 窗口期內(nèi):低優(yōu) Pod 平均 CPU 利用率接近 100%(如 90% 或者 80%)
- 當(dāng)前時(shí)間:平均低優(yōu) Pod 資源滿足率 < 低優(yōu) Pod 滿足率下限
- 最近時(shí)間:BE CPU 利用率接近100%(如 90% 或者 80%)
而驅(qū)逐低優(yōu) Pod 的排序?yàn)椋?/p>
- 優(yōu)先驅(qū)逐調(diào)度優(yōu)先級(jí) Priority 低的 Pod(是的,即使是低優(yōu) Pod,我們還是可以按照數(shù)值來(lái)細(xì)分不同的調(diào)度優(yōu)先級(jí))
- 如果 2 個(gè) Pod 調(diào)度優(yōu)先級(jí)一致,則計(jì)算驅(qū)逐哪一個(gè) Pod 帶來(lái)的資源釋放更多,優(yōu)先驅(qū)逐能釋放更多資源的
內(nèi)存的驅(qū)逐方式和 CPU 基本類似,但沒(méi)有滿足率,到了驅(qū)逐水位線按照優(yōu)先級(jí)和內(nèi)存大小來(lái)進(jìn)行驅(qū)逐。
注:低優(yōu) Pod 的在別的節(jié)點(diǎn)上重建,還是依賴于低優(yōu) Pod 的管控系統(tǒng)(例如,離線計(jì)算的框架 Spark/Flink 等),這個(gè)重建過(guò)程往往涉及到臨時(shí)緩存的文件或者數(shù)據(jù)的遷移和一致性的校驗(yàn),這個(gè)重建操作并不適合在 K8s 層主動(dòng)的去做操作,而是交給上層管控系統(tǒng)或者 operator 更加合適。
5.?展望:是否有更好的設(shè)計(jì)?
在本文的開(kāi)始,提到了衡量系統(tǒng)資源的競(jìng)爭(zhēng)激烈程度,最簡(jiǎn)單和直觀的就是看資源利用率。當(dāng)然,在實(shí)際的大規(guī)模集群運(yùn)行過(guò)程中,我們也看到了資源利用率高和資源競(jìng)爭(zhēng)激烈并不是完全的一一對(duì)應(yīng)關(guān)系,甚至有些應(yīng)用在 CPU 利用率非常高的情況下,依然穩(wěn)定運(yùn)行,而另外一些應(yīng)用,在一個(gè)低的 CPU 利用情況下,就會(huì)非常的“卡”。這就意味著如果我們有新的、更好的指標(biāo)來(lái)衡量系統(tǒng)的利用率,那么我們對(duì)相應(yīng)的 Workload 就能有更“微操”的操作,在保證應(yīng)用 SLO 的同時(shí),提升集群的資源利用率。
6?.相關(guān)解決方案介紹
進(jìn)入了 2022 年,混部在阿里內(nèi)部已經(jīng)成為了一個(gè)非常成熟的技術(shù),為阿里每年節(jié)省數(shù)十億的成本,是阿里數(shù)據(jù)中心的基本能力。而阿里云也把這些成熟的技術(shù)經(jīng)過(guò)兩年的時(shí)間,沉淀成為混部產(chǎn)品,開(kāi)始服務(wù)于各行各業(yè)。云原生混部相關(guān)能力已經(jīng)申請(qǐng)了多項(xiàng)獨(dú)立的知識(shí)產(chǎn)權(quán)。
在阿里云的產(chǎn)品族里面,我們會(huì)把混部的能力通過(guò) ACK 敏捷版,以及 CNStack(CloudNative Stack)產(chǎn)品家族,對(duì)外進(jìn)行透出,并結(jié)合龍蜥操作系統(tǒng)(OpenAnolis),形成完整的云原生數(shù)據(jù)中心混部的一體化解決方案,輸出給我們的客戶。
參考文檔:
[1]《在Google使用Borg進(jìn)行大規(guī)模集群的管理 5-6》:https://my.oschina.net/HardySimpson/blog/517283?