基于K8S,云原生架構(gòu)的成本優(yōu)化指南
鄭韓
貨拉拉 技術(shù)中心 核心基礎(chǔ)設(shè)施部
架構(gòu)師
- 在貨拉拉主導(dǎo)了Kubernetes從0到1落地全過程,致力于探索符合貨拉拉特點(diǎn)的云原生之道。
今天的分享主要包含以下五個(gè)方面的內(nèi)容:
一、貨拉拉的基本情況介紹
二、基于K8S的成本優(yōu)化手段
三、符合貨拉拉特點(diǎn)的成本優(yōu)化路線
四、競價(jià)實(shí)例成本優(yōu)化實(shí)踐
五、定時(shí)擴(kuò)縮容成本優(yōu)化實(shí)踐
一、貨拉拉的基本情況介紹
在探討成 本優(yōu)化 之前 ,我們 先來 看看 貨拉拉 的基 本情 況,讓 大家 對(duì)貨拉拉有一個(gè)初步的認(rèn)識(shí)。
- 貨拉拉的生產(chǎn)環(huán)境是100%跑在公有云上的,所以我們的成本優(yōu)化也是針對(duì)公有云。
- 貨拉拉是一間全球化的互聯(lián)網(wǎng)公司,我們的業(yè)務(wù)遍布世界各地,在新加坡、印度、拉美和國內(nèi)都有集群,所以我們必定會(huì)有多個(gè)集群跑在不同的云廠商上,這就決定了我們的所有方案都必須是通用的,不綁定任何云廠商的。
- 貨拉拉的流量比較規(guī)律,高峰低谷也比較明顯,貨運(yùn)行業(yè)一般沒有什么突發(fā)事件導(dǎo)致流量突增,不像微博這種服務(wù),某個(gè)明星突然丟出一個(gè)瓜就引來一大波吃瓜群眾,導(dǎo)致流量突增。同時(shí),同城貨運(yùn)是個(gè)日出而作、日落而息的行業(yè),所以白天高峰期比較穩(wěn)定,晚上低峰期流量也會(huì)降到很低,這樣的流量特點(diǎn)可以使我們通過簡單的預(yù)測算法就達(dá)到較好的預(yù)測效果,同時(shí)低峰期的成本優(yōu)化也將會(huì)是我們的優(yōu)化重點(diǎn)。
- 貨拉拉也會(huì)有大量的大數(shù)據(jù)離線任務(wù),大數(shù)據(jù)的離線任務(wù)占了我們公司大概一半的計(jì)算資源,并且高峰期正好是業(yè)務(wù)的低峰期,所以如何通過離在線的混合部署提高整體資源利用率也是我們的優(yōu)化方向之一。
二、基于K8S的成本優(yōu)化手段
講完貨拉拉的基本情況,我們?cè)賮砜匆幌略圃鷷r(shí)代下,一般有哪些成本優(yōu)化手段,我把主流的成本優(yōu)化手段分成四類:
- 私有云的服務(wù)器成本優(yōu)化
- 公有云的服務(wù)器成本優(yōu)化
- 服務(wù)器利用率優(yōu)化
- 服務(wù)性能優(yōu)化
由于貨拉拉是100%跑在公有云上,所以我們本次不討論私有云方面的優(yōu)化。而服務(wù)性能優(yōu)化是非常個(gè)性化的優(yōu)化,所以也不在我們這次討論范圍內(nèi),我們這次主要討論公有云的服務(wù)器成本優(yōu)化和服務(wù)器利用率優(yōu)化。
1、公有云的服務(wù)器成本優(yōu)化
所謂公有云的服務(wù)器成本優(yōu)化,其實(shí)就是研究如何在保證滿足公司實(shí)際需求的前提下,以盡可能低的價(jià)格買到服務(wù)器實(shí)例。
公有云的服務(wù)器,一般有三種優(yōu)惠模式:
- 包年包月: 按固定周期購買一臺(tái)服務(wù)器,這種模式穩(wěn)定性高,價(jià)格實(shí)惠,但是彈性不足,特別是晚上想縮容根本縮不動(dòng)。
- 節(jié)省計(jì)劃: 這種模式其實(shí)就是通過承諾每小時(shí)最低消費(fèi)換取折扣,穩(wěn)定性有保障,服務(wù)器也可以隨意伸縮變換,但是每小時(shí)的總消費(fèi)不能低于承諾消費(fèi),一般來講公司都會(huì)按最低需求購買。
- 競價(jià)實(shí)例: 競價(jià)實(shí)例就是云廠商將閑置的實(shí)例通過固定折扣或競價(jià)的方式出售,折扣一般能到一折或兩折,競價(jià)實(shí)例有最便宜的價(jià)格以及不輸按需實(shí)例的靈活性,但是不穩(wěn)定,隨時(shí)有被回收的風(fēng)險(xiǎn),使用這種實(shí)例對(duì)公司的技術(shù)能力和服務(wù)質(zhì)量都有較高要求。
2、服務(wù)器利用率優(yōu)化
下面我們?cè)賮砜纯刺嵘?wù)器利用率的一些常用優(yōu)化手段。
1)合理request/limit
如何科學(xué)合理地配置request/limit是每個(gè)公司使用k8s都會(huì)遇到的問題,request調(diào)整太大節(jié)點(diǎn)利用率低,調(diào)整太小服務(wù)容易OOM或者被驅(qū)逐。一般來講優(yōu)化方式分兩步,第一步是根據(jù)應(yīng)用畫像和過往負(fù)載設(shè)置一個(gè)初始值,第二步是建立巡檢機(jī)制定期巡檢,根據(jù)實(shí)際負(fù)載和策略動(dòng)態(tài)調(diào)整request/limit配置。
2)HPA
水平POD自動(dòng)擴(kuò)縮容,提前配置好指標(biāo)和閾值,當(dāng)指定指標(biāo)超過閾值時(shí)自動(dòng)擴(kuò)容,低于閾值時(shí)自動(dòng)縮容,比如CPU高于35%就擴(kuò)容。HPA在應(yīng)對(duì)突發(fā)流量時(shí)很不錯(cuò),但是HPA的擴(kuò)容有一定的滯后性,如果負(fù)載增長過快,可能會(huì)出現(xiàn)來不及擴(kuò)容的情況,導(dǎo)致短時(shí)間內(nèi)故障或雪崩。
3)CronHPA
定時(shí)水平擴(kuò)縮容,這種很容易理解,設(shè)置時(shí)間點(diǎn)和副本數(shù),到擴(kuò)容時(shí)間點(diǎn)就擴(kuò)容,到縮容時(shí)間點(diǎn)就縮容,適用于可預(yù)期或計(jì)劃內(nèi)的場景。
4)智能調(diào)度
智能調(diào)度是指根據(jù)公司實(shí)際需求增強(qiáng)調(diào)度器。k8s默認(rèn)的調(diào)度器比較簡單,但一般不能完全符合公司需求,并且有較大的優(yōu)化空間,例如實(shí)際負(fù)載感知、權(quán)重計(jì)算增加更多維度、磁盤GPU、優(yōu)化堆疊策略等,通過優(yōu)化更符合公司實(shí)際情況的調(diào)度算法,可以有效地提升節(jié)點(diǎn)資源利用率。
5)在離線混合部署
離在線混合部署是利用離線任務(wù)可以中斷以及高峰期與在線服務(wù)相反的特點(diǎn),充分利用服務(wù)器算力的一種方式。由于離線任務(wù)一般是在晚上運(yùn)行,如果將離線任務(wù)和在線服務(wù)整合進(jìn)一個(gè)k8s集群,那剛好可以彌補(bǔ)在線服務(wù)低峰期時(shí)的資源浪費(fèi),同時(shí),如果離線任務(wù)可以支持隨時(shí)中斷,那通過自動(dòng)避讓以及資源隔離等手段,還可以實(shí)現(xiàn)在高峰期利用空閑資源運(yùn)行離線任務(wù),榨干服務(wù)器最后一滴性能,但是這項(xiàng)能力在大幅度提升服務(wù)器利用率的情況下,也帶來了巨大的技術(shù)挑戰(zhàn)。
三、符合貨拉拉特點(diǎn)的成本優(yōu)化路線
通過結(jié)合上面說的業(yè)界最佳實(shí)踐和貨拉拉的實(shí)際情況,我們探索出了以下這條貨拉拉成本優(yōu)化演進(jìn)路線。
首先我們通過節(jié)省計(jì)劃以相對(duì)優(yōu)惠的價(jià)格保證了貨拉拉的基礎(chǔ)算力和穩(wěn)定性,然后使用價(jià)格低廉且伸縮靈活的競價(jià)實(shí)例來提供彈性伸縮的算力,當(dāng)然我們也做好了準(zhǔn)備面對(duì)競價(jià)實(shí)例帶來的穩(wěn)定性挑戰(zhàn),到此基本上解決了服務(wù)器價(jià)格的優(yōu)化問題。
接下來我們就需要解決服務(wù)器利用率的問題。
首先我們需要解決低峰期資源浪費(fèi)的問題。剛剛講過貨拉拉的流量是很有規(guī)律的,所以我們通過自研CronHPA實(shí)現(xiàn)可預(yù)測和計(jì)劃內(nèi)的彈性伸縮,同時(shí)通過HPA實(shí)現(xiàn)流量突增時(shí)的緊急擴(kuò)容。這是我們已經(jīng)做完的內(nèi)容。
我們目前正在做的是智能request,通過應(yīng)用畫像和過去的指標(biāo)計(jì)算出合理的request和limit,期望通過這個(gè)功能提高高峰期的節(jié)點(diǎn)資源利用率。
當(dāng)我們完成前面這幾項(xiàng)后,我相信我們已經(jīng)極大的提高了節(jié)點(diǎn)的資源利用率,剩下的就是走完最后一公里,通過智能調(diào)度和在離線混合部署榨干服務(wù)器的最后一滴性能,我們計(jì)劃在2023年完成這些功能,之后再整體不斷優(yōu)化。
接下來我將重點(diǎn)介紹下我們已經(jīng)做完的兩點(diǎn)優(yōu)化, 競價(jià)實(shí)例 和 定時(shí)擴(kuò)縮容。
四、競價(jià)實(shí)例
1、什么是競價(jià)實(shí)例
我們都知道云廠商提供的服務(wù)器實(shí)例都是他們的物理機(jī)房虛擬化出來的,那既然是物理機(jī)房,服務(wù)器就是相對(duì)固定的,能夠提供的算力也是固定的,但是我們購買的實(shí)例數(shù)卻是浮動(dòng)的,所以云廠商總有些算力是閑置的,而閑置的服務(wù)器產(chǎn)生的經(jīng)濟(jì)價(jià)值就是0,所以云廠商就將這些閑置的算力拿出來打折或競價(jià)銷售,這些打折或競價(jià)銷售的實(shí)例就是競價(jià)實(shí)例。
競價(jià)實(shí)例的由來所有云廠都是一樣的,但是各個(gè)云廠商對(duì)競價(jià)實(shí)例的價(jià)格計(jì)算方式卻存在差異,主要有兩種方式:一種是 固定折扣 ,基本上都是打兩折,這個(gè)很好理解;另外一種是 競價(jià) ,競價(jià)比較難理解。下面我介紹一下競價(jià)的基本過程。
2、競價(jià)方式介紹
我們購買競價(jià)實(shí)例時(shí),會(huì)填寫一個(gè)可接受的最高價(jià)格,然后云廠商會(huì)根據(jù)所有人的報(bào)價(jià)和庫存情況計(jì)算出一個(gè)價(jià)格,出價(jià)高于或等于這個(gè)價(jià)格的人就能以這個(gè)價(jià)格買到實(shí)例,低于價(jià)格則購買失敗。上圖有個(gè)細(xì)節(jié)不知道大家有沒有發(fā)現(xiàn),整幅圖只有定價(jià)這里我是用了黑色,那是因?yàn)檫@個(gè)價(jià)格到底是怎么計(jì)算出來的完全是個(gè)黑盒,其中的算法只有云廠商自己知道,我們只能知道他最后得出來一個(gè)價(jià)格,這個(gè)價(jià)格最低可以低到1折,最高可以等于沒打折。
3、競價(jià)實(shí)例原理
下面我講講使用競價(jià)實(shí)例的基本原理。
首先我們帶著機(jī)器型號(hào)和一個(gè)能接受的最高價(jià)向云廠商提出購買申請(qǐng),云廠商如果判斷指定型號(hào)有庫存并且價(jià)格在我們的報(bào)價(jià)之下,則給我們分配實(shí)例,購買完成,這時(shí)我們就可以正常使用了。
在我們正常使用該競價(jià)實(shí)例的過程中,云廠商會(huì)一直監(jiān)控庫存和價(jià)格變化,當(dāng)發(fā)現(xiàn)價(jià)格實(shí)時(shí)價(jià)格高于我們的報(bào)價(jià)或庫存不足時(shí),將向我們發(fā)送中斷信號(hào),收到信號(hào)后我們需要做一些措施保證該實(shí)例被回收不影響業(yè)務(wù),在我們收到中斷信號(hào)的幾分鐘后,實(shí)例就會(huì)被回收。
不同云廠商在回收機(jī)制上有些不同。aws會(huì)有預(yù)測算法,在預(yù)測到庫存不足時(shí)提前通知你,讓你有更多反應(yīng)時(shí)間;阿里云有一小時(shí)保護(hù)機(jī)制,競價(jià)實(shí)例運(yùn)行的第一個(gè)小時(shí)能保證不被回收。但是都不會(huì)等我們做完我們想做的事再回收,無一例外。比如我們想再買臺(tái)機(jī)器將服務(wù)遷移過去,但是可能還沒遷移就被回收了,所以我們應(yīng)對(duì)突然中斷的手段一定要足夠快,才能避免對(duì)業(yè)務(wù)產(chǎn)生影響。
4、競價(jià)實(shí)例特點(diǎn)
介紹完競價(jià)實(shí)例的基本原理,我們?cè)倏偨Y(jié)一下競價(jià)實(shí)例的特點(diǎn):
- 性價(jià)比高。 和按需實(shí)例對(duì)比,競價(jià)實(shí)例通常僅是其價(jià)格的10-20%。和預(yù)留實(shí)例對(duì)比,競價(jià)實(shí)例通常僅是其價(jià)格的30-60%。
- 競價(jià)實(shí)例是將閑置資源打折出售。 當(dāng)沒有閑置資源時(shí),也就無法購買了,不是你什么時(shí)候想買云廠商都有貨。
- 隨時(shí)中斷。 云廠商會(huì)動(dòng)態(tài)檢測當(dāng)前的市場價(jià)格和庫存,一旦庫存不足,或者你的出價(jià)小于市場價(jià)格,云供應(yīng)商可以在任何時(shí)候回收這些實(shí)例。
性價(jià)比高是我們使用競價(jià)實(shí)例的目標(biāo),庫存沒保障和隨時(shí)中斷是我們需要解決的問題。
5、競價(jià)實(shí)例結(jié)合K8S 落地
下面我將介紹競價(jià)實(shí)例如何結(jié)合K8S落地,以及如何解決競價(jià)實(shí)例帶來的穩(wěn)定性問題。
首先從圖中我們可以看到,我將k8s的節(jié)點(diǎn)分成了多個(gè)節(jié)點(diǎn)組,然后通過cluster autoscaler進(jìn)行彈性伸縮。節(jié)點(diǎn)組中有按需實(shí)例的節(jié)點(diǎn)組,也有競價(jià)實(shí)例的節(jié)點(diǎn)組,這是因?yàn)椴⒉皇撬蟹?wù)都適合部署在競價(jià)實(shí)例上,我們需要一些更穩(wěn)定性的節(jié)點(diǎn)部署跑不適合跑在競價(jià)實(shí)例上的服務(wù),同時(shí)我們也需要在競價(jià)實(shí)例庫存不足時(shí)有按需實(shí)例的節(jié)點(diǎn)組提供足夠的算力支持業(yè)務(wù)正常運(yùn)行。
然后我們?cè)賮砜粗袛嗷厥詹糠?。?dāng)競價(jià)實(shí)例需要中斷時(shí),云廠商會(huì)發(fā)送一個(gè)中斷信號(hào),如果是托管集群,云廠商會(huì)自己處理這個(gè)中斷信號(hào),幫我們起一個(gè)新的節(jié)點(diǎn)并回收舊節(jié)點(diǎn),但如果是自建集群,我們則需要自己實(shí)現(xiàn)一個(gè)中斷信號(hào)處理服務(wù),在該服務(wù)中處理中斷問題。
在貨拉拉雖然我們是托管集群,但是我們還是自己開發(fā)了一個(gè)notify handler,該服務(wù)主要是為了收集中斷信號(hào),用于監(jiān)控中斷頻率以便后續(xù)用于告警和觸發(fā)應(yīng)急預(yù)案。
整體架構(gòu)還是比較簡單的,但是我們?cè)趯?shí)際使用過程中還是發(fā)現(xiàn)有不少地方需要優(yōu)化,下面我就介紹下幾個(gè)主要的優(yōu)化點(diǎn)。
6、競價(jià)實(shí)例優(yōu)化點(diǎn)
1)增加競價(jià)實(shí)例的型號(hào)
上面我們講過競價(jià)實(shí)例的庫存沒有保障,所以我們能做的就是擴(kuò)大這個(gè)池子,池子越多,庫存不足的概率就越低,所以我們創(chuàng)建的節(jié)點(diǎn)組需要覆蓋更多的可用區(qū)和更多的實(shí)例型號(hào)。但是需要注意的是,受到cluster autoscaler的限制,同一個(gè)節(jié)點(diǎn)組里的節(jié)點(diǎn)cpu和內(nèi)存必須一致。
2)設(shè)置節(jié)點(diǎn)組優(yōu)先級(jí)
目前我們的集群中有按需實(shí)例節(jié)點(diǎn)組和競價(jià)實(shí)例節(jié)點(diǎn)組,我們希望資源不足時(shí)優(yōu)先彈出競價(jià)實(shí)例,只有當(dāng)競價(jià)實(shí)例無法彈出時(shí)才彈出按需實(shí)例,這樣可以確保最大化的利用競價(jià)實(shí)例,同時(shí)又能確保競價(jià)實(shí)例庫存不足時(shí)及時(shí)彈出按需實(shí)例保證業(yè)務(wù)穩(wěn)定運(yùn)行。
這里用到的是cluster autoscaler的優(yōu)先級(jí)配置,我們?cè)赾luster autoscaler的一個(gè)configmap中配置節(jié)點(diǎn)組的優(yōu)先級(jí),將競價(jià)實(shí)例的優(yōu)先級(jí)設(shè)置成20,其他節(jié)點(diǎn)組是10,這樣ca就會(huì)優(yōu)先彈出競價(jià)實(shí)例,彈不出競價(jià)實(shí)例時(shí)彈出按需實(shí)例。
3)設(shè)置pod親和性
由于競價(jià)實(shí)例隨時(shí)可能被中斷,且一旦中斷很有可能是同一個(gè)型號(hào)的節(jié)點(diǎn)同時(shí)被中斷,所以我們要避免把雞蛋放在一個(gè)籃子里,盡量把同一個(gè)服務(wù)的pod分散在不同實(shí)例、不同型號(hào)甚至是不同的可用區(qū)中,避免某一個(gè)服務(wù)所有的pod被同時(shí)驅(qū)逐,造成服務(wù)不可用。
這里用到的就是pod的親和性配置。從配置上我們可以看到,我們給了可用區(qū)最大的權(quán)重,其次是實(shí)例型號(hào),最后是實(shí)例名,這樣k8s會(huì)盡量將同一個(gè)app的pod分散到不同的可用區(qū),如果沒有合適的節(jié)點(diǎn)則分散到不同的實(shí)例類型,依然沒有合適的再分散到不同的實(shí)例,這樣可以最大化地打散同一個(gè)服務(wù)的pod,避免由于競價(jià)實(shí)例中斷導(dǎo)致服務(wù)不可用。
4)配置PDB
盡管我們之前已經(jīng)做了很多措施,避免同一個(gè)服務(wù)的pod在同一時(shí)間由于實(shí)例中斷被驅(qū)逐,但是沒有哪一項(xiàng)是能100%避免這種情況的,所以我們需要再上一層保險(xiǎn),這層保險(xiǎn)就是PDB,通過PDB我們可以設(shè)置同一個(gè)服務(wù)的pod必須保證同一時(shí)間有多少副本是可用的。像下面這張圖的配置里面就保證了服務(wù)70%的副本是正常的,這樣就算遇到需要同時(shí)驅(qū)逐的情況,k8s也會(huì)在強(qiáng)制保證至少有70%的副本可用的情況下滾動(dòng)驅(qū)逐,確保整個(gè)過程服務(wù)都是可用的狀態(tài)。
但是需要注意的是,這個(gè)配置會(huì)導(dǎo)致本來可以并發(fā)的驅(qū)逐變成串行,這會(huì)影響到排空節(jié)點(diǎn)的時(shí)間,所以這個(gè)需要服務(wù)的啟動(dòng)速度足夠快,在節(jié)點(diǎn)被真正回收前執(zhí)行完整個(gè)遷移過程。
5)利用低優(yōu)先級(jí)的pause pod給集群預(yù)留空間
上面我們講過,競價(jià)實(shí)例從收到中斷信號(hào)到真的被回收就那么兩三分鐘時(shí)間,時(shí)間一到不管我們是什么情況實(shí)例都會(huì)被回收,所以我們必須保證在實(shí)例被回收前完成整個(gè)遷移動(dòng)作,那這兩三分鐘的每一秒是很珍貴的,我們必須想方設(shè)法提高遷移的效率,但是創(chuàng)建一個(gè)新的節(jié)點(diǎn)少則幾十秒,多則一兩分鐘,等新節(jié)點(diǎn)準(zhǔn)備好其實(shí)已經(jīng)浪費(fèi)了很多時(shí)間,所以我們需要想辦法在收到中斷信號(hào)的時(shí)候就直接將舊節(jié)點(diǎn)排空,但是要排空節(jié)點(diǎn)就需要保證集群隨時(shí)有足夠的空間運(yùn)行被驅(qū)逐的pod。而保證有足夠空間的做法就是我們現(xiàn)在講的這個(gè)利用低優(yōu)先級(jí)的pause pod給集群預(yù)留空間。
k8s里面的pod有一個(gè)優(yōu)先級(jí)的概念,高優(yōu)先級(jí)的pod可以在資源不足時(shí)搶占低優(yōu)先級(jí)的pod。從下面這張圖我們可以看到,我們?cè)贜ode1和Node2都放置了一些低優(yōu)先級(jí)的Pod,當(dāng)Node1被中斷回收后,高優(yōu)先級(jí)的pod會(huì)直接搶占低優(yōu)先級(jí)的pod從而實(shí)現(xiàn)快速啟動(dòng),而不需要等新的節(jié)點(diǎn)準(zhǔn)備就緒,而低優(yōu)先級(jí)的pod則會(huì)全部變成pending狀態(tài)觸發(fā)擴(kuò)容或等待新的節(jié)點(diǎn)ready后啟動(dòng),從而重新創(chuàng)建了一塊預(yù)留空間。
下面是具體的yaml,這里面優(yōu)先級(jí)不必非得是-1,只要保證比正常pod的優(yōu)先級(jí)小即可,低優(yōu)先級(jí)pod主要是要把PriorityClassName填對(duì),然后根據(jù)實(shí)際情況設(shè)置副本數(shù)和request即可。
7、不適宜部署在競價(jià)實(shí)例的服務(wù)
- 單副本服務(wù)。 這個(gè)不用解釋大家都明白。
- 啟動(dòng)時(shí)間過長的服務(wù)。 因?yàn)樾枰WC服務(wù)能在實(shí)例被回收之前啟動(dòng)完成,所以服務(wù)的啟動(dòng)時(shí)間不能太長。
- 無法容忍任何非優(yōu)雅停止的服務(wù)。 我們需要認(rèn)識(shí)到不管我們做了多少措施,都不能完全杜絕實(shí)例在沒有排空之前就被回收,所以對(duì)于不能優(yōu)雅停止無法容忍的服務(wù)也不適合部署在競價(jià)實(shí)例上。
- 有狀態(tài)的服務(wù)。 有狀態(tài)的服務(wù)遷移起來遠(yuǎn)沒有無狀態(tài)的服務(wù)靈活,為避免出現(xiàn)各種各樣的問題,也不建議有狀態(tài)的服務(wù)部署在競價(jià)實(shí)例上。
五、定時(shí)擴(kuò)縮容
1、背景
彈性伸縮的本質(zhì)是為了提高服務(wù)器的利用率,那我們來看看貨拉拉一個(gè)沒有任何優(yōu)化的集群的CPU利用率是怎么樣的。
從這個(gè)圖我們可以看到,這個(gè)集群在白天最高峰時(shí)的CPU利用率是35%,半夜低峰期的CPU利用率卻只有2.5%,2點(diǎn)的時(shí)候還有一個(gè)小高峰,是因?yàn)槲覀冊(cè)谶@個(gè)時(shí)候有大量定時(shí)任務(wù)在執(zhí)行,可以先不用考慮。目前這個(gè)利用率如果是放在虛擬機(jī)時(shí)代,還算是一個(gè)比較能接受的利用率,但是放在云原生時(shí)代,我們還是有很多手段可以提升這個(gè)利用率。
我們的優(yōu)化目標(biāo)是希望把高峰期節(jié)點(diǎn)CPU平均利用率達(dá)到50%,低峰期節(jié)點(diǎn)CPU平均利用率達(dá)到30%。
2、默認(rèn)HPA的不足
按照正常做法,我們把HPA套上去應(yīng)該就可以解決這些問題,隨著流量上升自動(dòng)擴(kuò)容,流量下降后自動(dòng)縮容,事實(shí)上我們也這樣做過,但是很快就發(fā)現(xiàn)了問題。
第一個(gè)問題是 擴(kuò)容有一定滯后。 HPA需要等負(fù)載上來觸發(fā)閾值后才開始擴(kuò)容,而負(fù)載升得太快可能會(huì)導(dǎo)致擴(kuò)容不及時(shí),我們每天早上9點(diǎn)和下午2點(diǎn)都有一波很迅速的流量上升,這時(shí)HPA會(huì)大量擴(kuò)容,但是大量擴(kuò)容就需要先大量擴(kuò)節(jié)點(diǎn),導(dǎo)致這兩個(gè)時(shí)間點(diǎn)擴(kuò)容總是太慢,每天這兩個(gè)時(shí)間點(diǎn)都會(huì)有些報(bào)錯(cuò),然后觸發(fā)告警。
第二個(gè)問題是 擴(kuò)容閾值受到限制 。為了白天流量上升時(shí)擴(kuò)容盡量穩(wěn)定,我們不能把最小副本數(shù)設(shè)置得太低,這就導(dǎo)致我們晚上的CPU利用率上不去。而為了擴(kuò)容及時(shí),我們也不能把CPU的閾值設(shè)置得太高,因?yàn)樵礁呔鸵馕稊U(kuò)容時(shí)反應(yīng)約遲鈍,而設(shè)置得太低又導(dǎo)致高峰期CPU利用率上不去,例如我們?cè)贖PA把CPU的閾值設(shè)置為35%,那我們的pod的CPU使用率基本上都不能超過35%,因?yàn)槌^就會(huì)擴(kuò)容,然后把CPU利用率拉下來。
第三個(gè)問題是 擴(kuò)縮容時(shí)機(jī)無法控制。 HPA是完全根據(jù)配置的指標(biāo)和閾值來擴(kuò)容,無法根據(jù)企業(yè)特點(diǎn)定制策略,例如貨拉拉的流量白天還是比較穩(wěn)定的,我們?cè)诎滋旄叻迤跁r(shí)就算浪費(fèi)點(diǎn)資源也不希望出現(xiàn)過多擴(kuò)縮容影響穩(wěn)定性,但是HPA并沒有提供這樣的配置。
3、CronHPA+HPA
結(jié)合我們對(duì)HPA的實(shí)踐經(jīng)驗(yàn)和貨拉拉的業(yè)務(wù)特點(diǎn),我們總結(jié)探索出了符合貨拉拉特點(diǎn)的水平彈性伸縮方式,那就是自研的CronHPA+HPA組合。
CronHPA是根據(jù)設(shè)定好的時(shí)間調(diào)整對(duì)應(yīng)HPA 的最小副本數(shù),實(shí)現(xiàn)可預(yù)期或計(jì)劃內(nèi)的彈性伸縮。
考慮到貨拉拉流量規(guī)律的特點(diǎn),我們?cè)谧匝械腃ronHPA中通過定時(shí)+過往指標(biāo)分析+簡單預(yù)測算法可以做到比較高質(zhì)量的預(yù)擴(kuò)容以及定時(shí)縮容。例如早上9點(diǎn)流量開始快速上升,我們可以在7點(diǎn)到8點(diǎn)就提前把集群擴(kuò)容到高峰期的水平,晚上10點(diǎn)后流量已經(jīng)下降了很多,我們可以放心地縮容,并且有了預(yù)擴(kuò)容打底,我們晚上可以把副本數(shù)縮到一個(gè)極低的水平而不用擔(dān)心白天來不及擴(kuò)容。
CronHPA沒有直接操作deployment的副本數(shù),而是操作HPA的最低副本數(shù),是因?yàn)楸M管CronHPA可以覆蓋我們99%的擴(kuò)縮容需求,但是仍然需要HPA的自動(dòng)擴(kuò)縮容來解決1%偶發(fā)流量突增的問題,盡管我們很少遇到流量突增的情況,但是有了HPA可以讓我們?cè)诳s容或者設(shè)置高峰期副本數(shù)時(shí)不必為偶發(fā)的流量突增添加額外的buff,從而提升整體的資源利用率。
4、架構(gòu)
講完定時(shí)擴(kuò)縮容的原理,我們?cè)賮碇v講定時(shí)擴(kuò)縮容的架構(gòu)。
我們?cè)贙8S部署了一個(gè)自研的hll-cronhpa-controller,并且添加了一個(gè)CronHPA的CRD,用戶主要是設(shè)置CronHPA的CRD來設(shè)置彈性伸縮,并不直接設(shè)置HPA和deployment副本數(shù),hll-cronhpa-controller會(huì)監(jiān)聽CronHPA CRD對(duì)象的變化,當(dāng)發(fā)現(xiàn)有新增或者更新時(shí),就會(huì)同步修改HPA對(duì)象,其中除了最小副本數(shù)其他都是直接透傳,CronHPA的所有業(yè)務(wù)邏輯最終都會(huì)體現(xiàn)在HPA最小副本數(shù)的變化上。
而CronHPA的業(yè)務(wù)邏輯主要是hll-cronhpa-controller根據(jù)cronHPA對(duì)象的配置,從Prometheus拉取過往指標(biāo)分析,同時(shí)結(jié)合從應(yīng)用管理平臺(tái)拉取的應(yīng)用畫像以及從配置中心拉取的擴(kuò)縮容策略綜合分析后在合適的時(shí)間點(diǎn)為對(duì)應(yīng)的HPA對(duì)象設(shè)置一個(gè)合適的最小副本數(shù),這么說可能有點(diǎn)抽象。
舉個(gè)例子,假設(shè)我目前有個(gè)服務(wù)設(shè)置了晚上需要縮容,我們通過分析該服務(wù)過往夜間資源利用率得出晚上可以縮到剩下2個(gè)副本,同時(shí)我們從應(yīng)用畫像中查到該服務(wù)是核心服務(wù),而配置中心的擴(kuò)縮容策略是核心服務(wù)最低不能少于5個(gè)副本,那綜合分析我們夜間需要給他設(shè)置的副本數(shù)就是5。
5、實(shí)現(xiàn)路徑
下面講一下我們的實(shí)現(xiàn)路徑。我們最開始自研的時(shí)候就確定了cronHPA+HPA的架構(gòu)。
第一階段是純手工配置的,我們通過分析流量設(shè)置了一個(gè)全局縮容時(shí)間點(diǎn)和全局?jǐn)U容時(shí)間點(diǎn),然后各個(gè)服務(wù)根據(jù)經(jīng)驗(yàn)人工估算出一個(gè)縮容比例。這個(gè)階段由于全局是在同一個(gè)時(shí)間點(diǎn)同時(shí)擴(kuò)縮容,在擴(kuò)容瞬間對(duì)基礎(chǔ)設(shè)施的壓力比較大,同時(shí)人工估算出來的縮容比例還是過于保守。
第二階段是根據(jù)過往指標(biāo)分析自動(dòng)設(shè)置擴(kuò)縮容的時(shí)機(jī),這樣可以有效分散擴(kuò)縮容壓力,同時(shí)讓擴(kuò)縮容時(shí)機(jī)更為合理。例如有些服務(wù)可能晚上6點(diǎn)就沒流量了,階段一還需要等到晚上10點(diǎn)才縮容。
第三階段是根據(jù)appid自動(dòng)計(jì)算縮容比例。人工估算縮容比例還是過于保守,例如高峰期100個(gè)pod,晚上其實(shí)可能只需要10個(gè),但是一般人工評(píng)估只會(huì)縮到50個(gè),但是通過算法自動(dòng)計(jì)算就會(huì)相對(duì)科學(xué)很多,同時(shí)自動(dòng)計(jì)算還可以通過分析過往指標(biāo)不斷修正,例如某個(gè)pod經(jīng)過計(jì)算晚上縮容到2個(gè)pod,但是通過分析過往指標(biāo)發(fā)現(xiàn)過去7天晚上都會(huì)通過HPA擴(kuò)容到3個(gè)pod,那第八天就把縮容副本數(shù)自動(dòng)調(diào)整到3個(gè)。
第四階段是自動(dòng)識(shí)別低峰期。原來手工設(shè)置低峰期時(shí)間段,程序在從這個(gè)時(shí)間段里選擇擴(kuò)縮容時(shí)機(jī),到了這一階段,我們可以自動(dòng)識(shí)別每個(gè)服務(wù)自己的業(yè)務(wù)低峰期,做到個(gè)性化縮容。
第五階段是自動(dòng)分階段擴(kuò)縮容,前幾個(gè)階段都是確定一個(gè)擴(kuò)縮容時(shí)間點(diǎn),直接把副本數(shù)擴(kuò)縮到目標(biāo)副本數(shù),但流量其實(shí)是逐漸變化的,通過這個(gè)階段我們可以實(shí)現(xiàn)服務(wù)在高峰期來臨前隨著流量上升逐步把副本數(shù)提上去,而在低峰期,隨時(shí)流量降低逐步降低副本數(shù),這個(gè)階段與HPA最大的不同在于,HPA是基于指標(biāo)和閾值,而cronHPA是基于預(yù)測。
6、未來規(guī)劃
最后講一下我們對(duì)于彈性伸縮的未來規(guī)劃,我們希望未來彈性伸縮可以形成這樣一個(gè)機(jī)制,服務(wù)初始化時(shí)可以通過應(yīng)用畫像自動(dòng)設(shè)置reqeust/limit和副本數(shù),然后自動(dòng)在高低峰通過過往指標(biāo)分析和算法實(shí)現(xiàn)預(yù)擴(kuò)容和及時(shí)縮容。
如果遇到突發(fā)流量可以通過原地升配實(shí)現(xiàn)快速縱向擴(kuò)容,原地升配對(duì)比VPA最大的區(qū)別在于不用重啟pod,所以可以做到秒級(jí)擴(kuò)容。如果所在節(jié)點(diǎn)資源不足則通過HPA橫向擴(kuò)容,同時(shí)根據(jù)指標(biāo)分析不斷修正服務(wù)的reqeust/limit和副本數(shù),實(shí)現(xiàn)全自動(dòng)的彈性伸縮閉環(huán)。