日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

当 K8s 集群达到万级规模,阿里巴巴如何解决系统各组件性能问题?

發(fā)布時間:2025/3/20 windows 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 当 K8s 集群达到万级规模,阿里巴巴如何解决系统各组件性能问题? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作者 | 阿里云容器平臺高級技術(shù)專家 曾凡松(逐靈)

本文主要介紹阿里巴巴在大規(guī)模生產(chǎn)環(huán)境中落地 Kubernetes 的過程中,在集群規(guī)模上遇到的典型問題以及對應(yīng)的解決方案,內(nèi)容包含對 etcd、kube-apiserver、kube-controller 的若干性能及穩(wěn)定性增強,這些關(guān)鍵的增強是阿里巴巴內(nèi)部上萬節(jié)點的 Kubernetes 集群能夠平穩(wěn)支撐 2019 年天貓 618 大促的關(guān)鍵所在。

背景

從阿里巴巴最早期的 AI 系統(tǒng)(2013)開始,集群管理系統(tǒng)經(jīng)歷了多輪的架構(gòu)演進,到 2018 年全面的應(yīng)用 Kubernetes ,這期間的故事是非常精彩的,有機會可以單獨給大家做一個分享。這里忽略系統(tǒng)演進的過程,不去討論為什么 Kubernetes 能夠在社區(qū)和公司內(nèi)部全面的勝出,而是將焦點關(guān)注到應(yīng)用 Kubernetes 中會遇到什么樣的問題,以及我們做了哪些關(guān)鍵的優(yōu)化。

在阿里巴巴的生產(chǎn)環(huán)境中,容器化的應(yīng)用超過了 10k 個,全網(wǎng)的容器在百萬的級別,運行在十幾萬臺宿主機上。支撐阿里巴巴核心電商業(yè)務(wù)的集群有十幾個,最大的集群有幾萬的節(jié)點。在落地 Kubernetes 的過程中,在規(guī)模上面臨了很大的挑戰(zhàn),比如如何將 Kubernetes 應(yīng)用到超大規(guī)模的生產(chǎn)級別。

羅馬不是一天就建成的,為了了解 Kubernetes 的性能瓶頸,我們結(jié)合阿里的生產(chǎn)集群現(xiàn)狀,估算了在 10k 個節(jié)點的集群中,預(yù)計會達到的規(guī)模:

  • 20w pods
  • 100w objects

我們基于 Kubemark 搭建了大規(guī)模集群模擬的平臺,通過一個容器啟動多個(50個)Kubemark 進程的方式,使用了 200 個 4c 的容器模擬了 10k 節(jié)點的 kubelet。在模擬集群中運行常見的負(fù)載時,我們發(fā)現(xiàn)一些基本的操作比如 Pod 調(diào)度延遲非常高,達到了驚人的 10s 這一級別,并且集群處在非常不穩(wěn)定的狀態(tài)。

當(dāng) Kubernetes 集群規(guī)模達到 10k 節(jié)點時,系統(tǒng)的各個組件均出現(xiàn)相應(yīng)的性能問題,比如:

  • etcd 中出現(xiàn)了大量的讀寫延遲,并且產(chǎn)生了拒絕服務(wù)的情形,同時因其空間的限制也無法承載 Kubernetes 存儲大量的對象;
  • API Server 查詢 pods/nodes 延遲非常的高,并發(fā)查詢請求可能地址后端 etcd oom;
  • Controller 不能及時從 API Server 感知到在最新的變化,處理的延時較高;當(dāng)發(fā)生異常重啟時,服務(wù)的恢復(fù)時間需要幾分鐘;
  • Scheduler 延遲高、吞吐低,無法適應(yīng)阿里業(yè)務(wù)日常運維的需求,更無法支持大促態(tài)的極端場景。
  • etcd improvements

    為了解決這些問題,阿里云容器平臺在各方面都做了很大的努力,改進 Kubernetes 在大規(guī)模場景下的性能。

    首先是 etcd 層面,作為 Kubernetes 存儲對象的數(shù)據(jù)庫,其對 Kubernetes 集群的性能影響至關(guān)重要。

    • 第一版本的改進,我們通過將 etcd 的數(shù)據(jù)轉(zhuǎn)存到 tair 集群中,提高了 etcd 存儲的數(shù)據(jù)總量。但這個方式有一個顯著的弊端是額外增加的 tair 集群,增加的運維復(fù)雜性對集群中的數(shù)據(jù)安全性帶來了很大的挑戰(zhàn),同時其數(shù)據(jù)一致性模型也并非基于 raft 復(fù)制組,犧牲了數(shù)據(jù)的安全性。

    • 第二版本的改進,我們通過將 API Server 中不同類型的對象存儲到不同的 etcd 集群中。從 etcd 內(nèi)部看,也就對應(yīng)了不同的數(shù)據(jù)目錄,通過將不同目錄的數(shù)據(jù)路由到不同的后端 etcd 中,從而降低了單個 etcd 集群中存儲的數(shù)據(jù)總量,提高了擴展性。

    • 第三版本的改進,我們深入研究了 etcd 內(nèi)部的實現(xiàn)原理,并發(fā)現(xiàn)了影響 etcd 擴展性的一個關(guān)鍵問題在底層 bbolt db 的 page 頁面分配算法上:隨著 etcd 中存儲的數(shù)據(jù)量的增長,bbolt db 中線性查找“連續(xù)長度為 n 的 page 存儲頁面”的性能顯著下降。

    為了解決該問題,我們設(shè)計了基于 segregrated hashmap 的空閑頁面管理算法,hashmap 以連續(xù) page 大小為 key, 連續(xù)頁面起始 page id 為 value。通過查這個 segregrated hashmap 實現(xiàn) O(1) 的空閑 page 查找,極大地提高了性能。在釋放塊時,新算法嘗試和地址相鄰的 page 合并,并更新 segregrated hashmap。更詳細(xì)的算法分析可以見已發(fā)表在 CNCF 博客的博文:

    https://www.cncf.io/blog/2019/05/09/performance-optimization-of-etcd-in-web-scale-data-scenario/

    通過這個算法改進,我們可以將 etcd 的存儲空間從推薦的 2GB 擴展到 100GB,極大的提高了 etcd 存儲數(shù)據(jù)的規(guī)模,并且讀寫無顯著延遲增長。除此之外,我們也和谷歌工程師協(xié)作開發(fā)了 etcd raft learner(類 zookeeper observer)/fully concurrent read 等特性,在數(shù)據(jù)的安全性和讀寫性能上進行增強。這些改進已貢獻開源,將在社區(qū) etcd 3.4 版本中發(fā)布。

    API Server improvements

    Efficient node heartbeats

    在 Kubernetes 集群中,影響其擴展到更大規(guī)模的一個核心問題是如何有效的處理節(jié)點的心跳。在一個典型的生產(chǎn)環(huán)境中 (non-trival),kubelet 每 10s 匯報一次心跳,每次心跳請求的內(nèi)容達到 15kb(包含節(jié)點上數(shù)十計的鏡像,和若干的卷信息),這會帶來兩大問題:

  • 心跳請求觸發(fā) etcd 中 node 對象的更新,在 10k nodes 的集群中,這些更新將產(chǎn)生近 1GB/min 的 transaction logs(etcd 會記錄變更歷史);
  • API Server 很高的 CPU 消耗,node 節(jié)點非常龐大,序列化/反序列化開銷很大,處理心跳請求的 CPU 開銷超過 API Server CPU 時間占用的 80%。
  • 為了解決這個問題,Kubernetes 引入了一個新的 build-in Lease API ,將與心跳密切相關(guān)的信息從 node 對象中剝離出來,也就是上圖中的 Lease 。原本 kubelet 每 10s 更新一次 node 對象升級為:

  • 每 10s 更新一次 Lease 對象,表明該節(jié)點的存活狀態(tài),Node Controller 根據(jù)該 Lease 對象的狀態(tài)來判斷節(jié)點是否存活;
  • 處于兼容性的考慮,降低為每 60s 更新一次 node 對象,使得 Eviction_ _Manager 等可以繼續(xù)按照原有的邏輯工作。
  • 因為 Lease 對象非常小,因此其更新的代價遠(yuǎn)小于更新 node 對象。kubernetes 通過這個機制,顯著的降低了 API Server 的 CPU 開銷,同時也大幅減小了 etcd 中大量的 transaction logs,成功將其規(guī)模從 1000 擴展到了幾千個節(jié)點的規(guī)模,該功能在社區(qū) Kubernetes-1.14 中已經(jīng)默認(rèn)啟用。

    API Server load balancing

    在生產(chǎn)集群中,出于性能和可用性的考慮,通常會部署多個節(jié)點組成高可用 Kubernetes 集群。但在高可用集群實際的運行中,可能會出現(xiàn)多個 API Server 之間的負(fù)載不均衡,尤其是在集群升級或部分節(jié)點發(fā)生故障重啟的時候。這給集群的穩(wěn)定性帶來了很大的壓力,原本計劃通過高可用的方式分?jǐn)?API Server 面臨的壓力,但在極端情況下所有壓力又回到了一個節(jié)點,導(dǎo)致系統(tǒng)響應(yīng)時間變長,甚至擊垮該節(jié)點繼而導(dǎo)致雪崩。

    下圖為壓測集群中模擬的一個 case,在三個節(jié)點的集群,API Server 升級后所有的壓力均打到了其中一個 API Server 上,其 CPU 開銷遠(yuǎn)高于其他兩個節(jié)點。

    解決負(fù)載均衡問題,一個自然的思路就是增加 load balancer。前文的描述中提到,集群中主要的負(fù)載是處理節(jié)點的心跳,那我們就在 API Server 與 kubelet 中間增加 lb,有兩個典型的思路:

  • API Server 測增加 lb,所有的 kubelets 連接 lb,典型的云廠商交付的 Kubernetes 集群,就是這一模式;
  • kubelet 測增加 lb,由 lb 來選擇 API Server。

  • 通過壓測環(huán)境驗證發(fā)現(xiàn),增加 lb 并不能很好的解決上面提到的問題,我們必須要深入理解 Kubernetes 內(nèi)部的通信機制。深入到 Kubernetes 中研究發(fā)現(xiàn),為了解決 tls 連接認(rèn)證的開銷,Kubernetes 客戶端做了很多的努力確保“盡量復(fù)用同樣的 tls 連接”,大多數(shù)情況下客戶端 watcher 均工作在下層的同一個 tls 連接上,僅當(dāng)這個連接發(fā)生異常時,才可能會觸發(fā)重連繼而發(fā)生 API Server 的切換。其結(jié)果就是我們看到的,當(dāng) kubelet 連接到其中一個 API Server 后,基本上是不會發(fā)生負(fù)載切換。為了解決這個問題,我們進行了三個方面的優(yōu)化:

  • API Server:認(rèn)為客戶端是不可信的,需要保護自己不被過載的請求擊潰。當(dāng)自身負(fù)載超過一個閾值時,發(fā)送 409 - too many requests 提醒客戶端退避;當(dāng)自身負(fù)載超過一個更高的閾值時,通過關(guān)閉客戶端連接拒絕請求;
  • Client:在一個時間段內(nèi)頻繁的收到 409 時,嘗試重建連接切換 API Server;定期地重建連接切換 API Server 完成洗牌;
  • 運維層面,我們通過設(shè)置 maxSurge=3 的方式升級 API Server,避免升級過程帶來的性能抖動。
  • 如上圖左下角監(jiān)控圖所示,增強后的版本可以做到 API Server 負(fù)載基本均衡,同時在顯示重啟兩個節(jié)點(圖中抖動)時,能夠快速的自動恢復(fù)到均衡狀態(tài)。

    List-Watch & Cacher

    List-Watch 是 Kubernetes 中 Server 與 Client 通信最核心一個機制,etcd 中所有對象及其更新的信息,API Server 內(nèi)部通過 Reflector 去 watch etcd 的數(shù)據(jù)變化并存儲到內(nèi)存中,controller/kubelets 中的客戶端也通過類似的機制去訂閱數(shù)據(jù)的變化。

    在 List-Watch 機制中面臨的一個核心問題是,當(dāng) Client 與 Server 之間的通信斷開時,如何確保重連期間的數(shù)據(jù)不丟,這在 Kubernetes 中通過了一個全局遞增的版本號 resourceVersion 來實現(xiàn)。如下圖所示 Reflector 中保存這當(dāng)前已經(jīng)同步到的數(shù)據(jù)版本,重連時 Reflector 告知 Server 自己當(dāng)前的版本(5),Server 根據(jù)內(nèi)存中記錄的最近變更歷史計算客戶端需要的數(shù)據(jù)起始位置(7)。

    這一切看起來十分簡單可靠,但是…

    在 API Server 內(nèi)部,每個類型的對象會存儲在一個叫做 storage 的對象中,比如會有:

  • Pod Storage
  • Node Storage
  • Configmap Storage
  • 每個類型的 storage 會有一個有限的隊列,存儲對象最近的變更,用于支持 watcher 一定的滯后(重試等場景)。一般來說,所有類型的類型共享一個遞增版本號空間(1, 2, 3, …, n),也就是如上圖所示,pod 對象的版本號僅保證遞增不保證連續(xù)。Client 使用 List-Watch 機制同步數(shù)據(jù)時,可能僅關(guān)注 pods 中的一部分,最典型的 kubelet 僅關(guān)注和自己節(jié)點相關(guān)的 pods,如上圖所示,某個 kubelet 僅關(guān)注綠色的 pods (2, 5)。

    因為 storage 隊列是有限的(FIFO),當(dāng) pods 的更新時隊列,舊的變更就會從隊列中淘汰。如上圖所示,當(dāng)隊列中的更新與某個 Client 無關(guān)時,Client 進度仍然保持在 rv=5,如果 Client 在 5 被淘汰后重連,這時候 API Server 無法判斷 5 與當(dāng)前隊列最小值(7)之間是否存在客戶端需要感知的變更,因此返回 Client too old version err 觸發(fā) Client 重新 list 所有的數(shù)據(jù)。為了解決這個問題,Kubernetes 引入 Watch bookmark 機制:

    bookmark 的核心思想概括起來就是在 Client 與 Server 之間保持一個“心跳”,即使隊列中無 Client 需要感知的更新,Reflector 內(nèi)部的版本號也需要及時的更新。如上圖所示,Server 會在合適的適合推送當(dāng)前最新的 rv=12 版本號給 Client,使得 Client 版本號跟上 Server 的進展。bookmark 可以將 API Server 重啟時需要重新同步的事件降低為原來的 3%(性能提高了幾十倍),該功能有阿里云容器平臺開發(fā),已經(jīng)發(fā)布到社區(qū) Kubernetes-1.15 版本中。

    Cacher & Indexing

    除 List-Watch 之外,另外一種客戶端的訪問模式是直接查詢 API Server,如下圖所示。為了保證客戶端在多個 API Server 節(jié)點間讀到一致的數(shù)據(jù),API Server 會通過獲取 etcd 中的數(shù)據(jù)來支持 Client 的查詢請求。從性能角度看,這帶來了幾個問題:

  • 無法支持索引,查詢節(jié)點的 pod 需要先獲取集群中所有的 pod,這個開銷是巨大的;
  • 因為 etcd 的 request-response 模型,單次請求查詢過大的數(shù)據(jù)會消耗大量的內(nèi)存,通常情況下 API Server 與 etcd 之間的查詢會限制請求的數(shù)據(jù)量,并通過分頁的方式來完成大量的數(shù)據(jù)查詢,分頁帶來的多次的 round trip 顯著降低了性能;
  • 為了確保一致性,API Server 查詢 etcd 均采用了 Quorum read ,這個查詢開銷是集群級別,無法擴展的。
  • 為了解決這個問題,我們設(shè)計了 API Server 與 etcd 的數(shù)據(jù)協(xié)同機制,確保 Client 能夠通過 API Server 的 cache 獲取到一致的數(shù)據(jù),其原理如下圖所示,整體工作流程如下:

  • t0 時刻 Client 查詢 API Server;
  • API Server 請求 etcd 獲取當(dāng)前的數(shù)據(jù)版本 rv@t0;
  • API Server 請求進度的更新,并等待 Reflector 數(shù)據(jù)版本達到 rv@t0;
  • 通過 cache 響應(yīng)用戶的請求。
  • 這個方式并未打破 Client 的一致性模型(感興趣的可以自己論證一下),同時通過 cache 響應(yīng)用戶請求時我們可以靈活的增強查詢能力,比如支持 namespace nodename/labels 索引。該增強大幅提高了 API Server 的讀請求處理能力,在萬臺規(guī)模集群中典型的 describe node 的時間從原來的 5s 降低到 0.3s(觸發(fā)了 node name 索引),其他如 get nodes 等查詢操作的效率也獲得了成倍的增長。

    Controller failover

    在 10k node 的生產(chǎn)集群中,Controller 中存儲著近百萬的對象,從 API Server 獲取這些對象并反序列化的開銷是無法忽略的,重啟 Controller 恢復(fù)時可能需要花費幾分鐘才能完成這項工作,這對于阿里巴巴規(guī)模的企業(yè)來說是不可接受的。為了減小組件升級對系統(tǒng)可用性的影響,我們需要盡量的減小 controller 單次升級對系統(tǒng)的中斷時間,這里通過如下圖所示的方案來解決這個問題:

  • 預(yù)啟動備 controller informer ,提前加載 controller 需要的數(shù)據(jù);
  • 主 controller 升級時,會主動釋放 Leader Lease,觸發(fā)備立即接管工作。
  • 通過這個方案,我們將 controller 中斷時間降低到秒級別(升級時 < 2s),即使在異常宕機時,備僅需等待 leader lease 的過期(默認(rèn) 15s),無需要花費幾分鐘重新同步數(shù)據(jù)。通過這個增強,顯著的降低了 controller MTTR,同時降低了 controller 恢復(fù)時對 API Server 的性能沖擊。該方案同樣適用于 scheduler。

    Customized scheduler

    由于歷史原因,阿里巴巴的調(diào)度器采用了自研的架構(gòu),因時間的關(guān)系本次分享并未展開調(diào)度器部分的增強。這里僅分享兩個基本的思路,如下圖所示:

  • Equivalence classes:典型的用戶擴容請求為一次擴容多個容器,因此我們通過將 pending 隊列中的請求劃分等價類的方式,實現(xiàn)批處理,顯著的降低 Predicates/Priorities 的次數(shù);
  • Relaxed randomization:對于單次的調(diào)度請求,當(dāng)集群中的候選節(jié)點非常多時,我們并不需要評估集群中全部節(jié)點,在挑選到足夠的節(jié)點后即可進入調(diào)度的后續(xù)處理(通過犧牲求解的精確性來提高調(diào)度性能)。
  • 總結(jié)

    阿里巴巴通過一系列的增強與優(yōu)化,成功將 Kubernetes 應(yīng)用到生產(chǎn)環(huán)境并達到了單集群 10000 節(jié)點的超大規(guī)模,具體包括:

  • 通過將索引和數(shù)據(jù)分離、數(shù)據(jù) shard 等方式提高 etcd 存儲容量,并最終通過改進 etcd 底層 bbolt db 存儲引擎的塊分配算法,大幅提高了 etcd 在存儲大數(shù)據(jù)量場景下的性能,通過單 etcd 集群支持大規(guī)模 Kubernetes 集群,大幅簡化了整個系統(tǒng)架構(gòu)的復(fù)雜性;
  • 通過落地 Kubernetes 輕量級心跳、改進 HA 集群下多個 API Server 節(jié)點的負(fù)載均衡、ListWatch 機制中增加 bookmark、通過索引與 Cache 的方式改進了 Kubernetes 大規(guī)模集群中最頭疼的 List 性能瓶頸,使得穩(wěn)定的運行萬節(jié)點集群成為可能;
  • 通過熱備的方式大幅縮短了 controller/scheduler 在主備切換時的服務(wù)中斷時間,提高了整個集群的可用性;
  • 阿里巴巴自研調(diào)度器在性能優(yōu)化上最有效的兩個思路:等價類處理以及隨機松弛算法。
  • 通過這一系列功能增強,阿里巴巴成功將內(nèi)部最核心的業(yè)務(wù)運行在上萬節(jié)點的 Kubernetes 集群之上,并經(jīng)歷了 2019 年天貓 618 大促的考驗。

    作者簡介:

    曾凡松(花名:逐靈),阿里云云原生應(yīng)用平臺高級技術(shù)專家。

    有豐富的分布式系統(tǒng)設(shè)計研發(fā)經(jīng)驗。在集群資源調(diào)度這一領(lǐng)域,曾負(fù)責(zé)的自研調(diào)度系統(tǒng)管理了數(shù)十萬規(guī)模的節(jié)點,在集群資源調(diào)度、容器資源隔離、不同工作負(fù)載混部等方面有豐富的實踐經(jīng)驗。當(dāng)前主要負(fù)責(zé) Kubernetes 在阿里內(nèi)部的規(guī)模化落地,將 Kubernetes 應(yīng)用于阿里內(nèi)部的最核心電商業(yè)務(wù),提高了應(yīng)用發(fā)布效率及集群資源利用率,并穩(wěn)定支撐了 2018 雙十一 及 2019 618 大促。

    ** “ 阿里巴巴云原生微信公眾號(ID:Alicloudnative)關(guān)注微服務(wù)、Serverless、容器、Service Mesh 等技術(shù)領(lǐng)域、聚焦云原生流行技術(shù)趨勢、云原生大規(guī)模的落地實踐,做最懂云原生開發(fā)者的技術(shù)公眾號。”**

    總結(jié)

    以上是生活随笔為你收集整理的当 K8s 集群达到万级规模,阿里巴巴如何解决系统各组件性能问题?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。