iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0
Kubernetes

異世界生存戰記:30天煉成GKE大師系列 第 29

Day29 GKE 艦隊大軍集結:串連跨區域高可用多集群服務

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20241013/2016901720X8NfYNFh.png

前言

在現代雲原生應用程式中,跨多個 Kubernetes 叢集部署和管理服務變得越來越普遍。Google Kubernetes Engine (GKE) 提供了強大的功能來簡化這個過程,其中 GKE Fleet 和 Multi-cluster Services (MCS) 是兩個關鍵技術。

本文將深入探討如何利用 Shared VPC 在 GKE Fleet 中設置 MCS,實現跨不同區域叢集的服務發現和流量管理。此架構不僅提升了應用程式的可用性和容錯能力,也簡化了網路管理的複雜度,讓您可以更專注於應用程式的開發和部署。 無論您是 Kubernetes 新手還是經驗豐富的用戶,本文都將提供您在 GKE 環境中建構和管理多叢集服務的實用知識。

MCS 介紹

GKE 多叢集服務 (Multi-Cluster Services,MCS) 允許您在多個 Google Kubernetes Engine (GKE) 叢集上部署和管理應用程式。它簡化了跨多個叢集的操作,例如流量分割、故障轉移和服務探索,讓您可以更輕鬆地建構和管理高度可用且可擴展的應用程式。

以下是 GKE MCS 的主要功能和優點:

  • 跨叢集服務發現和流量管理: MCS 允許您建立跨多個叢集的單一服務,並在這些叢集之間自動分配流量。您可以使用不同的流量分割策略,例如基於權重的路由或基於地理位置的路由。
  • 跨叢集服務同步: MCS 會自動同步服務和端點資訊到所有參與的叢集,確保服務的一致性。
  • 簡化的操作: MCS 提供了一個集中式的控制平面,用於管理跨多個叢集的服務,簡化了部署和管理的複雜性。
  • 高可用性和災難復原: 通過將應用程式部署到多個叢集,MCS 可以提高應用程式的高可用性,並在單個叢集發生故障時提供災難復原能力。
  • 無需複雜的配置: MCS 抽象了底層的網路和服務發現機制,讓您可以更輕鬆地在多個叢集上部署應用程式,而無需進行複雜的配置。

設置 Shared VPC 下的 GKE Fleet

接續第 Day2, Day3,會使用 Day2 創建的 Shared VPC 網路及Day3 的 GKE Terraform,需要再創建一個 GKE 叢集在 US-West4 地區。

GKE Fleet 網路架構表如下:

https://ithelp.ithome.com.tw/upload/images/20241013/20169017rYt61lbfq5.png

啟用必需的 API

將讀者的設定取代以下變數內容:

  • SHARED_VPC_HOST_PROJ:共用 VPC 宿主專案的 ID
  • FLEET_HOST_PROJ_NUMBER:艦隊宿主專案的編號,不是專案 ID 唷!
  • FLEET_HOST_PROJ:集群專案的ID。

在艦隊宿主專案中啟用 GKE Hub, Traffic Director、Resource Manager 、Anthos、Cloud DNS 和 Multi-cluster Service Discovery API

$ gcloud services enable gkehub.googleapis.com \
		anthos.googleapis.com \
		trafficdirector.googleapis.com \
    cloudresourcemanager.googleapis.com \
    multiclusterservicediscovery.googleapis.com \
    dns.googleapis.com \
    --project $FLEET_HOST_PROJ

在 SHARED VPC 專案下開啟 Cloud DNS API

$ gcloud services enable dns.googleapis.com \
    --project $SHARED_VPC_HOST_PROJ

在艦隊宿主專案中啟用多集群服務

$ gcloud container fleet multi-cluster-services enable \
    --project $FLEET_HOST_PROJ
##輸出
Waiting for Feature Multi-cluster Services to be created...done. 

如果在艦隊宿主專案中啟用多集群服務,則系統會創建以下服務帳號或者確保以下服務帳號存在 service-$FLEET_HOST_PROJ_NUMBER@gcp-sa-mcsd.iam.gserviceaccount.com 

使用 GKE Fleet 需要開啟 GKE Enterprise 版本,如下圖所示這樣就代表有開啟了。
https://ithelp.ithome.com.tw/upload/images/20241016/201690179WsTIldibT.png

創建空艦隊

運行以下命令創建空艦隊

$ gcloud alpha container fleet create --display-name=$NAME --project=$FLEET_HOST_PROJECT

https://ithelp.ithome.com.tw/upload/images/20241013/20169017jiUZgp918H.png

創建完成後,可以在 Fleet Host Project(艦隊宿主專案)下的的 GKE 頁面會看到 Fleet(機群)會顯示出來,而 Cluster(叢集)頁面也會出現 REGISTER(註冊)的選項。

將叢集註冊到 Fleet(機群)中

使用指令進行註冊操作

  1. 將第一個集群註冊到艦隊。 -gke-cluster 標誌可用於此命令,因為第一個集群與註冊它的艦隊位於同一專案中。

    $ gcloud container fleet memberships $叢集名稱_1 \
        --project $FLEET所在專案ID \
        --enable-workload-identity \
        --gke-cluster=$地區/$叢集名稱_1
    

    取代以下內容:

    • $叢集名稱_1:此集群在此艦隊中的唯一標識符。 通常使用第一個要註冊的 GKE 集群名稱。
    • $FLEET所在專案ID:艦隊宿主專案的ID。
    • $地區:對於可用區級集群,這是包含集群的 Compute Engine 可用區; 對於區域級集群,這是包含集群的 Compute Engine 區域。
    • $叢集名稱_2:第一個要註冊的叢集的名稱。
  2. 將第二個集群註冊到艦隊宿主專案。 -gke-cluster 標誌可用於此命令,因為第二個集群也位於艦隊宿主專案中。

    $ gcloud container fleet memberships $叢集名稱_2 \
        --project $FLEET所在專案ID \
        --enable-workload-identity \
        --gke-cluster=$地區/$叢集名稱_2
    

    取代以下內容:

    • $叢集名稱_2:此集群在此艦隊中的唯一標識符。 通常使用第二個要註冊的 GKE 集群名稱。
    • $FLEET所在專案ID:艦隊宿主專案的ID。
    • $地區:對於可用區級集群,這是包含集群的 Compute Engine 可用區; 對於區域級集群,這是包含集群的 Compute Engine 區域。
    • $叢集名稱_2:第二個要註冊的叢集的名稱。

使用 GCP UI 介面進行註冊操作

點擊下圖中的註冊,將集群註冊到當前專案中的 Fleet(機群)中

https://ithelp.ithome.com.tw/upload/images/20241013/20169017KEt2eqIicD.png

註冊完成後會如下圖顯示叢集所在的機群

https://ithelp.ithome.com.tw/upload/images/20241013/20169017qZVdacKQ5S.png

再創建一個在 us-west4 的 GKE 叢集,並註冊到此專案中的 Fleet(機群)

https://ithelp.ithome.com.tw/upload/images/20241013/20169017rh2Dz8ysa1.png

創建 IAM 綁定

創建 IAM 綁定,向艦隊宿主專案 MCS 服務帳號授予共用 VPC 宿主專案的 MCS Service Agent 角色:

$ gcloud projects add-iam-policy-binding $SHARED_VPC_HOST_PROJ \
    --member "serviceAccount:service-$FLEET_HOST_PROJ_NUMBER@gcp-sa-mcsd.iam.gserviceaccount.com" \
    --role roles/multiclusterservicediscovery.serviceAgent

由於此場景使用適用於 GKE 的工作負載身份聯合,因此艦隊宿主專案的 MCS 導入程式 GKE 服務帳號需要自己專案的 Network User 角色。

創建 IAM 綁定,向艦隊宿主專案 MCS 服務帳號授予自己專案和 Shared VPC 專案的 Network User 角色:

$ gcloud projects add-iam-policy-binding $FLEET_HOST_PROJ \
    --member "serviceAccount:$FLEET_HOST_PROJ.svc.id.goog[gke-mcs/gke-mcs-importer]" \
    --role roles/compute.networkViewer
    
$ gcloud projects add-iam-policy-binding $SHARED_VPC_HOST_PROJ \
    --member "serviceAccount:$FLEET_HOST_PROJ.svc.id.goog[gke-mcs/gke-mcs-importer]" \
    --role roles/compute.networkViewer

驗證 MCS 已經正確啟動

 可由以下指令驗證是否已啟用 MCS。

$ gcloud container fleet multi-cluster-services describe --project ithome-202409-demo-2

createTime: '2024-10-11T08:57:43.606552889Z'
membershipStates:
  projects/407205409614/locations/us-central1/memberships/demo2-cluster:
    state:
      code: OK
      description: Firewall successfully updated
      updateTime: '2024-10-13T07:31:59.227720484Z'
  projects/407205409614/locations/us-west4/memberships/demo2-us-west4-fleet-cluster:
    state:
      code: OK
      description: Firewall successfully updated
      updateTime: '2024-10-13T07:31:58.574210973Z'
name: projects/ithome-202409-demo-2/locations/global/features/multiclusterservicediscovery
resourceState:
  state: ACTIVE
spec: {}
updateTime: '2024-10-11T08:57:46.039837503Z'

由輸出可得知兩個集群都已經正常啟用 MCS 了。

同樣 GKE Fleet 的兩個叢集內會創建gke-mcs NameSpace,並在此 Namespace 下創建 Deployment 及 ServiceAccount,可以到此 Fleet(機群) 下的所有叢集中查看,

$ kubectl get deployment -n gke-mcs  
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
gke-mcs-importer   1/1     1            1           1m

$ kubectl get sa -n gke-mcs          
NAME               SECRETS   AGE
default            0         1m
gke-mcs-importer   0         1m

開始使用 MCS 及其後端服務

下表為本次實驗環境的 GKE Cluster 所有網路相關設定。

GKE Cluster Name Region Node IP CIDR Pod CIDR Service CIDR
demo2-cluster us-central1 10.120.64.0/20 10.120.80.0/20 10.120.96.0/20
demo2-us-west4-fleet-cluster us-west4 10.123.64.0/20 10.123.80.0/20 10.123.96.0/20

以下使用的鏡像 a51907/display-podname-image:2024 是筆者自己製作可以在前端網頁顯示 Pod 中的環境變數來知道自己的 Pod Name 及 Service Name。

us-central1這個地區的集群創建以下 Deployment,有特別標記名稱為 us-central1

kubectl apply -f us-central1-deployment.yaml

# us-central1-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: us-central1-deployment
  namespace: mcs-test
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: display-podname-image
          image: a51907/display-podname-image:2024
          ports:
          - containerPort: 80

us-west4這個地區的集群創建以下 Deployment,有特別標記名稱為 us-west4

kubectl apply -f us-west4-deployment.yaml

# us-west4-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: us-west4-deployment
  namespace: mcs-test
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: display-podname-image
          image: a51907/display-podname-image:2024
          ports:
          - containerPort: 80

在兩個不同地區的不同集群(us-central1us-west4)都創建上述兩個 Deployment 的 Service 及 ServiceExport

kubectl apply -f mcs-test.yaml

# mcs-test.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: mcs-test
spec:
  selector:
    app: my-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP
---
# serviceexport.yaml
kind: ServiceExport
apiVersion: net.gke.io/v1
metadata:
 name: my-service
 namespace: mcs-test

等待五分鐘後,系統將會於兩個集群都自動創建 ServiceImport 物件。以下 Tsh 的指令是 Day15 Teleport 介紹,可以快速切換當前的集群。

進入 us-central1 的叢集 demo2-cluster

$ tsh kube login demo2-cluster
$ kubectl get ServiceImport -n mcs-test
NAME         TYPE           IP                   AGE
my-service   ClusterSetIP   ["10.120.102.128"]   8m20s

kubectl get Service -n mcs-test
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
gke-mcs-8b6i2bo58n   ClusterIP   10.120.102.128   <none>        80/TCP    53m
my-service           ClusterIP   10.120.98.2      <none>        80/TCP    57m

$ kubectl get endpoints gke-mcs-8b6i2bo58n -n mcs-test
NAME                 ENDPOINTS                                                       AGE
gke-mcs-8b6i2bo58n   10.120.80.193:80,10.120.80.71:80,10.123.80.152:80 + 1 more...   54m

進入 us-west4 的叢集 demo2-us-west4-fleet-cluster

$ tsh kube login demo2-us-west4-fleet-cluster
$ kubectl get ServiceImport -n mcs-test
NAME         TYPE           IP                   AGE
my-service   ClusterSetIP   ["10.123.111.156"]   9m

$ kubectl get Service -n mcs-test
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
gke-mcs-8b6i2bo58n   ClusterIP   10.123.111.156   <none>        80/TCP    52m
my-service           ClusterIP   10.123.97.28     <none>        80/TCP    25m

$ kubectl get endpoints gke-mcs-8b6i2bo58n -n mcs-test
NAME                 ENDPOINTS                                                       AGE
gke-mcs-8b6i2bo58n   10.120.80.193:80,10.120.80.71:80,10.123.80.152:80 + 1 more...   54m

可以發現 ServiceImport 和系統自動創建的 gke-mcs Service 會是同一個 IP,我們去搜索 MCS Service 背後對應的 Endpoint,會發現對應到不同集群中的 Pod IP。

讀者如果設定完後,ServiceImport, Service, Endpoints輸出都如上述所示,恭喜!那就代表設定無誤。此時 GKE Fleet 架構如下圖:

https://ithelp.ithome.com.tw/upload/images/20241013/201690177hMN6W9O7o.png

接下來,在兩個不同地區的不同集群(us-central1us-west4)都啟動 radial/busyboxplus:curl 的 pod,待會要使用其來進行 Curl 的指令來確定剛剛創建的 MCS Service 可以正確轉發到不同的集群內

$ kubectl run test-curl --image=radial/busyboxplus:curl -n mcs-test  --command -- /bin/sh -c "while true; do sleep 360000; done"

進入上個步驟創建的 Pod 中,請求 K8s 內部的 Service DNS 解析(gke-mcs-8b6i2bo58n.mcs-test.svc.cluster.local:80)

$ exec kubectl exec -i -t -n mcs-test test-curl -c test-curl -- sh -c "clear; (bash || ash || sh)"
[root@test-curl:/]$ curl http://gke-mcs-8b6i2bo58n.mcs-test.svc.cluster.local:80

可以看到請求到不同地區的 GKE 叢集及不同的 Pod 之中。

https://ithelp.ithome.com.tw/upload/images/20241013/20169017WOOAAB1Kg7.png

總結

由於今年 AI 熱潮導致 GCP 特定區域的 GPU 資源經常短缺,筆者在部署 GPU 叢集時,經常遇到配額不足的問題。由於 GKE 叢集區域固定,若單一節點池(Node Pool)需更換區域,則必須重建整個叢集。為了避免這種情況,並確保 GPU 資源的彈性調度,我們選擇採用 GKE Fleet 的多叢集架構。

這系列的鐵人賽文章也到了第 29 天了,由於篇幅有限,只能帶領讀者體驗 GKE Fleet 的入門,更進階的課題還有 Multi-Cluster Ingress, Multi-Cluster Gateway 這兩項是 Day7Day10 的延伸,以及 Anthos 混合雲和多雲應用程式現代化平台,將不同雲供應商的 K8s Cluster 彼此串接製作成集群艦隊唷!

參考文件


上一篇
Day28 在 GKE TPU 異世界中轉職為詠唱師:Gemma LLM 部署實戰
下一篇
Day30 GKE 異世界之旅後記
系列文
異世界生存戰記:30天煉成GKE大師30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言