本文是上海站 Meetup 中講師李宇根據其分享內容梳理成的文章
大家好,很高興來到今天下午的 Meetup。我先簡單做個自我介紹,我叫李宇,目前是 KubeSphere 的一名研發,主要負責多集群方向的工作,我今天帶來的分享是混合雲下的 Kubernetes 多集群管理與應用部署。
KubeSphere 在開始做 v3.0之前,曾發起了一個社區用戶調研,發現呼聲最高的是支持多集群管理和跨雲的應用部署,因此 KubeSphere 3.0 重點支持了多集群管理。
單集群下的 Kubernetes 架構
Kubernetes 內部分為 Master 和 Worker 兩個角色。Master 上面有 API Server 負責 API 請求,Controller Manager 負責啟動多個controller,持續協調聲明式的 API 從 spec 到 status 的轉換過程,Scheduler 則負責 Pod 的調度,Etcd負責集群數據的存儲。Worker 則作為工作節點主要負責 Pod 的啟動。
單集群下有許多場景是無法滿足企業需求的,主要分為以下幾點。
-
物理隔離。盡管 Kubernetes 提供了 ns 級別的隔離,你可以設置每個 Namespace 各自使用的 cpu 內存,甚至可以使用 Network Policy 配置不同 Namespace 的網絡連通性,企業仍然需要一個更加徹底的物理隔離環境,以此避免業務之間的互相影響。
-
混合雲。混合雲場景下,企業希望可以選擇多個公有雲廠商和私有雲解決方案,避免受限於單一雲廠商,降低一定成本。
-
應用異地多活。部署業務多個副本到不同 region 集群,避免單個 region 的斷電造成應用的不可用情況,實現不把雞蛋放在同一個籃子目的。
-
開發/測試/生產環境 。為了區分開發測試生產環境,把這些環境部署到不同的集群。
-
可拓展性。提高集群的拓展性,突破單一集群的節點上限。
其實最簡單的方式就是使用多個 Kubeconfig 文件來分別管理不同的集群,前端調動多次 API 即可同時部署業務,包括其他一些現有的其他產品也是這么做的,但是 KubeSphere 還是想以一種更加 Cloud Native 的方式去管理多個集群,於是 KubeSphere 先調研了一些已有的解決方案。
總體來說分為兩個方向:
第一個是偏向控制層的資源分發,比如 Kubernetes 社區的 Federation v1 和 Federation v2 , Argo CD/Flux CD (流水線中實現應用的分發)
第二個是致力於實現多集群之間的 Pod 網絡可達。例如 Cilium Mesh,Istio Multi-Cluster,Linkerd Service Mirroring,由於這些項目同特定的 CNI 以及服務治理組件綁定了,因此接下來我會詳細介紹一下 Federation v1 和 Federation v2 兩個項目。
Federation v1
上面是 Federation v1 的架構圖 可以看到有額外的 API Server (基於 Kube-Apiserver 開發) 和 Controller Manager (同 Kube-Controller-Manager 類似) ,下面是被管控的集群,多集群的資源分發需要在上面集群創建,然后最終被分發到下面的各個集群去。
上面是一個 在Federation v1 里面創建 Replicaset 的示例,與普通的 Replicaset 區別就是多了一些 Annotation,里面主要存了一些分發資源的邏輯,從中我們也能看到 v1 的一些缺點。
- 其引入了單獨開發的 API Server,帶來了額外的維護成本。
- 在 Kubernetes 里一個 API 是通過 Group/Version/Kind 確定的,但是 Federation v1 里面對於K8s 原生 API、GVK 固定,導致對不同版本的集群 API 兼容性很差。
- 設計之初未考慮 RBAC,無法提供跨集群的權限控制
- 基於 Annotation 的資源分發讓整個 API 過於臃腫,不夠優雅,是最被詬病的一點。
Federation v2
正是由於 v1 的這些缺點,Kubernetes 社區逐漸棄用了 v1 的設計,吸取了 v1 的一些教訓,推出了 v2 也就是 Kubefed 這個項目。Kubefed 最大的特點就是基於 CRD 和 Controller 的方式替換掉了 v1 基於Annotation 分發資源的方案,沒有侵入原生的 K8s API,也沒有引入額外的 API Server。
上面是 v2 的架構圖,可以看到一個 CRD 資源主要由 Template、Override、Placement 三部分組成,通過結合 Type Configuration,可以支持多個版本的API,大大提高了集群之間的版本兼容性,並且支持了所有資源的 Federation,包括 CRD 本身。同時 Kubefed 在設計之初也考慮到了多集群的服務發現、調度等。
下面是一個聯邦資源的示例,Deployment 在 Kubefed 中對應 FederatedDeployment,其中 spec 里面的 template 就是原來的 Deployment 資源,placement 表示聯邦資源需要被下放到哪幾個集群去, override 可以通過不同的集群配置不同集群的字段,例如 deployment 的鏡像的 tag 各個集群的副本數等。
當然 Kubefed 也不是銀彈,也有其一定的局限性。從前面可以看到,其 API 定義復雜,容易出錯,也只能使用 kubefedctl 加入和解綁集群,沒有提供單獨的 SDK。再就是它要求控制層集群到管控集群必須網絡可達,單集群到多集群需要改造 API,舊版本也不支持聯邦資源的狀態收集。
KubeShere On Kubefed
接下來我們看看 KubeSphere 基於 Kubefed 如何實現並簡化了多集群管理。
圖片里面定義了兩個概念,Host 集群指的是裝了 Kubefed 的集群,屬於 Control Plane,Member 集群指的是被管控集群,Host 集群與 Member 集群之間屬於聯邦關系。
在圖片這里用戶可以統一管理多個集群,KubeSphere 單獨定義了一個 Cluster Object,拓展了 Kubefed 里面的 Cluster 對象,包含了 region zone provider 等信息。
在導入集群的時候 KubeSphere 提供了兩種方式:
- 直接連接。這種情況要求 Host 到 Member 集群網絡可達,只需要提供一個 kubeconfig 文件可直接把集群加入進來,避免了之前提到的 kubefedctl 的復雜性 。
- 代理連接。
對於 Host 集群到 Member 集群網絡不可達的情況,目前 Kubefed 還沒有辦法做到聯邦。因此 KubeSphere 基於 chisel 開源了Tower,實現了私有雲場景下集群聯邦管理,用戶只需要在私有集群創建一個 agent 就可以實現集群聯邦。
這里展示了 Tower 的工作流程。在 Member 集群內部起了一個 agent 以后,Member 集群會去連接 Host 集群的 Tower Server,Server 收到這個連接請求后會直接監聽一個 Controller 預先分配好的端口,建立一個隧道,這樣就可以通過這個隧道從 Host 往 Member 集群分發資源。
多集群下的多租戶支持
在 KubeSphere 里面,一個租戶就是一個 Workspace,並且租戶de授權認證都是通過 CRD 來實現的。為了減少 Kubefed 對 Control Plane 的依賴,KubeSphere 把這些 CRD 通過聯邦層下放,在 Host 集群收到 API 請求后直接轉發到 Member 集群,這樣假如 Host 集群掛了,原來的租戶信息在 Member 集群仍然存在,用戶依然可以登陸 Member 集群的 Console 來部署業務。
多集群下的應用部署
Kubefed 的 API 前面我們也看到過,手動去定義是十分復雜並且容易出錯,因此 KubeSphere 在部署應用的時候,可以直接選擇需要部署的集群名稱以及各自集群的副本數,也可以在差異化配置里面配置不同集群的鏡像地址以及環境變量,例如集群 A 位於國內,拉不到 gcr.io 的鏡像,就可以配成 DockerHub 的。
聯邦資源的狀態收集
對於聯邦資源的狀態收集,前面我們提到 Kubefed 之前是沒有實現的。因此 KubeSphere 自研了聯邦資源的狀態收集,在例如創建 Pod 失敗的場景下可以很方便的去排查對應的 event 信息,另外 KubeSphere 也提供了聯邦資源的監控,提高了其可觀測性。
TODO
盡管 KubeSphere 基於 Kubefed 簡化了多集群之間的聯邦,未來也仍有一些需要改進的地方。
- 目前中心化的 Control Plane 導致資源分發只能 push,這對 Host 集群高可用有一定要求,這塊 Kubefed 社區也在積極開發從 Member 集群 pull 資源到 Host 集群的 feature。
- KubeSphere 是一個非常開放的社區,我們希望有更過的社區用戶加入進來,但是目前多集群的開發門檻較高,開發者需要定義一系列很多的 Types CRD,不夠友好。
- 多集群的服務發現目前沒有比較好的解決方案,這個本來一開始社區是有做的,但是后來為了更快的發 beta 版本,就棄用了。
- 多集群的 Pod 副本數調度,這個目前社區是有提供 RSP (Replica Scheduling Preference),KubeSphere 預計也會在下個版本加進去。
那么,有沒有既不引入中心化的 Control Plane,又能夠減少過多的 API 引入實現多集群呢。答案就是 Liqo。在介紹它之前,首先我們介紹一下 Virtual Kubelet。
Virtual Kubelet 可以幫助你把自己的服務偽裝成一個 Kubernetes 的節點,模擬 Kubelet 加入這個集群。這樣就可以水平拓展 Kubernetes 集群。
在 Liqo 里面,集群之間不存在聯邦關系,左圖里在 Kubefed 架構下 k2、k3 兩個集群是 k1 的成員集群,資源下方需要經過一次 k1 的 push,而在右邊的圖里面,k2、k3 只是 k1 的一個節點,因此在部署應用的時候,完全不需要引入任何的 API,k2、k3 看起來就是 k1 的節點,這樣業務就可以無感知的被部署到不同的集群上去,極大減少了單集群到多集群改造的復雜性。現在 Liqo 屬於剛起步階段,目前不支持兩個集群以上的拓撲,在未來 KubeSphere 也會持續關注開源領域的一些其他的多集群管理方案。
本文由博客一文多發平台 OpenWrite 發布!