做爲國內領先的生活服務平臺,美團點評不少業務都具備很是顯著、規律的」高峯「和」低谷「特徵。尤爲遇到節假日或促銷活動,流量還會在短期內出現爆發式的增加。這對集羣中心的資源彈性和可用性有很是高的要求,同時也會使系統在支撐業務流量時的複雜度和成本支出呈現指數級增加。而咱們須要作的,就是利用有限的資源最大化地提高集羣的吞吐能力,以保障用戶體驗。node
本文將介紹美團點評Kubernetes集羣管理與使用實踐,包括美團點評集羣管理與調度系統介紹、Kubernetes管理與實踐、Kubernetes優化與改造以及資源管理與優化等。git
美團點評在集羣管理和資源優化這條道路上已經「摸爬滾打」多年。2013年,開始構建基於傳統虛擬化技術的資源交付方式;2015年7月,開始創建完善的集羣管理與調度系統——HULK,目標是推進美團點評服務容器化;2016年,完成基於Docker容器技術自研實現了彈性伸縮能力,來提高交付速度和應對快速擴縮容的需求,實現彈性擴容、縮容,提高資源利用率,提高業務運維效率,合理有效的下降企業IT運維成本;2018年,開始基於Kubernetes來進行資源管理和調度,進一步提高資源的使用效率。github
最初,美團點評經過基於Docker容器技術自研實現了彈性伸縮能力,主要是爲了解決基於虛擬化技術的管理及部署機制在應對服務快速擴容、縮容需求時存在的諸多不足。例如資源實例建立慢、沒法統一運行環境、實例部署和交付流程長、資源回收效率低、彈性能力差等等。通過調研與測試,結合業界的實踐經驗,咱們決定基於Docker容器技術自研集羣管理與調度系統,有效應對快速擴縮容的需求,提高資源的利用效率。咱們把它叫作"綠巨人"——HULK,這個階段能夠看做是HULK1.0。算法
以後,在生產環境中通過不斷摸索和嘗試,咱們逐漸意識到,僅僅知足於集羣的彈性伸縮能力是不夠的,成本和效率確定是將來必將面臨且更爲棘手的問題。咱們吸收了2年來HULK 1.0的開發和運維經驗,在架構和支撐系統層面作了進一步優化和改進,並藉助於生態和開源的力量來爲HULK賦能,即引入了開源的集羣管理與調度系統Kubernetes,指望能進一步提高集羣管理、運行的效率和穩定性,同時下降資源成本。因此咱們從自研平臺轉向了開源的Kubernetes系統,並基於Kubernetes系統打造了更加智能化的集羣管理與調度系統——HULK2.0。安全
在架構層面,HULK2.0如何能與上層業務和底層Kubernetes平臺更好地分層和解耦,是咱們在設計之初就優先考慮的問題。咱們指望它既要能對業務使用友好,又能最大限度地發揮Kubernetes的調度能力,使得業務層和使用方毋需關注資源關係細節,所求即所得;同時使發佈、配置、計費、負載等邏輯層與底層的Kubernetes平臺解耦分層,並保持兼容原生Kubernetes API來訪問Kubernetes集羣。從而能夠藉助於統一的、主流的、符合業界規範的標準,來解決美團點評基礎架構面臨的複雜的、多樣的、不統一的管理需求。性能優化
自上而下來看,美團集羣管理與調度平臺面向全公司服務,有各個主要業務線、統一的OPS平臺以及Portal平臺,HULK不可能針對每一個平臺定製化接口和解決方案,因此須要將多樣的業務和需求抽象收斂,最終統一經過HULK API來屏蔽HULK系統的細節,作到HULK與上層業務方的解耦。HULK API是對業務層和資源需求的抽象,是外界訪問HULK的惟一途徑。服務器
解決了上層的問題後,咱們再來看與下層Kubernetes平臺的解耦。HULK接到上層資源請求後,首先要進行一系列的初始化工做,包括參數校驗、資源餘量、IP和Hostname的分配等等,以後向Kubernetes平臺實際申請分配機器資源,最終將資源交付給用戶,Kubernetes API進一步將資源需求收斂和轉換,讓咱們能夠藉助於Kubernetes的資源管理優點。Kubernetes API旨在收斂HULK的資源管理邏輯並與業界主流對齊。此外,由於徹底兼容Kubernetes API,可讓咱們藉助社區和生態的力量,共同建設和探索。網絡
能夠看到,HULK API和Kubernetes API將咱們整個系統分爲三層,這樣可讓每一層都專一於各自的模塊。架構
爲何會選擇Kubernetes呢?Kubernetes並非市面上惟一的集羣管理平臺(其餘如Docker Swarm或Mesos),之因此選擇它,除了它自己優秀的架構設計,咱們更加看重的是Kubernetes提供的不是一個解決方案,而是一個平臺和一種能力。這種能力可以讓咱們真正基於美團點評的實際狀況來擴展,同時可以依賴和複用多年來的技術積累,給予咱們更多選擇的自由,包括咱們能夠快速地部署應用程序,而無須面對傳統平臺所具備的風險,動態地擴展應用程序以及更好的資源分配策略。運維
Kubernetes集羣做爲整個HULK集羣資源管理與平臺的基礎,需求是穩定性和可擴展性,風險可控性和集羣吞吐能力。
咱們有集羣在使用1.6版本的調度器,隨着集羣規模的不斷增加,舊版本的Kubernetes調度器(1.10以前版本)在性能和穩定性的問題逐漸凸顯,因爲調度器的吞吐量低,致使業務擴容超時失敗,在規模近3000臺的集羣上,一次Pod的調度耗時在5s左右。Kubernetes的調度器是隊列化的調度器模型,一旦擴容高峯等待的Pod數量過多就會致使後面Pod的擴容超時。爲此,咱們對調度器性能進行了大幅度的優化,並取得了很是明顯的提高,根據咱們的實際生產環境驗證,性能比優化前提高了400%以上。
Kubernetes調度器工做模型以下:
(kubernetes調度器,圖片來源於網絡)
一次調度過程在判斷一個 Node是否可做爲目標機器時,主要分爲三個階段:
經過深刻分析調度過程能夠發現,調度器在預選階段即便已經知道當前 Node不符合某個過濾條件仍然會繼續判斷後續的過濾條件是否符合。試想若是有上萬臺 Node節點,這些判斷邏輯會浪費不少計算時間,這也是調度器性能低下的一個重要因素。
爲此,咱們提出了「預選失敗中斷機制」,即一旦某個預選條件不知足,那麼該 Node即被當即放棄,後面的預選條件再也不作判斷計算,從而大大減小了計算量,調度性能也大大提高。以下圖所示:
咱們把該項優化貢獻給了 Kubernetes社區(詳見PR),增長了 alwaysCheckAllPredicates 策略選項,並在 Kubernetes1.10版本發佈並開始做爲默認的調度策略,固然你也能夠經過設置alwaysCheckAllPredicates=true使用原先的調度策略。
在實際測試中,調度器至少能夠提高40%的性能,若是你目前在使用的Kube-scheduler的版本低於1.10,那麼建議你嘗試升級到新的版本。
對於優化問題尤爲是最優化問題,咱們總但願找到全局最優的解或策略,可是當問題的複雜度太高,要考慮的因素和處理的信息量過多時,咱們每每會傾向於接受局部最優解,由於局部最優解的質量不必定都是差的。尤爲是當咱們有肯定的評判標準,同時標明得出的解是能夠接受的話,一般會接收局部最優的結果。這樣,從成本、效率等多方面考慮,纔是咱們在實際工程中真正會採起的策略。
(圖片來源於網絡)
當前調度策略中,每次調度調度器都會遍歷集羣中全部的Node,以便找出最優的節點,這在調度領域稱之爲BestFit算法。可是在生產環境中,咱們是選取最優Node仍是次優Node,其實並無特別大的區別和影響,有時候咱們仍是會避免選取最優的Node(例如咱們集羣爲了解決新上線機器後頻繁在該機器上建立應用的問題,就將最優解隨機化)。換句話說,找出局部最優解就能知足需求。
假設集羣一共1000個Node,一次調度過程PodA,這其中有700個Node都能經過Predicates(預選階段),那麼咱們就會把全部的Node遍歷並找出這700個Node,而後通過得分排序找出最優的Node節點NodeX。可是採用局部最優算法,即咱們認爲只要能找出N個Node,並在這N個Node中選擇得分最高的Node即能知足需求,好比默認找出100個能夠經過Predicates(預選階段)的Node便可,最優解就在這100個Node中選擇。固然全局最優解NodeX也可能不在這100個Node中,可是咱們在這100個Node中選擇最優的NodeY也能知足要求。最好的狀況是遍歷100個Node就找出這100個Node,也可能遍歷了200個或者300個Node等等,這樣咱們能夠大大減小計算時間,同時也不會對咱們的調度結果產生太大的影響。
局部最優的策略是咱們與社區合做共同完成的,這裏面還涉及到如何作到公平調度和計算任務優化的細節(詳見PR1,PR2),該項優化在Kubernetes 1.12版本中發佈,並做爲當前默認調度策略,能夠大幅度提高調度性能,尤爲在大規模集羣中的提高,效果很是明顯。
前面提到,穩定性和風險可控性對大規模集羣管理來講很是重要。從架構上來看,Kubelet是離真實業務最近的集羣管理組件,咱們知道社區版本的Kubelet對本機資源管理有着很大的自主性,試想一下,若是某個業務正在運行,可是Kubelet因爲出發了驅逐策略而把這個業務的容器幹掉了會發生什麼?這在咱們的集羣中是不該該發生的,因此須要收斂和封鎖Kubelet的自決策能力,它對本機上業務容器的操做都應該從上層平臺發起。
容器重啓策略
Kernel升級是平常的運維操做,在經過重啓宿主機來升級Kernel版本的時候,咱們發現宿主機重啓後,上面的容器沒法自愈或者自愈後版本不對,這會引起業務的不滿,也形成了咱們不小的運維壓力。後來咱們爲Kubelet增長了一個重啓策略(Reuse),同時保留了原生重啓策略(Rebuild),保證容器系統盤和數據盤的信息都能保留,宿主機重啓後容器也能自愈。
IP狀態保持
根據美團點評的網絡環境,咱們自研了CNI插件,並經過基於Pod惟一標識來申請和複用IP。作到了應用IP在Pod遷移和容器重啓以後也能複用,爲業務上線和運維帶來了很多的收益。
限制驅逐策略
咱們知道Kubelet擁有節點自動修復的能力,例如在發現異常容器或不合規容器後,會對它們進行驅逐刪除操做,這對於咱們來講風險太大,咱們容許容器在一些次要因素方面能夠不合規。例如當Kubelet發現當前宿主機上容器個數比設置的最大容器個數大時,會挑選驅逐和刪除某些容器,雖然正常狀況下不會輕易發生這種問題,可是咱們也須要對此進行控制,下降此類風險。
資源調配
在Kubelet的擴展性方面咱們加強了資源的可操做性,例如爲容器綁定Numa從而提高應用的穩定性;根據應用等級爲容器設置CPUShare,從而調整調度權重;爲容器綁定CPUSet等等。
加強容器
咱們打通並加強了業務對容器的配置能力,支持業務給本身的容器擴展ulimit、io limit、pid limit、swap等參數的同時也加強容器之間的隔離能力。
應用原地升級
你們都知道,Kubernetes默認只要Pod的關鍵信息有改動,例如鏡像信息,就會出發Pod的重建和替換,這在生產環境中代價是很大的,一方面IP和HostName會發生改變,另外一方面頻繁的重建也給集羣管理帶來了更多的壓力,甚至還可能致使沒法調度成功。爲了解決該問題,咱們打通了自上而下的應用原地升級功能,便可以動態高效地修改應用的信息,並能在原地(宿主機)進行升級。
鏡像分發
鏡像分發是影響容器擴容時長的一個重要環節,咱們採起了一系列手段來優化,保證鏡像分發效率高且穩定:
調度策略的主要做用在兩方面,一方面是按照既定策略部署目標機器;二是能作到集羣資源的排布最優。
在線集羣資源的優化問題,不像離線集羣那樣能夠經過預知資源需求從而達到很是好的效果,因爲將來需求的未知性,在線集羣很難在資源排布上達到離線集羣的效果。針對在線集羣的問題,咱們從上層調度到底層的資源使用都採起了一系列的優化。
當前,在如下幾個方面咱們正在積極探索:
國樑,美團點評基礎研發平臺集羣調度中心高級工程師。
美團點評基礎研發平臺集羣調度中心,致力於打造高效的業界領先的集羣管理與調度平臺,經過企業級集羣管理平臺建設業界領先的雲化解決方案,提升集羣管理能力和穩定性,同時下降IT成本,加速公司的創新發展。同時隨着Kubernetes已經成爲業界的事實標準,美團點評也在逐步擁抱社區,參與開源而且在集羣調度領域已經取得很大進展,也期待和業界同仁一塊兒努力,共同提升集羣管理和調度能力,下降整個行業的IT成本,協同創新發展。美團點評基礎研發平臺長期招聘集羣管理與調度、彈性調度、Kubernetes以及Linux內核方面的人才,有興趣的同窗能夠發送簡歷到tech@meituan.com。