混合云下的 Kubernetes 多集群管理與應(yīng)用部署
本文是上海站 Meetup 中講師李宇根據(jù)其分享內(nèi)容梳理成的文章

大家好,很高興來到今天下午的 Meetup。我先簡單做個自我介紹,我叫李宇,目前是 KubeSphere 的一名研發(fā)工程師,主要負(fù)責(zé)多集群方向的工作。我今天帶來的分享是混合云下的 Kubernetes 多集群管理與應(yīng)用部署。
KubeSphere 在開始做 v3.0 之前,曾發(fā)起了一個社區(qū)用戶調(diào)研,發(fā)現(xiàn)呼聲最高的是支持多集群管理和跨云的應(yīng)用部署,因此 KubeSphere 3.0 重點支持了多集群管理。
單集群下的 Kubernetes 架構(gòu)

Kubernetes 內(nèi)部分為 Master 和 Worker 兩個角色。Master 上面有 API Server 負(fù)責(zé) API 請求,Controller Manager 負(fù)責(zé)啟動多個 controller,持續(xù)協(xié)調(diào)聲明式的 API 從 spec 到 status 的轉(zhuǎn)換過程,Scheduler 則負(fù)責(zé) Pod 的調(diào)度,Etcd 負(fù)責(zé)集群數(shù)據(jù)的存儲。Worker 則作為工作節(jié)點主要負(fù)責(zé) Pod 的啟動。
單集群下有許多場景是無法滿足企業(yè)需求的,主要分為以下幾點。
物理隔離
盡管 Kubernetes 提供了 ns 級別的隔離,你可以設(shè)置每個 Namespace 各自使用的 cpu 內(nèi)存,甚至可以使用 Network Policy 配置不同 Namespace 的網(wǎng)絡(luò)連通性,企業(yè)仍然需要一個更加徹底的物理隔離環(huán)境,以此避免業(yè)務(wù)之間的互相影響。
混合云
混合云場景下,企業(yè)希望可以選擇多個公有云廠商和私有云解決方案,避免受限于單一云廠商,降低一定成本。
應(yīng)用異地多活
部署業(yè)務(wù)多個副本到不同 region 集群,避免單個 region 的斷電造成應(yīng)用的不可用情況,實現(xiàn)不把雞蛋放在同一個籃子目的。
開發(fā)/測試/生產(chǎn)環(huán)境
為了區(qū)分開發(fā)測試生產(chǎn)環(huán)境,把這些環(huán)境部署到不同的集群。
可拓展性
提高集群的拓展性,突破單一集群的節(jié)點上限。
其實最簡單的方式就是使用多個 Kubeconfig 文件來分別管理不同的集群,前端調(diào)用多次 API 即可同時部署業(yè)務(wù),包括其他一些現(xiàn)有的其他產(chǎn)品也是這么做的,但是 KubeSphere 還是想以一種更加 Cloud Native 的方式去管理多個集群,于是 KubeSphere 先調(diào)研了一些已有的解決方案。
總體來說分為兩個方向:
偏向控制層的資源分發(fā),比如 Kubernetes 社區(qū)的 Federation v1 和 Federation v2 , Argo CD/Flux CD (流水線中實現(xiàn)應(yīng)用的分發(fā)) 致力于實現(xiàn)多集群之間的 Pod 網(wǎng)絡(luò)可達(dá)。例如 Cilium Mesh,Istio Multi-Cluster,Linkerd Service Mirroring,由于這些項目同特定的 CNI 以及服務(wù)治理組件綁定了,因此接下來我會詳細(xì)介紹一下 Federation v1 和 Federation v2 兩個項目。
Federation v1

上面是 Federation v1 的架構(gòu)圖??梢钥吹接蓄~外的 API Server (基于 Kube-Apiserver 開發(fā)) 和 Controller Manager (同 Kube-Controller-Manager 類似) ,下面是被管控的集群,多集群的資源分發(fā)需要在上面的集群創(chuàng)建,然后最終被分發(fā)到下面的各個集群去。

上圖是一個在 Federation v1 里面創(chuàng)建 Replicaset 的示例,與普通的 Replicaset 區(qū)別就是多了一些 Annotation,里面主要存了一些分發(fā)資源的邏輯,從中我們也能看到 Federation v1 的一些缺點。
其引入了單獨開發(fā)的 API Server,帶來了額外的維護成本。 在 Kubernetes 里一個 API 是通過 Group/Version/Kind 確定的,但是 Federation v1 里面對于K8s 原生 API、GVK 固定,導(dǎo)致對不同版本的集群 API 兼容性很差。 設(shè)計之初未考慮 RBAC,無法提供跨集群的權(quán)限控制 基于 Annotation 的資源分發(fā)讓整個 API 過于臃腫,不夠優(yōu)雅,是最被詬病的一點。
Federation v2
正是由于 Federation v1 的這些缺點,Kubernetes 社區(qū)逐漸棄用了 Federation v1 的設(shè)計,吸取了 Federation v1 的一些教訓(xùn),推出了 Federation v2 也就是 Kubefed 這個項目。Kubefed 最大的特點就是基于 CRD 和 Controller 的方式替換掉了 Federation v1 基于 Annotation 分發(fā)資源的方案,沒有侵入原生的 K8s API,也沒有引入額外的 API Server。

上面是 Federation v2 的架構(gòu)圖,可以看到一個 CRD 資源主要由 Template、Override、Placement 三部分組成,通過結(jié)合 Type Configuration,可以支持多個版本的 API,大大提高了集群之間的版本兼容性,并且支持了所有資源的 Federation,包括 CRD 本身。同時 Kubefed 在設(shè)計之初也考慮到了多集群的服務(wù)發(fā)現(xiàn)、調(diào)度等。
下面是一個聯(lián)邦資源的示例,Deployment 在 Kubefed 中對應(yīng) FederatedDeployment,其中 spec 里面的 template 就是原來的Deployment 資源,placement 表示聯(lián)邦資源需要被下放到哪幾個集群去,override 可以通過不同的集群配置不同集群的字段,例如 deployment 的鏡像的 tag 各個集群的副本數(shù)等。

當(dāng)然 Kubefed 也不是銀彈,也有其一定的局限性。從前面可以看到,其 API 定義復(fù)雜,容易出錯,也只能使用 kubefedctl 加入和解綁集群,沒有提供單獨的 SDK。再就是它要求控制層集群到管控集群必須網(wǎng)絡(luò)可達(dá),單集群到多集群需要改造 API,舊版本也不支持聯(lián)邦資源的狀態(tài)收集。
KubeShere On Kubefed
接下來我們看看 KubeSphere 基于 Kubefed 如何實現(xiàn)并簡化了多集群管理。

上圖定義了兩個概念,Host 集群指的是裝了 Kubefed 的集群,屬于 Control Plane,Member 集群指的是被管控集群,Host 集群與 Member 集群之間屬于聯(lián)邦關(guān)系。

如上圖所示,用戶可以統(tǒng)一管理多個集群,KubeSphere 單獨定義了一個 Cluster Object,拓展了 Kubefed 里面的 Cluster 對象,包含了 region zone provider 等信息。

在導(dǎo)入集群的時候 KubeSphere 提供了兩種方式:
直接連接 這種情況要求 Host 到 Member 集群網(wǎng)絡(luò)可達(dá),只需要提供一個 kubeconfig 文件可直接把集群加入進來,避免了之前提到的 kubefedctl 的復(fù)雜性 。

代理連接 對于 Host 集群到 Member 集群網(wǎng)絡(luò)不可達(dá)的情況,目前 Kubefed 還沒有辦法做到聯(lián)邦。因此 KubeSphere 基于 chisel 開源了 Tower,實現(xiàn)了私有云場景下集群聯(lián)邦管理,用戶只需要在私有集群創(chuàng)建一個 agent 就可以實現(xiàn)集群聯(lián)邦。

這里展示了 Tower 的工作流程。在 Member 集群內(nèi)部起了一個 agent 以后,Member 集群會去連接 Host 集群的 Tower Server,Server 收到這個連接請求后會直接監(jiān)聽一個 Controller 預(yù)先分配好的端口,建立一個隧道,這樣就可以通過這個隧道從 Host 往 Member 集群分發(fā)資源。
多集群下的多租戶支持

在 KubeSphere 中,一個租戶就是一個 Workspace,并且租戶的授權(quán)認(rèn)證都是通過 CRD 來實現(xiàn)的。為了減少 Kubefed 對 Control Plane 的依賴,KubeSphere 把這些 CRD 通過聯(lián)邦層下放,在 Host 集群收到 API 請求后直接轉(zhuǎn)發(fā)到 Member 集群,這樣假如 Host 集群掛了,原來的租戶信息在 Member 集群仍然存在,用戶依然可以登陸 Member 集群的 Console 來部署業(yè)務(wù)。
多集群下的應(yīng)用部署

Kubefed 的 API 前面我們也看到過,手動去定義是十分復(fù)雜并且容易出錯,因此 KubeSphere 在部署應(yīng)用的時候,可以直接選擇需要部署的集群名稱以及各自集群的副本數(shù),也可以在差異化配置里面配置不同集群的鏡像地址以及環(huán)境變量,例如集群 A 位于國內(nèi),拉不到 gcr.io 的鏡像,就可以配成 DockerHub 的。
聯(lián)邦資源的狀態(tài)收集

對于聯(lián)邦資源的狀態(tài)收集,前面我們提到 Kubefed 之前是沒有實現(xiàn)的。因此 KubeSphere 自研了聯(lián)邦資源的狀態(tài)收集,在例如創(chuàng)建 Pod 失敗的場景下可以很方便的去排查對應(yīng)的 event 信息,另外 KubeSphere 也提供了聯(lián)邦資源的監(jiān)控,提高了其可觀測性。
TODO
盡管 KubeSphere 基于 Kubefed 簡化了多集群之間的聯(lián)邦,未來也仍有一些需要改進的地方。
目前中心化的 Control Plane 導(dǎo)致資源分發(fā)只能 push,這對 Host 集群高可用有一定要求,這塊 Kubefed 社區(qū)也在積極開發(fā)從 Member 集群 pull 資源到 Host 集群的 feature。 KubeSphere 是一個非常開放的社區(qū),我們希望有更過的社區(qū)用戶加入進來,但是目前多集群的開發(fā)門檻較高,開發(fā)者需要定義一系列很多的 Types CRD,不夠友好。 多集群的服務(wù)發(fā)現(xiàn)目前沒有比較好的解決方案,這個本來一開始社區(qū)是有做的,但是后來為了更快的發(fā) beta 版本,就棄用了。 多集群的 Pod 副本數(shù)調(diào)度,這個目前社區(qū)是有提供 RSP (Replica Scheduling Preference),KubeSphere 預(yù)計也會在下個版本加進去。
那么,有沒有既不引入中心化的 Control Plane,又能夠減少過多的 API 引入實現(xiàn)多集群呢。答案就是 Liqo。在介紹它之前,首先我們介紹一下 Virtual Kubelet。

Virtual Kubelet 可以幫助你把自己的服務(wù)偽裝成一個 Kubernetes 的節(jié)點,模擬 Kubelet 加入這個集群。這樣就可以水平拓展 Kubernetes 集群。

在 Liqo 里面,集群之間不存在聯(lián)邦關(guān)系,左圖里在 Kubefed 架構(gòu)下 k2、k3 兩個集群是 k1 的成員集群,資源下方需要經(jīng)過一次 k1 的 push,而在右邊的圖里面,k2、k3 只是 k1 的一個節(jié)點,因此在部署應(yīng)用的時候,完全不需要引入任何的 API,k2、k3 看起來就是 k1 的節(jié)點,這樣業(yè)務(wù)就可以無感知的被部署到不同的集群上去,極大減少了單集群到多集群改造的復(fù)雜性?,F(xiàn)在 Liqo 屬于剛起步階段,目前不支持兩個集群以上的拓?fù)?,在未?KubeSphere 也會持續(xù)關(guān)注開源領(lǐng)域的一些其他的多集群管理方案。
以上就是本次分享的全部內(nèi)容,歡迎大家交流!
2. 下一代微服務(wù),到底什么是Service Mesh?
最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。
獲取方式:點“在看”,關(guān)注公眾號并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。
文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。
謝謝支持喲 (*^__^*)

