本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
Kubernetes 1.5 中的叢集聯邦
編者按:這篇博文是關於 Kubernetes 1.5 新功能系列深度文章的一部分。
在最新的Kubernetes 1.5 釋出中,您會注意到叢集聯邦的支援正在日趨成熟。該功能在 Kubernetes 1.3 中引入,而 1.5 版本包含多項新功能,包括更簡單的設定體驗,以及向支援所有 Kubernetes API 物件邁進了一步。
引入了一個名為“kubefed”的新命令列工具,使叢集聯邦的入門變得更加簡單。此外,還添加了對聯邦 DaemonSets、Deployments 和 ConfigMaps 的 Alpha 級支援。總之
- DaemonSets 是 Kubernetes 部署規則,它保證當新節點新增到叢集時,特定 Pod 始終存在於每個節點上(更多資訊)。
- Deployments 描述了 Replica Sets 的所需狀態(更多資訊)。
- ConfigMaps 是應用於 Replica Sets 的變數(這極大地提高了映象的可重用性,因為它們的引數可以外部化 - 更多資訊)。聯邦 DaemonSets、聯邦 Deployments、聯邦 ConfigMaps 將基本概念的質量提升到新的水平。例如,聯邦 DaemonSets 保證 Pod 部署在新新增叢集的每個節點上。
但是,“聯邦”究竟是什麼?我們透過它滿足的需求來解釋。想象一個在全球範圍內執行的服務。自然,它的所有使用者都希望獲得相同的服務質量,無論他們位於亞洲、歐洲還是美國。這意味著服務必須對每個位置的請求做出同樣快速的響應。這聽起來很簡單,但幕後涉及大量的邏輯。這就是 Kubernetes 叢集聯邦的目標。
它是如何工作的?其中一個 Kubernetes 叢集必須透過執行聯邦控制平面成為主叢集。實際上,這是一個控制器,它監控其他叢集的健康狀況,並提供一個統一的管理入口點。該入口點行為類似於典型的 Kubernetes 叢集。它允許建立Replica Sets、Deployments、Services,但聯邦控制平面將資源傳遞給底層叢集。這意味著如果我們請求聯邦控制平面建立一個包含 1,000 個副本的 Replica Set,它會將請求分散到所有底層叢集。如果我們有 5 個叢集,那麼預設情況下每個叢集將獲得 200 個副本。
這本身就是一個強大的機制。但還有更多。還可以建立聯邦 Ingress。實際上,這是一個全域性應用層負載均衡器。由於對應用層的理解,它允許負載均衡“更智慧”——例如,透過考慮客戶端和伺服器的地理位置,並以最佳方式在它們之間路由流量。
總而言之,透過 Kubernetes 叢集聯邦,我們可以方便地管理所有叢集(單一訪問點),還可以最佳化全球內容交付。在下面的章節中,我們將展示它是如何工作的。
建立聯邦平面
在此練習中,我們將聯邦一些叢集。為方便起見,所有命令已分組到此處提供的 6 個指令碼中
- 0-settings.sh
- 1-create.sh
- 2-getcredentials.sh
- 3-initfed.sh
- 4-joinfed.sh
- 5-destroy.sh 首先我們需要定義幾個變數(0-settings.sh)
$ cat 0-settings.sh && . 0-settings.sh
# this project create 3 clusters in 3 zones. FED\_HOST\_CLUSTER points to the one, which will be used to deploy federation control plane
export FED\_HOST\_CLUSTER=us-east1-b
# Google Cloud project name
export FED\_PROJECT=\<YOUR PROJECT e.g. company-project\>
# DNS suffix for this federation. Federated Service DNS names are published with this suffix. This must be a real domain name that you control and is programmable by one of the DNS providers (Google Cloud DNS or AWS Route53)
export FED\_DNS\_ZONE=\<YOUR DNS SUFFIX e.g. example.com\>
並獲取 kubectl 和 kubefed 二進位制檔案。(有關安裝說明,請參閱此處和此處的指南)。
現在設定已準備好使用 gcloud container clusters create (1-create.sh) 建立一些 Google Container Engine (GKE) 叢集。在此示例中,一個在美國,一個在歐洲,一個在亞洲。
$ cat 1-create.sh && . 1-create.sh
gcloud container clusters create gce-us-east1-b --project=${FED\_PROJECT} --zone=us-east1-b --scopes cloud-platform,storage-ro,logging-write,monitoring-write,service-control,service-management,https://www.googleapis.com/auth/ndev.clouddns.readwrite
gcloud container clusters create gce-europe-west1-b --project=${FED\_PROJECT} --zone=europe-west1-b --scopes cloud-platform,storage-ro,logging-write,monitoring-write,service-control,service-management,https://www.googleapis.com/auth/ndev.clouddns.readwrite
gcloud container clusters create gce-asia-east1-a --project=${FED\_PROJECT} --zone=asia-east1-a --scopes cloud-platform,storage-ro,logging-write,monitoring-write,service-control,service-management,https://www.googleapis.com/auth/ndev.clouddns.readwrite
下一步是使用 gcloud -q container clusters get-credentials (2-getcredentials.sh) 獲取 kubectl 配置。這些配置將用於指示 kubectl 命令的當前上下文。
$ cat 2-getcredentials.sh && . 2-getcredentials.sh
gcloud -q container clusters get-credentials gce-us-east1-b --zone=us-east1-b --project=${FED\_PROJECT}
gcloud -q container clusters get-credentials gce-europe-west1-b --zone=europe-west1-b --project=${FED\_PROJECT}
gcloud -q container clusters get-credentials gce-asia-east1-a --zone=asia-east1-a --project=${FED\_PROJECT}
讓我們驗證一下設定
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
\*
gke\_container-solutions\_europe-west1-b\_gce-europe-west1-b
gke\_container-solutions\_europe-west1-b\_gce-europe-west1-b
gke\_container-solutions\_europe-west1-b\_gce-europe-west1-b
gke\_container-solutions\_us-east1-b\_gce-us-east1-b
gke\_container-solutions\_us-east1-b\_gce-us-east1-b
gke\_container-solutions\_us-east1-b\_gce-us-east1-b
gke\_container-solutions\_asia-east1-a\_gce-asia-east1-a
gke\_container-solutions\_asia-east1-a\_gce-asia-east1-a
gke\_container-solutions\_asia-east1-a\_gce-asia-east1-a
我們有 3 個叢集。其中一個,由 FED_HOST_CLUSTER 環境變數指示,將用於執行聯邦平面。為此,我們將使用 kubefed init federation 命令(3-initfed.sh)。
$ cat 3-initfed.sh && . 3-initfed.sh
kubefed init federation --host-cluster-context=gke\_${FED\_PROJECT}\_${FED\_HOST\_CLUSTER}\_gce-${FED\_HOST\_CLUSTER} --dns-zone-name=${FED\_DNS\_ZONE}
您會注意到,執行上述命令後,出現了一個新的 kubectl 上下文
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
...
federation
federation
聯邦上下文將成為我們的管理入口點。現在是時候加入叢集了(4-joinfed.sh)
$ cat 4-joinfed.sh && . 4-joinfed.sh
kubefed --context=federation join cluster-europe-west1-b --cluster-context=gke\_${FED\_PROJECT}\_europe-west1-b\_gce-europe-west1-b --host-cluster-context=gke\_${FED\_PROJECT}\_${FED\_HOST\_CLUSTER}\_gce-${FED\_HOST\_CLUSTER}
kubefed --context=federation join cluster-asia-east1-a --cluster-context=gke\_${FED\_PROJECT}\_asia-east1-a\_gce-asia-east1-a --host-cluster-context=gke\_${FED\_PROJECT}\_${FED\_HOST\_CLUSTER}\_gce-${FED\_HOST\_CLUSTER}
kubefed --context=federation join cluster-us-east1-b --cluster-context=gke\_${FED\_PROJECT}\_us-east1-b\_gce-us-east1-b --host-cluster-context=gke\_${FED\_PROJECT}\_${FED\_HOST\_CLUSTER}\_gce-${FED\_HOST\_CLUSTER}
請注意,這裡使用叢集 gce-us-east1-b 來執行聯邦控制平面,並作為工作叢集。這種迴圈依賴有助於更有效地利用資源,可以透過使用 kubectl --context=federation get clusters 命令進行驗證
$ kubectl --context=federation get clusters
NAME STATUS AGE
cluster-asia-east1-a Ready 7s
cluster-europe-west1-b Ready 10s
cluster-us-east1-b Ready 10s
我們準備就緒。
使用聯邦執行應用程式
在我們的儲存庫中,您將找到如何構建一個帶有顯示容器主機名和 Google Cloud Platform (GCP) 區域的 Web 服務的 Docker 映象的說明。
一個示例輸出可能如下所示
{"hostname":"k8shserver-6we2u","zone":"europe-west1-b"}
現在我們將部署 Replica Set (k8shserver.yaml)
$ kubectl --context=federation create -f rs/k8shserver
以及聯邦 Service (k8shserver.yaml)
$ kubectl --context=federation create -f service/k8shserver
如您所見,這兩個命令引用了“federation”上下文,即聯邦控制平面。幾分鐘後,您會發現底層叢集執行著 Replica Set 和 Service。
建立 Ingress
Service 準備好後,我們可以建立 Ingress - 全域性負載均衡器。命令如下
kubectl --context=federation create -f ingress/k8shserver.yaml
檔案的內容指向我們在上一步中建立的服務
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: k8shserver
spec:
backend:
serviceName: k8shserver
servicePort: 80
幾分鐘後,我們應該得到一個全球 IP 地址
$ kubectl --context=federation get ingress
NAME HOSTS ADDRESS PORTS AGE
k8shserver \* 130.211.40.125 80 20m
實際上,以下請求的響應
$ curl 130.211.40.125
取決於客戶端的位置。在美國可能會看到類似這樣的內容
{"hostname":"k8shserver-w56n4","zone":"us-east1-b"}
而在歐洲,我們可能會看到
{"hostname":"k8shserver-z31p1","zone":"eu-west1-b"}
有關我們所描述的一切工作原理的更多詳細資訊,請參閱此問題。
演示
總結
叢集聯邦仍在積極開發中,尚未完全普遍可用。一些 API 處於 Beta 階段,另一些處於 Alpha 階段。一些功能缺失,例如不支援跨雲負載均衡(聯邦 Ingress 目前僅在 Google Cloud Platform 上執行,因為它依賴於 GCP HTTP(S) 負載均衡)。
然而,隨著功能的成熟,它將成為所有瞄準全球市場,但目前無法承擔 Netflix 或 Amazon 等公司使用的複雜管理技術的企業的推動者。這就是我們密切關注這項技術,並希望它能儘快實現其承諾的原因。
PS. 完成後,請記住銷燬您的叢集
$ . 5-destroy.sh