工作原理
在(zai)Kubernetes中(zhong),節點(dian)自動伸縮(suo)的(de)(de)工作原理(li)與傳統(tong)意義上基于使用(yong)率(lv)閾(yu)值的(de)(de)模(mo)型有所差(cha)別,這也是(shi)很多(duo)開發者在(zai)從傳統(tong)的(de)(de)IDC或者其他編排系統(tong)遷(qian)移到Kubernetes后最難理(li)解的(de)(de)地方。
傳統的(de)(de)彈(dan)性伸縮模型(xing)是基于使(shi)用(yong)率(lv)的(de)(de),例如(ru):一個集群(qun)中有(you)3個節點(dian),當集群(qun)中的(de)(de)節點(dian)CPU、內存使(shi)用(yong)率(lv)超(chao)過特定的(de)(de)閾值時,此(ci)時彈(dan)出新的(de)(de)節點(dian)。但當深(shen)入思考(kao)時會發現(xian)以(yi)下幾個問題:
閾值(zhi)是如何選(xuan)擇與判斷的?
在(zai)一個集(ji)群(qun)中,部分熱(re)點(dian)節(jie)點(dian)的利用率會(hui)較高,而另外一個節(jie)點(dian)的利用率會(hui)很低。如(ru)果選(xuan)擇平(ping)均(jun)利用率的話可能會(hui)造(zao)成彈性伸縮的不及時。如(ru)果使用最低的節(jie)點(dian)的利用率,那么也(ye)會(hui)造(zao)成彈出資源的浪費。
彈出(chu)實(shi)例(li)后是如何緩(huan)解壓(ya)力的?
在(zai)(zai)Kubernetes中,應(ying)(ying)用是(shi)以Pod為(wei)最小單(dan)元(yuan),部署在(zai)(zai)集群的不(bu)同(tong)節點(dian)(dian)上的。當一個Pod資源利用率(lv)較(jiao)高的時候,即便此時所在(zai)(zai)的節點(dian)(dian)或(huo)者集群的總量觸發了彈性(xing)擴(kuo)容,但是(shi)該應(ying)(ying)用的Pod數目(mu),以及Pod對應(ying)(ying)的Limit沒有任何變(bian)換,那么負載(zai)的壓(ya)力(li)是(shi)無法(fa)轉移(yi)到新擴(kuo)容出的節點(dian)(dian)上的。
如何(he)判斷(duan)以及(ji)執行實(shi)例(li)的縮容?
如(ru)果基于資源利用(yong)率的方(fang)式判斷節點是否縮容,那么很有可能出現,Request很大,但(dan)是Usage很小的Pod被驅逐,當集群中這種類型(xing)的Pod較多時,會導致集群的調(diao)度資源被占滿,部(bu)分Pod無法調(diao)度。
Kubernetes節點伸縮(suo)是怎么解決以上問題的(de)(de)呢(ni)?Kubernetes是通過調(diao)度與資源解耦的(de)(de)兩層彈性(xing)模(mo)型來解決的(de)(de)。
基于資源的(de)(de)使(shi)用率來觸發應用副(fu)本的(de)(de)變化(hua)(hua),也就是調度(du)單元的(de)(de)變化(hua)(hua)。而當集群的(de)(de)調度(du)水位達到(dao)100%的(de)(de)時(shi)候會(hui)觸發資源層(ceng)的(de)(de)彈性擴(kuo)容,當資源彈出(chu)后,無法(fa)調度(du)的(de)(de)單元會(hui)自動調度(du)到(dao)新彈出(chu)的(de)(de)節點上,從而降低(di)整個(ge)應用的(de)(de)負載狀況。以下介紹(shao)Kubernetes彈性伸縮的(de)(de)技(ji)術細節:
如何判(pan)斷節點的彈(dan)出?
cluster-autoscaler是通過對處在(zai)Pending的Pod進行監聽(ting)而觸發(fa)(fa)的。當Pod處在(zai)Pending的原因是調(diao)(diao)度(du)資源(yuan)不(bu)足的時候,會觸發(fa)(fa)cluster-autoscaler的模(mo)擬調(diao)(diao)度(du),模(mo)擬調(diao)(diao)度(du)器(qi)會計算在(zai)配置的伸(shen)(shen)縮組(zu)中哪個伸(shen)(shen)縮組(zu)彈出節點(dian)后可以調(diao)(diao)度(du)這(zhe)些Pending的Pod。如果有(you)伸(shen)(shen)縮組(zu)可以滿足,那么(me)就彈出相應的節點(dian)。
模擬(ni)調度就(jiu)是(shi)(shi)將(jiang)(jiang)一個(ge)伸縮(suo)(suo)組(zu)(zu)當成(cheng)一個(ge)抽象(xiang)的(de)Node,伸縮(suo)(suo)組(zu)(zu)中配(pei)置的(de)機(ji)型規格對(dui)應會(hui)成(cheng)為Node的(de)CPU/內存/GPU的(de)容量(liang),然后設置伸縮(suo)(suo)組(zu)(zu)上(shang)面的(de)Label、Taint,也就(jiu)是(shi)(shi)Node的(de)Label與Taint。模擬(ni)調度器會(hui)在調度模擬(ni)的(de)時候,將(jiang)(jiang)該抽象(xiang)的(de)Node納入調度參考。如果Pending的(de)Pod可(ke)以調度到抽象(xiang)的(de)Node,那么就(jiu)會(hui)計(ji)算所需的(de)Node的(de)數目,驅動伸縮(suo)(suo)組(zu)(zu)彈出節點(dian)。
如何(he)判(pan)斷節點的縮容(rong)?
首先(xian)只有(you)彈性伸縮彈出的(de)(de)(de)節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)會(hui)(hui)被(bei)縮容(rong),靜態的(de)(de)(de)節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)是無法(fa)被(bei)cluster-autoscaler接管的(de)(de)(de)。縮容(rong)的(de)(de)(de)判(pan)斷(duan)是通(tong)過每個節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)單獨判(pan)斷(duan)的(de)(de)(de)。當(dang)任意一個節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)的(de)(de)(de)調(diao)(diao)度利(li)用率低(di)于所設置的(de)(de)(de)調(diao)(diao)度閾值時(shi),會(hui)(hui)觸(chu)發(fa)節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)的(de)(de)(de)縮容(rong)判(pan)斷(duan)。此時(shi)cluster-autoscaler會(hui)(hui)嘗試模擬驅(qu)逐(zhu)節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)上面(mian)的(de)(de)(de)負載,判(pan)斷(duan)當(dang)前節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)是否可以排(pai)水徹底(di)。有(you)些(xie)特殊的(de)(de)(de)Pod(kube-system命名空(kong)間的(de)(de)(de)非DaemonSet Pod、PDB控制的(de)(de)(de)Pod等(deng)),則(ze)會(hui)(hui)跳過該節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)而選擇其(qi)(qi)他的(de)(de)(de)候選節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)。當(dang)節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)發(fa)生驅(qu)逐(zhu)時(shi),會(hui)(hui)先(xian)進行排(pai)水,將節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)上的(de)(de)(de)Pod驅(qu)逐(zhu)到其(qi)(qi)他的(de)(de)(de)節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian),然后再下線該節(jie)(jie)(jie)(jie)(jie)點(dian)(dian)(dian)。
多(duo)個分(fen)組之間如何(he)選擇?
不(bu)同(tong)分組之間(jian),實際上相當(dang)于不(bu)同(tong)的(de)(de)虛擬(ni)的(de)(de)Node之間(jian)的(de)(de)選擇(ze),和調度策(ce)(ce)略(lve)一樣,這里也存在(zai)一個(ge)打分的(de)(de)機(ji)制。首先符合(he)調度策(ce)(ce)略(lve)的(de)(de)Node會先過濾出(chu)來(lai),在(zai)符合(he)調度策(ce)(ce)略(lve)的(de)(de)Node中,會根據affinity等親和性的(de)(de)策(ce)(ce)略(lve)進行選擇(ze)。如果上述的(de)(de)策(ce)(ce)略(lve)都(dou)不(bu)存在(zai),默認情況下cluster-autoscaler會通過least-waste的(de)(de)策(ce)(ce)略(lve)來(lai)進行抉擇(ze)。least-waste的(de)(de)策(ce)(ce)略(lve)的(de)(de)核(he)心就是模擬(ni)彈出(chu)節點(dian)后(hou),剩(sheng)余(yu)的(de)(de)資(zi)源(yuan)最少。此外,有一個(ge)特別的(de)(de)場景,當(dang)有一個(ge)GPU的(de)(de)伸縮(suo)組和CPU的(de)(de)伸縮(suo)組同(tong)時可以彈出(chu)生效時,默認CPU會優先于GPU彈出(chu)。
如何提高彈性伸縮(suo)的成功率?
彈性(xing)伸縮的成功率主要(yao)取(qu)決如下兩(liang)個因素(su):
1、調(diao)度策略是(shi)否滿足
首先(xian)在配置好(hao)伸(shen)縮組(zu)后,開發者需要先(xian)確認下該(gai)伸(shen)縮組(zu)可以承(cheng)載的(de)Pod的(de)調度策略范圍。如果(guo)無(wu)法直接判(pan)斷,最簡單的(de)方式是(shi)通過nodeSelector直接選擇伸(shen)縮組(zu)的(de)Label進行預彈模擬。
2、資源配(pei)置(zhi)是否充分(fen)
當模擬(ni)調度通(tong)過后,會選擇(ze)伸縮(suo)組進行彈出(chu),但是(shi)伸縮(suo)組中配置的(de)ECS規(gui)格是(shi)否有庫(ku)存(cun)會直(zhi)接決定是(shi)否可(ke)以成功(gong)彈出(chu)實例。因此配置多個節點池選擇(ze)不同(tong)的(de)規(gui)格可(ke)以大大提高彈出(chu)成功(gong)率。
應用場景
節點(dian)彈性伸(shen)縮(suo)基(ji)于社區的(de)cluster-autoscaler實現(xian),僅(jin)支持pod pending等有(you)限(xian)的(de)場景(jing)。為應對(dui)更加復(fu)雜的(de)伸(shen)縮(suo)場景(jing),支持監(jian)控、告警、定時。