美團點評Kubernetes集群管理實踐
背景
作為國內領先的生活服務平臺,美團點評很多業(yè)務都具有非常顯著、規(guī)律的”高峰“和”低谷“特征。尤其遇到節(jié)假日或促銷活動,流量還會在短時間內出現爆發(fā)式的增長。這對集群中心的資源彈性和可用性有非常高的要求,同時也會使系統(tǒng)在支撐業(yè)務流量時的復雜度和成本支出呈現指數級增長。而我們需要做的,就是利用有限的資源最大化地提升集群的吞吐能力,以保障用戶體驗。
本文將介紹美團點評Kubernetes集群管理與使用實踐,包括美團點評集群管理與調度系統(tǒng)介紹、Kubernetes管理與實踐、Kubernetes優(yōu)化與改造以及資源管理與優(yōu)化等。
美團點評集群管理與調度系統(tǒng)
美團點評在集群管理和資源優(yōu)化這條道路上已經“摸爬滾打”多年。2013年,開始構建基于傳統(tǒng)虛擬化技術的資源交付方式;2015年7月,開始建立完善的集群管理與調度系統(tǒng)——HULK,目標是推動美團點評服務容器化;2016年,完成基于Docker容器技術自研實現了彈性伸縮能力,來提升交付速度和應對快速擴縮容的需求,實現彈性擴容、縮容,提升資源利用率,提升業(yè)務運維效率,合理有效的降低企業(yè)IT運維成本;2018年,開始基于Kubernetes來進行資源管理和調度,進一步提升資源的使用效率。
最初,美團點評通過基于Docker容器技術自研實現了彈性伸縮能力,主要是為了解決基于虛擬化技術的管理及部署機制在應對服務快速擴容、縮容需求時存在的諸多不足。例如資源實例創(chuàng)建慢、無法統(tǒng)一運行環(huán)境、實例部署和交付流程長、資源回收效率低、彈性能力差等等。經過調研與測試,結合業(yè)界的實踐經驗,我們決定基于Docker容器技術自研集群管理與調度系統(tǒng),有效應對快速擴縮容的需求,提升資源的利用效率。我們把它叫做”綠巨人”——HULK,這個階段可以看作是HULK1.0。
之后,在生產環(huán)境中經過不斷摸索和嘗試,我們逐漸意識到,僅僅滿足于集群的彈性伸縮能力是不夠的,成本和效率肯定是未來必將面臨且更為棘手的問題。我們吸取了2年來HULK 1.0的開發(fā)和運維經驗,在架構和支撐系統(tǒng)層面做了進一步優(yōu)化和改進,并借助于生態(tài)和開源的力量來為HULK賦能,即引入了開源的集群管理與調度系統(tǒng)Kubernetes,期望能進一步提升集群管理、運行的效率和穩(wěn)定性,同時降低資源成本。所以我們從自研平臺轉向了開源的Kubernetes系統(tǒng),并基于Kubernetes系統(tǒng)打造了更加智能化的集群管理與調度系統(tǒng)——HULK2.0。
架構全覽
在架構層面,HULK2.0如何能與上層業(yè)務和底層Kubernetes平臺更好地分層和解耦,是我們在設計之初就優(yōu)先考慮的問題。我們期望它既要能對業(yè)務使用友好,又能最大限度地發(fā)揮Kubernetes的調度能力,使得業(yè)務層和使用方毋需關注資源關系細節(jié),所求即所得;同時使發(fā)布、配置、計費、負載等邏輯層與底層的Kubernetes平臺解耦分層,并保持兼容原生Kubernetes API來訪問Kubernetes集群。從而可以借助于統(tǒng)一的、主流的、符合業(yè)界規(guī)范的標準,來解決美團點評基礎架構面臨的復雜的、多樣的、不統(tǒng)一的管理需求。
架構介紹
自上而下來看,美團集群管理與調度平臺面向全公司服務,有各個主要業(yè)務線、統(tǒng)一的OPS平臺以及Portal平臺,HULK不可能針對每個平臺定制化接口和解決方案,所以需要將多樣的業(yè)務和需求抽象收斂,最終統(tǒng)一通過HULK API來屏蔽HULK系統(tǒng)的細節(jié),做到HULK與上層業(yè)務方的解耦。HULK API是對業(yè)務層和資源需求的抽象,是外界訪問HULK的唯一途徑。
解決了上層的問題后,我們再來看與下層Kubernetes平臺的解耦。HULK接到上層資源請求后,首先要進行一系列的初始化工作,包括參數校驗、資源余量、IP和Hostname的分配等等,之后向Kubernetes平臺實際申請分配機器資源,最終將資源交付給用戶,Kubernetes API進一步將資源需求收斂和轉換,讓我們可以借助于Kubernetes的資源管理優(yōu)勢。Kubernetes API旨在收斂HULK的資源管理邏輯并與業(yè)界主流對齊。此外,因為完全兼容Kubernetes API,可以讓我們借助社區(qū)和生態(tài)的力量,共同建設和探索。
可以看到,HULK API和Kubernetes API將我們整個系統(tǒng)分為三層,這樣可以讓每一層都專注于各自的模塊。
Kubernetes管理與實踐
為什么會選擇Kubernetes呢?Kubernetes并不是市面上唯一的集群管理平臺(其他如Docker Swarm或Mesos),之所以選擇它,除了它本身優(yōu)秀的架構設計,我們更加看重的是Kubernetes提供的不是一個解決方案,而是一個平臺和一種能力。這種能力能夠讓我們真正基于美團點評的實際情況來擴展,同時能夠依賴和復用多年來的技術積累,給予我們更多選擇的自由,包括我們可以快速地部署應用程序,而無須面對傳統(tǒng)平臺所具有的風險,動態(tài)地擴展應用程序以及更好的資源分配策略。
Kubernetes集群作為整個HULK集群資源管理與平臺的基礎,需求是穩(wěn)定性和可擴展性,風險可控性和集群吞吐能力。
集群運營現狀
- 集群規(guī)模:10萬+級別線上實例,多地域部署,還在不斷快速增長中。
- 業(yè)務的監(jiān)控告警:集群對應用的啟動和狀態(tài)數據進行采集,container-init自動集成業(yè)務監(jiān)控信息,業(yè)務程序毋需關注,做到可插拔、可配置。
- 資源的健康告警:從資源的角度對 Node、Pod和 Container等重要數據監(jiān)控采集,及時發(fā)現它們的狀態(tài)信息,例如 Node不可用、Container不斷重啟等等。
- 定時巡檢與對賬:每天自動對所有宿主機進行狀態(tài)檢查,包括剩余磁盤量(數據卷)、D進程數量、宿主機狀態(tài)等,并對AppKey擴容數據和實際的Pod和容器數據同步校驗,及時發(fā)現不一致情況。
- 集群數據可視化:對當前集群狀態(tài),包括宿主機資源狀態(tài)、服務數、Pod數、容器化率、服務狀態(tài)、擴縮容數據等等可視化;并提供了界面化的服務配置、宿主機下線以及Pod遷移操作入口。
- 容量規(guī)劃與預測:提前感知集群資源狀態(tài),預先準備資源;基于規(guī)則和機器學習的方式感知流量和高峰,保證業(yè)務正常、穩(wěn)定、高效地運行。
Kubernetes優(yōu)化與改造
kube-scheduler性能優(yōu)化
我們有集群在使用1.6版本的調度器,隨著集群規(guī)模的不斷增長,舊版本的Kubernetes調度器(1.10之前版本)在性能和穩(wěn)定性的問題逐漸凸顯,由于調度器的吞吐量低,導致業(yè)務擴容超時失敗,在規(guī)模近3000臺的集群上,一次Pod的調度耗時在5s左右。Kubernetes的調度器是隊列化的調度器模型,一旦擴容高峰等待的Pod數量過多就會導致后面Pod的擴容超時。為此,我們對調度器性能進行了大幅度的優(yōu)化,并取得了非常明顯的提升,根據我們的實際生產環(huán)境驗證,性能比優(yōu)化前提升了400%以上。
Kubernetes調度器工作模型如下:
(kubernetes調度器,圖片來源于網絡)
預選失敗中斷機制
一次調度過程在判斷一個 Node是否可作為目標機器時,主要分為三個階段:
- 預選階段:硬性條件,過濾掉不滿足條件的節(jié)點,這個過程稱為 Predicates。這是固定先后順序的一系列過濾條件,任何一個 Predicate不符合則放棄該 Node。
- 優(yōu)選階段:軟性條件,對通過的節(jié)點按照優(yōu)先級排序,稱之為 Priorities。每一個Priority都是一個影響因素,都有一定的權重。
- 選定階段:從優(yōu)選列表中選擇優(yōu)先級最高的節(jié)點,稱為 Select。選擇的Node即為最終部署Pod的機器。
通過深入分析調度過程可以發(fā)現,調度器在預選階段即使已經知道當前 Node不符合某個過濾條件仍然會繼續(xù)判斷后續(xù)的過濾條件是否符合。試想如果有上萬臺 Node節(jié)點,這些判斷邏輯會浪費很多計算時間,這也是調度器性能低下的一個重要因素。
為此,我們提出了“預選失敗中斷機制”,即一旦某個預選條件不滿足,那么該 Node即被立即放棄,后面的預選條件不再做判斷計算,從而大大減少了計算量,調度性能也大大提升。如下圖所示:
我們把該項優(yōu)化貢獻給了 Kubernetes社區(qū)(詳見PR),增加了 alwaysCheckAllPredicates 策略選項,并在 Kubernetes1.10版本發(fā)布并開始作為默認的調度策略,當然你也可以通過設置alwaysCheckAllPredicates=true使用原先的調度策略。
在實際測試中,調度器至少可以提升40%的性能,如果你目前在使用的Kube-scheduler的版本低于1.10,那么建議你嘗試升級到新的版本。
局部最優(yōu)解
對于優(yōu)化問題尤其是最優(yōu)化問題,我們總希望找到全局最優(yōu)的解或策略,但是當問題的復雜度過高,要考慮的因素和處理的信息量過多時,我們往往會傾向于接受局部最優(yōu)解,因為局部最優(yōu)解的質量不一定都是差的。尤其是當我們有確定的評判標準,同時標明得出的解是可以接受的話,通常會接收局部最優(yōu)的結果。這樣,從成本、效率等多方面考慮,才是我們在實際工程中真正會采取的策略。
(圖片來源于網絡)
當前調度策略中,每次調度調度器都會遍歷集群中所有的Node,以便找出最優(yōu)的節(jié)點,這在調度領域稱之為BestFit算法。但是在生產環(huán)境中,我們是選取最優(yōu)Node還是次優(yōu)Node,其實并沒有特別大的區(qū)別和影響,有時候我們還是會避免選取最優(yōu)的Node(例如我們集群為了解決新上線機器后頻繁在該機器上創(chuàng)建應用的問題,就將最優(yōu)解隨機化)。換句話說,找出局部最優(yōu)解就能滿足需求。
假設集群一共1000個Node,一次調度過程PodA,這其中有700個Node都能通過Predicates(預選階段),那么我們就會把所有的Node遍歷并找出這700個Node,然后經過得分排序找出最優(yōu)的Node節(jié)點NodeX。但是采用局部最優(yōu)算法,即我們認為只要能找出N個Node,并在這N個Node中選擇得分最高的Node即能滿足需求,比如默認找出100個可以通過Predicates(預選階段)的Node即可,最優(yōu)解就在這100個Node中選擇。當然全局最優(yōu)解NodeX也可能不在這100個Node中,但是我們在這100個Node中選擇最優(yōu)的NodeY也能滿足要求。最好的情況是遍歷100個Node就找出這100個Node,也可能遍歷了200個或者300個Node等等,這樣我們可以大大減少計算時間,同時也不會對我們的調度結果產生太大的影響。
局部最優(yōu)的策略是我們與社區(qū)合作共同完成的,這里面還涉及到如何做到公平調度和計算任務優(yōu)化的細節(jié)(詳見PR1,PR2),該項優(yōu)化在Kubernetes 1.12版本中發(fā)布,并作為當前默認調度策略,可以大幅度提升調度性能,尤其在大規(guī)模集群中的提升,效果非常明顯。
kubelet改造
風險可控性
前面提到,穩(wěn)定性和風險可控性對大規(guī)模集群管理來說非常重要。從架構上來看,Kubelet是離真實業(yè)務最近的集群管理組件,我們知道社區(qū)版本的Kubelet對本機資源管理有著很大的自主性,試想一下,如果某個業(yè)務正在運行,但是Kubelet由于出發(fā)了驅逐策略而把這個業(yè)務的容器干掉了會發(fā)生什么?這在我們的集群中是不應該發(fā)生的,所以需要收斂和封鎖Kubelet的自決策能力,它對本機上業(yè)務容器的操作都應該從上層平臺發(fā)起。
容器重啟策略
Kernel升級是日常的運維操作,在通過重啟宿主機來升級Kernel版本的時候,我們發(fā)現宿主機重啟后,上面的容器無法自愈或者自愈后版本不對,這會引發(fā)業(yè)務的不滿,也造成了我們不小的運維壓力。后來我們?yōu)镵ubelet增加了一個重啟策略(Reuse),同時保留了原生重啟策略(Rebuild),保證容器系統(tǒng)盤和數據盤的信息都能保留,宿主機重啟后容器也能自愈。
IP狀態(tài)保持
根據美團點評的網絡環(huán)境,我們自研了CNI插件,并通過基于Pod唯一標識來申請和復用IP。做到了應用IP在Pod遷移和容器重啟之后也能復用,為業(yè)務上線和運維帶來了不少的收益。
限制驅逐策略
我們知道Kubelet擁有節(jié)點自動修復的能力,例如在發(fā)現異常容器或不合規(guī)容器后,會對它們進行驅逐刪除操作,這對于我們來說風險太大,我們允許容器在一些次要因素方面可以不合規(guī)。例如當Kubelet發(fā)現當前宿主機上容器個數比設置的最大容器個數大時,會挑選驅逐和刪除某些容器,雖然正常情況下不會輕易發(fā)生這種問題,但是我們也需要對此進行控制,降低此類風險。
可擴展性
資源調配
在Kubelet的擴展性方面我們增強了資源的可操作性,例如為容器綁定Numa從而提升應用的穩(wěn)定性;根據應用等級為容器設置CPUShare,從而調整調度權重;為容器綁定CPUSet等等。
增強容器
我們打通并增強了業(yè)務對容器的配置能力,支持業(yè)務給自己的容器擴展ulimit、io limit、pid limit、swap等參數的同時也增強容器之間的隔離能力。
應用原地升級
大家都知道,Kubernetes默認只要Pod的關鍵信息有改動,例如鏡像信息,就會出發(fā)Pod的重建和替換,這在生產環(huán)境中代價是很大的,一方面IP和HostName會發(fā)生改變,另一方面頻繁的重建也給集群管理帶來了更多的壓力,甚至還可能導致無法調度成功。為了解決該問題,我們打通了自上而下的應用原地升級功能,即可以動態(tài)高效地修改應用的信息,并能在原地(宿主機)進行升級。
鏡像分發(fā)
鏡像分發(fā)是影響容器擴容時長的一個重要環(huán)節(jié),我們采取了一系列手段來優(yōu)化,保證鏡像分發(fā)效率高且穩(wěn)定:
- 跨Site同步:保證服務器總能從就近的鏡像倉庫拉取到擴容用的鏡像,減少拉取時間,降低跨Site帶寬消耗。
- 基礎鏡像預分發(fā):美團點評的基礎鏡像是構建業(yè)務鏡像的公共鏡像。業(yè)務鏡像層是業(yè)務的應用代碼,通常比基礎鏡像小很多。在容器擴容的時候如果基礎鏡像已經在本地,就只需要拉取業(yè)務鏡像的部分,可以明顯的加快擴容速度。為達到這樣的效果,我們會把基礎鏡像事先分發(fā)到所有的服務器上。
- P2P鏡像分發(fā):基礎鏡像預分發(fā)在有些場景會導致上千個服務器同時從鏡像倉庫拉取鏡像,對鏡像倉庫服務和帶寬帶來很大的壓力。因此我們開發(fā)了鏡像P2P分發(fā)的功能,服務器不僅能從鏡像倉庫中拉取鏡像,還能從其他服務器上獲取鏡像的分片。
資源管理與優(yōu)化
優(yōu)化關鍵技術
- 服務畫像:對應用的CPU、內存、網絡、磁盤和網絡 I/O 容量和負載畫像,了解應用的特征、資源規(guī)格和應用類型以及不同時間對資源的真實使用,然后從服務角度和時間維度進行相關性分析,從而進行整體調度和部署優(yōu)化。
- 親和性和互斥性:哪些應用放在一起使整體計算能力比較少而吞吐能力比較高,它們就存在一定親和性;反之如果應用之間存在資源競爭或相互影響,則它們之間就存在著互斥性。
- 場景優(yōu)先:美團點評的業(yè)務大都是基本穩(wěn)定的場景,所以場景劃分很有必要。例如一類業(yè)務對延遲非常敏感,即使在高峰時刻也不允許有太多的資源競爭產生,這種場景就要避免和減少資源競爭引起的延遲,保證資源充足;一類業(yè)務在有些時間段需要的CPU資源可能會突破配置的上限,我們通過CPU Set化的方式讓這類業(yè)務共享這部分資源,以便能夠突破申請規(guī)格的機器資源限制,不僅服務能夠獲得更高的性能表現,同時也把空閑的資源利用了起來,資源使用率進一步提升。
- 彈性伸縮:應用部署做到流量預測、自動伸縮、基于規(guī)則的高低峰伸縮以及基于機器學習的伸縮機制。
- 精細化資源調配:基于資源共享和隔離技術做到了精細化的資源調度和分配,例如Numa綁定、任務優(yōu)先級、CPU Set化等等。
策略優(yōu)化
調度策略的主要作用在兩方面,一方面是按照既定策略部署目標機器;二是能做到集群資源的排布最優(yōu)。
- 親和性:有調用關系和依賴的應用,或哪些應用放在一起能使整體計算能力比較少、吞吐能力比較高,這些應用間就存在一定親和性。我們的CPU Set化即是利用了對CPU的偏好構建應用的親和性約束,讓不同CPU偏好的應用互補。
- 互斥性:跟親和性相對,主要是對有競爭關系或業(yè)務干擾的應用在調度時盡量分開部署。
- 應用優(yōu)先級:應用優(yōu)先級的劃分是為我們解決資源競爭提供了前提。當前當容器發(fā)生資源競爭時,我們無法決策究竟應該讓誰獲得資源,當有了應用優(yōu)先級的概念后,我們可以做到,在調度層,限制單臺宿主機上重要應用的個數,減少單機的資源競爭,也為單機底層解決資源競爭提供可能;在宿主機層,根據應用優(yōu)先級分配資源,保證重要應用的資源充足,同時也可運行低優(yōu)先級應用。
- 打散性:應用的打散主要是為了容災,在這里分為不同級別的打散。我們提供了不同級別的打散粒度,包括宿主機、Tor、機房、Zone等等。
- 隔離與獨占:這是一類特殊的應用,必須是獨立使用一臺宿主機或虛擬機隔離環(huán)境部署,例如搜索團隊的業(yè)務。
- 特殊資源:特殊資源是滿足某些業(yè)務對GPU、SSD、特殊網卡等特殊硬件需求。
在線集群優(yōu)化
在線集群資源的優(yōu)化問題,不像離線集群那樣可以通過預知資源需求從而達到非常好的效果,由于未來需求的未知性,在線集群很難在資源排布上達到離線集群的效果。針對在線集群的問題,我們從上層調度到底層的資源使用都采取了一系列的優(yōu)化。
- Numa綁定:主要是解決業(yè)務側反饋服務不穩(wěn)定的問題,通過綁定Numa,將同一個應用的CPU和Memory綁定到最合適的Numa Node上,減少跨Node訪問的開銷,提升應用性能。
- CPU Set化:將一組特性互補的應用綁定在同一組CPU上,從而讓他們能充分使用CPU資源。
- 應用錯峰:基于服務畫像數據為應用錯開高峰,減少資源競爭和相互干擾,提升業(yè)務SLA。
- 重調度:資源排布優(yōu)化,用更少的資源提升業(yè)務性能和SLA;解決碎片問題,提升資源的分配率。
- 干擾分析:基于業(yè)務監(jiān)控數據指標和容器信息判斷哪些容器有異常,提升業(yè)務SLA,發(fā)現并處理異常應用。
結束語
當前,在以下幾個方面我們正在積極探索:
- 在線-離線業(yè)務混合部署,進一步提升資源使用效率。
- 智能化調度,業(yè)務流量和資源使用感知調度,提升服務SLA。
- 高性能、強隔離和更安全的容器技術。
作者簡介
國梁,美團點評基礎研發(fā)平臺集群調度中心高級工程師。