GKE 叢集的進階負載平衡

您可以使用 Kubernetes API,在 GKE 叢集上為代管 Cloud Service Mesh (TD) 設定進階負載平衡。如要使用 Google Cloud API 設定進階負載平衡,請參閱「設定進階負載平衡」。

進階負載平衡功能可用於:

  • 將服務流量限制在可用區內,直到本機容量用盡為止。
  • 將流量傳送至「主要」位置的服務,並在主要位置有足夠數量的端點健康狀態不良時,容錯移轉至次要位置。
  • 控管容錯移轉的發生時間 (依據健康主機的百分比)。

限制

  • 在 Google Cloud 上使用進階負載平衡功能時,適用一般限制。
  • 這項功能僅適用於使用 Traffic Director 做為控制層的代管 Cloud Service Mesh 使用者,且資料層版本必須為 1.19.10-asm.22 以上。
  • 代管 Cloud Service Mesh (TD) 不支援 GCPTrafficDistributionPolicy 和 GCPBackendPolicy 中的部分欄位。支援的欄位如下:

    • GCPTrafficDistributionPolicy
      • ServiceLbAlgorithm
      • AutoCapacityDrain
      • FailoverConfig
    • GCPBackendPolicy
      • MaxRatePerEndpoint
      • BackendPreference

    未列出的欄位皆為不支援的欄位,如果政策設定了至少一個不支援的欄位,就不會在 Cloud Service Mesh 中生效。

  • 進階負載平衡功能只能套用至 Kubernetes 服務,且該服務必須由 Google Cloud上執行的工作負載支援。不支援外部服務或工作負載 (例如 ServiceEntry)。

  • 負載平衡政策只能套用至個別 Kubernetes 服務。不支援命名空間/網格層級的負載平衡政策。

  • 僅支援 QPS 容量。

  • 僅支援 1.31.1 以上版本的 GKE。

  • 服務網格進階負載平衡政策,只能套用至僅提供網格流量的服務。請勿套用至做為 GKE Gateway 後端的服務。如果進階負載平衡流量指定 Kubernetes 服務,而該服務同時提供網格流量和來自 GKE Gateway 的流量,則流量行為未定義。

設定進階負載平衡

您可以使用下列自訂資源,在 GKE 上設定進階負載平衡。您可以在 gke-gateway-api 存放區中找到詳細的資源定義。

GCPTrafficDistributionPolicy

GCPTrafficDistributionPolicy 會設定 Kubernetes 服務的服務層級負載平衡政策。你可以:

如果有多個 GCPTrafficDistributionPolicy 指定相同服務,系統會強制執行最舊的政策。

GCPBackendPolicy

GCPBackendPolicy 會設定服務後端屬性,這些屬性會影響負載平衡行為,包括:

如果多個 GCPBackendPolicy 指定叢集中的同一個服務,系統會強制執行最舊的政策。

政策狀態

GCPTrafficDistributionPolicy 和 GCPBackendPolicy 都有狀態欄位,指出政策的連結狀態。

例如,執行 kubectl describe gcpbackendpolicies example-policy -n example 會產生類似以下的輸出內容:

...
Status:
  Ancestors:
    Ancestor Ref:
      Group:
      Kind:       Service
      Name:       example-svc
      Namespace:  example
    Conditions:
      Last Transition Time:  2024-10-13T01:15:03Z
      Message:
      Observed Generation:   1
      Reason:                Attached
      Status:                True
      Type:                  Attached
    Controller Name:         gsmconfig.gke.io/controller

初步設定

完成本指南前,您必須先在 GKE 叢集上佈建 Cloud Service Mesh。

  1. 確認已安裝 CRD:

    kubectl get crd
    

    輸出內容大致如下:

    ...
    gcptrafficdistributionpolicies.networking.gke.io   2024-07-18T21:50:12Z
    gcpbackendpolicies.networking.gke.io               2024-07-18T21:50:12Z
    ...
    
  2. 如果尚未安裝 GCPBackendPolicy CRD,請先安裝:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-gateway-api/refs/heads/main/config/crd/networking.gke.io_gcpbackendpolicies.yaml
    
  3. 如果尚未安裝 GCPTrafficDistributionPolicy CRD,請先安裝:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-gateway-api/refs/heads/main/config/crd/networking.gke.io_gcptrafficdistributionpolicies.yaml
    

本使用手冊中的範例政策以命名空間 foo 中的服務 foo 為目標,僅供示範之用。您可以執行下列指令,建立測試服務和命名空間,也可以視需要使用自己的服務和命名空間:

kubectl apply -f - <<EOF
kind: Namespace
apiVersion: v1
metadata:
  name: foo
  labels:
    istio-injection: enabled
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo
  namespace: foo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-backend
  template:
    metadata:
      labels:
        app: test-backend
    spec:
      containers:
      - name: whereami
        image: gcr.io/google-samples/whereami:v1.2.23
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: foo
  namespace: foo
spec:
  selector:
    app: test-backend
  ports:
  - port: 8080
    targetPort: 8080
EOF

設定負載平衡演算法

根據預設,Cloud Service Mesh 服務網格中,傳送至服務的流量會平均分配給每個健康狀態良好的服務後端。您可以建立下列 GCPTrafficDistributionPolicy,將流量分配到最近的可用區,直到後端容量上限:

kubectl apply -f - <<EOF
apiVersion: networking.gke.io/v1
kind: GCPTrafficDistributionPolicy
metadata:
  name: lb-policy
  namespace: foo
spec:
  targetRefs:
  - kind: Service
    group: ""
    name: foo-service
  default:
    serviceLbAlgorithm: WATERFALL_BY_ZONE
EOF

根據預設,系統會將服務後端視為具有無限容量。如果本機/最近可用區中有足夠的健康主機,流量就不會分配到本機/最近可用區以外的特定用戶端位置。您也可以使用 GCPBackendPolicy 設定服務後端的容量,避免單一可用區超載。

kubectl apply -f - <<EOF
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
  name: backend-policy
  namespace: foo
spec:
  targetRef:
    kind: Service
    group: ""
    name: foo-backend
  default:
    maxRatePerEndpoint: 5
EOF

調整容錯移轉行為

根據預設,只要主要後端中有足夠比例的主機健康狀態良好,就不會觸發容錯移轉。如要進一步瞭解主要後端和其他術語,請參閱「進階負載平衡總覽」。您可以使用 GCPTrafficDistributionPolicy 設定健康主機百分比門檻,達到門檻後,流量就會從主要後端轉移至容錯移轉後端。門檻值越大,容錯移轉觸發的速度越快。舉例來說,如果希望在主要後端中健康主機的百分比低於 90% 時立即觸發容錯移轉,可以設定下列 GCPTrafficDistributionPolicy:

kubectl apply -f - <<EOF
apiVersion: networking.gke.io/v1
kind: GCPTrafficDistributionPolicy
metadata:
  name: lb-policy
  namespace: foo
spec:
  targetRefs:
  - kind: Service
    group: ""
    name: foo-service
  default:
   failoverConfig:
     failoverHealthThreshold: 90
EOF

在多叢集服務網格中設定進階負載平衡

在多叢集服務網格中,GCPTrafficDistributionPolicy 和 GCPBackendPolicy 會套用至不同範圍。

當 GCPTrafficDistributionPolicy 指定多叢集服務時,會定義所有叢集的服務層級負載平衡行為。您只需要為特定多叢集服務建立一個 GCPTrafficDistributionPolicy。如果您使用 Istio API 設定服務網格,可以在機群中的任何叢集建立 GCPTrafficDistributionPolicy。您可以檢查政策審查狀態,確認政策是否與其他政策衝突。

當 GCPBackendPolicy 指定多叢集服務時,會為本機叢集中指定服務選取的後端 Pod,定義後端層級設定 (例如每個 Pod 的容量)。對於同一個多叢集服務,您可以在不同叢集中定義不同的後端層級設定。

在以下範例中,叢集 A 建立了 GCPTrafficDistributionPolicy,定義整個機群使用的負載平衡演算法,而 GCPBackendPolicies 則位於各個叢集。兩項 GCPBackendPolicy 都會為本機叢集中的後端 Pod 設定每個 Pod 10 qps 的容量,而叢集 A 中的 GCPBackendPolicy 則會將叢集 A 中的後端 Pod 設為偏好的後端。

這些政策會共同設定傳送至 Service foo 的網格內流量負載平衡行為:

  • 來自任何位置的流量都會優先傳送至叢集 A 中的後端,直到叢集 A 中的後端 Pod 必須處理每個 Pod 10 QPS 為止。
    • 這項行為主要由 GCPBackendPolicy 定義,該政策在叢集 A 中將 backendPreference 設為 PREFERRED。
  • 超過叢集 A 後端設定容量的流量,會使用演算法 WATERFALL_BY_ZONE 轉送至叢集 B。如要進一步瞭解偏好的後端,請參閱「進階負載平衡總覽」。
    • 這項行為主要由 GCPTrafficDistributionPolicy (定義叢集 A 中的演算法) 和 GCPBackendPolicy (定義叢集 A 和 B 中的後端容量) 定義。

進階負載平衡多叢集服務網格

在 Istio 中,如果服務網格中有多個叢集,且服務是在叢集邊界建立,則一般 Kubernetes 服務會隱含地變成「多叢集」。雖然下列 GCPTrafficDistributionPolicy 指定一般 Kubernetes 服務 foo,但適用於由兩個叢集中對應工作負載組成的多叢集服務 foo。

  1. 為叢集 A 建立 GCPTrafficDistributionPolicy:

    kubectl apply --context cluster-a-context -f - <<EOF
    kind: GCPTrafficDistributionPolicy
    apiVersion: networking.gke.io/v1
    metadata:
    name: foo-traffic-distribution-policy
    namespace: foo
    spec:
      targetRefs:
      - kind: Service
        group: ""
        name: foo-service
      default:
        serviceLbAlgorithm: WATERFALL_BY_ZONE
    
    EOF
    
  2. 為叢集 A 建立 GCPBackendPolicy:

    kubectl apply --context cluster-a-context -f - <<EOF
    kind: GCPBackendPolicy
    apiVersion: networking.gke.io/v1
    metadata:
    name: foo-backend-policy
    namespace: foo
    spec:
      default:
        maxRatePerEndpoint: 100
        backendPreference: PREFERRED
      targetRef:
        group: ""
        kind: Service
        name: foo-service
    EOF
    
  3. 為叢集 B 建立 GCPBackendPolicy:

    kubectl apply --context cluster-b-context -f - <<EOF
    kind: GCPBackendPolicy
    apiVersion: networking.gke.io/v1
    metadata:
    name: foo-backend-policy
    namespace: foo
    spec:
      default:
        maxRatePerEndpoint: 10
      targetRef:
        group: ""
        kind: Service
        name: foo-service
    EOF
    

後續步驟