1. 程式人生 > >Rancher首席架構師解讀Fleet:它何以管理百萬叢集?

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

> 作者簡介 > >Darren Shepherd,Rancher Labs聯合創始人及首席架構師。在加入Rancher之前,Darren是Citrix的高階首席工程師,他在那裡從事CloudStack、OpenStack、Docker的工作,並構建下一代基礎設施編排技術。在加入Citrix之前,Darren曾在GoDaddy工作,他設計並領導一個團隊實施公有和私有IaaS雲。 本文轉自[Rancher Labs](https://mp.weixin.qq.com/s/XFDmkovJnvV6yIZ7Z532Vg) 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以讀取部署叢集,部署新的資源並報告狀態。 ![](https://oscimg.oschina.net/oscnet/up-7585648e97bf3253ffcbe4ca8368acef9e3.png) ## 擴充套件規模測試方法 我們使用兩種方法來模擬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](https://github.com/k3s-io/kine "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,我們喜歡