Rancher首席架構師解讀Fleet:它何以管理百萬集群?


作者簡介

Darren Shepherd,Rancher Labs聯合創始人及首席架構師。在加入Rancher之前,Darren是Citrix的高級首席工程師,他在那里從事CloudStack、OpenStack、Docker的工作,並構建下一代基礎設施編排技術。在加入Citrix之前,Darren曾在GoDaddy工作,他設計並領導一個團隊實施公有和私有IaaS雲。

本文轉自Rancher Labs

2020年年初,Rancher開源了海量集群管理項目Fleet,為大量的Kubernetes集群提供集中的GitOps式管理。Fleet最重要的目標是能夠管理100萬個分布於不同地理位置的集群。當我們設計Fleet架構時,我們希望使用標准的Kubernetes controller架構。這意味着我們可以擴展Kubernetes的數量比之前要多很多。在本文中,我將介紹Fleet的架構、我們用於測試擴展規模的方法和我們的發現。

為什么是100萬個集群?

隨着K3s用戶量爆發式增長(目前Github Star已經超過15,000),邊緣Kubernetes也開始迅猛發展。一些企業已經采用了邊緣部署模型,其中每個設備都是單節點集群。或者你可能會看到使用3個節點的集群來提供高可用性(HA)。關鍵點在於我們需要處理的是大量小型集群,而不是一個有很多節點的大型集群。現如今,幾乎任何地方的工程師都在使用Linux,他們都希望使用Kubernetes來管理工作負載。雖然大多數K3s的邊緣部署少於10,000個節點,但達到100萬個節點並非不可能。而Fleet將滿足你的規模擴展要求。

Fleet架構

Fleet架構的關鍵部分如下:

  • Fleet使用兩階段pull方法

  • Fleet是一組由標准K8S API交互驅動的K8S Controller

  • Fleet agent不需要一直保持連接

  • Fleet agent本身是另一組Kubernetes controller

要從git中進行部署,Fleet Manager首先要復制並存儲git中的內容,然后Fleet manager決定需要使用git中的內容更新哪個集群,並創建部署記錄供agent讀取。當agent可以讀取時,agent將check in以讀取部署集群,部署新的資源並報告狀態。

擴展規模測試方法

我們使用兩種方法來模擬100萬個集群。首先,我們部署了一組大型VM(m5ad.24xlarge - 384 GiB RAM)。每個VM使用k3d運行10個K3s集群。然后這10個集群每個都運行750個agent,每個agent都代表着一個下游的集群。總的來說,每個VM模擬7500個集群。平均來看,部署一個VM、在Fleet注冊所有集群並達到穩定狀態大約需要花費40分鍾。在兩天的時間里,我們以這種方式啟動虛擬機,直到達到10萬個集群。在最初的10萬個集群中,我們發現了大部分的擴展問題。在解決了這些問題之后,擴展變得相當可預測。以這一速度,模擬剩下的90萬個集群將會花費很長的時間以及相當可觀的資金。

然后,我們采用第二種方法:運行一個模擬器,它可以執行100萬個集群會進行的所有API調用,而不需要下游的Kubernetes集群或部署Kubernetes資源。取而代之的是,模擬器進行API調用以注冊新集群、發現新部署並報告它們的成功狀態。使用這種方法,我們在一天內實現了從0到100萬個模擬集群。

Fleet manager是一個運行在Kubernetes集群上的controller,運行在3個大型虛擬機(m5ad.24xlarge - 384 GiB RAM)和一個RDS(db.m5.24xlarge)實例上。實際上,我們使用K3s來運行Fleet Manager集群。我們這樣做是因為Kine已經在其中集成了。我將在后面解釋什么是Kine以及為什么使用它。盡管K3s針對的是小規模的集群,但它可能是最容易大規模運行的Kubernetes發行版,我們使用它是因為其簡單易用。值得注意的是,在EKS這樣的托管提供商上,我們無法大規模運行Fleet,稍后我會解釋這一點。

發現1:調整服務賬戶和費率限制

我們遇到的第一個問題完全出乎意料。當一個Fleet agent注冊到Fleet Manager時,它會使用一個臨時的集群注冊令牌(token)。然后,該令牌被用來為該集群/agent創建新的身份和憑證。集群注冊令牌和該agent的憑證都是服務賬戶。我們注冊集群的速度受到controller-manager為服務賬戶創建令牌的速度的限制。經過研究,我們發現我們可以修改controller-manager的默認設置來提高我們創建服務賬戶的速度(-concurrent-serviceaccount-token-syncs=100)和每秒API請求的總體數量(-kube-api-qps=10000)。

發現2:etcd不能在此規模下運行

Fleet是作為Kubernetes Controller編寫的。因此,將Fleet擴展到100萬個集群意味着要在Kubernetes中管理數千萬個對象。正如我們所了解的,etcd並沒有能力管理這么大的數據量。Etcd的主要空間有8GB的限制,默認設置為2GB。關鍵空間包括當前的值和它們之前尚未被垃圾收集的值。在Fleet中,一個簡單的集群對象大約需要6KB。對於100萬個集群,我們至少需要6GB。但是一個集群一般包含10個左右的Kubernetes對象,加上每個部署一個對象。所以在實際操作中,我們更有可能需要超過100萬個集群10倍的內存空間。

為了繞過etcd的限制,我們使用了Kine,這使得使用傳統的RDBMS運行任何Kubernetes發行版成為可能。在這個規模測試中,我們運行了RDS db.m5.24xlarge實例。我們沒有嘗試對數據庫進行適當的大小調整,而是從最大的m5實例開始。在測試結束時,我們在Kine中擁有大約2000萬個對象。這意味着以這種規模運行Fleet不能在EKS這樣的托管提供商上進行,因為它是基於etcd的,也不會為我們的需求提供足夠可擴展的數據存儲。

這個測試似乎並沒有把數據庫push得很厲害。誠然,我們使用了一個非常大的數據庫,但很明顯我們還有很多垂直擴展的空間。單條記錄的插入和查找繼續以可接受的速度進行。我們注意到,隨機列出大量對象(最多一萬個)將會花費30秒到一分鍾的時間。但一般來說,這些查詢會在不到1秒的時間內完成,或者在非常粗暴的測試下5秒也可以完成。因為這些耗時很長的查詢發生在緩存重載期間,所以對系統整體影響不大,我們將在后面討論。盡管這些緩慢的查詢並沒有對Fleet造成明顯的影響,但我們還是需要進一步調查為什么會出現這種情況。

發現3:增加監控緩存大小

當controller加載緩存時,首先會列出所有對象,然后從列表的修訂版開始監控。如果有非常高的變化率並且列出對象花費了很長的時間,那么你很容易陷入這樣的情況:你完成了列表但無法啟動監控,因為API Server的監控緩存中沒有這個修訂版,或者已經在etcd中被壓縮了。作為一個變通辦法,我們將監控緩存設置為一個非常高的值(–default-watch-cache-size=10000000)。理論上,我們認為我們會遇到Kine的壓實問題(compact),但我們沒有,這需要進一步調查。一般來說,Kine在壓實(compact)的頻率上要低很多。但在這種情況下,我們懷疑我們添加記錄的速度超過了Kine壓實的速度。這並不糟糕。我們並不希望堅持要保持一致的變化率,這只是因為我們正在快速注冊集群。

發現4:加載緩慢的緩存

Kubernetes controller的標准實現是將你正在處理的所有對象緩存在內存中。對於Fleet,這意味着我們需要加載數百萬個對象來建立緩存。對象列表的默認分頁大小為500。加載100萬個對象需要2000個API請求。如果你假設我們可以每秒鍾進行一次列表調用、處理對象並開啟下一頁,這意味着加載緩存需要30分鍾左右。不幸的是,如果這2000個API請求中的任何一個失敗,這個過程就會重新開始。我們嘗試將頁面大小增加到10,000個對象,但看到整體加載時間並沒有明顯加快。我們開始一次列出1萬個對象之后,我們就遇到了一個問題,Kine會隨機花費超過1分鍾的時間來返回所有對象。然后Kubernetes API Server會取消請求,導致整個加載操作失敗,不得不重新啟動。我們通過增加API請求超時(-request-timeout=30m)來解決這個問題,但這不是一個可接受的解決方案。保持較小的頁面大小可以確保請求的速度更快,但請求的數量增加了失敗幾率,並導致整個操作重啟。

重啟Fleet controller將需要花費45分鍾的時間。這一重啟時間同樣適用於kube-apiserver和kube-controller-manager。這意味着你需要非常小心。這也是我們發現運行K3s不如運行RKE等傳統發行版的一點。K3s將api-server和controller-manager結合到同一個進程中,這使得重啟api-server或controller-manager的速度比原本應有的速度慢,而且更容易出錯。模擬一場災難性的故障,需要完全重啟所有服務,包括Kubernetes,這一切花了幾個小時才恢復上線。

加載緩存所需的時間和失敗的幾率是迄今為止我們發現的擴展Fleet的最大問題。今后,這是我們要解決的首要問題。

結 論

通過測試,我們證明了Fleet的架構可以擴展到100萬個集群,更重要的是,Kubernetes可以作為一個平台來管理更多的數據。Fleet本身與容器沒有任何直接的關系,可以看成只是一個簡單的應用,在Kubernetes中管理數據。這些發現為我們開啟了一個可能性,即把Kubernetes更多的當作一個通用的編排平台來寫代碼。當考慮到你可以很容易地將一套controller與K3s捆綁在一起,Kubernetes就變成了一個很好的自成一體的應用server。

在擴展規模方面,重新加載緩存所需的時間令人擔憂,但絕對是可控的。我們將繼續在這方面進行改進,使運行100萬個集群不僅是可行的,而且是簡單的。因為在Rancher Labs,我們喜歡簡單。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM