GKE 集群上的高级负载均衡

本页面介绍如何使用 Kubernetes API,为托管式 Cloud Service Mesh (TD) 用户在 GKE 集群上配置高级负载均衡。如需查看相应的用户指南,以使用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
  • 高级负载均衡只能应用于由 Google Cloud上运行的工作负载提供支持的 Kubernetes 服务。不支持外部服务或工作负载(例如 ServiceEntry)。
  • 负载均衡政策只能应用于单个 Kubernetes 服务。不支持命名空间级/网格级负载均衡政策。
  • 仅支持 QPS 容量。
  • 仅支持 GKE 1.31.1 版及更高版本。
  • 服务网格高级负载均衡政策必须仅应用于仅提供网格流量的服务。不得将其应用于用作 GKE 网关后端的服务。如果高级负载均衡流量的目标是同时提供网格流量和来自 GKE 网关的流量的 Kubernetes 服务,则流量行为未定义。

配置高级负载均衡

您可以使用以下自定义资源在 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,以定义要在整个舰队中使用的负载均衡算法,同时每个集群中都有 GCPBackendPolicy。这两个 GCPBackendPolicy 都为其本地集群中的后端 Pod 配置了每 Pod 10qps 的容量,而集群 A 中的 GCPBackendPolicy 将集群 A 中的后端 Pod 配置为首选后端

这些政策共同配置了发送到服务 foo 的网格内流量的负载均衡行为:

  • 来自任何位置的流量都会优先发送到集群 A 中的后端,直到集群 A 中的每个后端 Pod 需要处理 10 qps。
    • 此行为主要由将集群 A 中的 backendPreference 设置为 PREFERRED 的 GCPBackendPolicy 定义。
  • 超出集群 A 中的后端配置容量的流量会使用算法 WATERFALL_BY_ZONE 路由到集群 B。如需详细了解首选后端,请参阅高级负载均衡概览
    • 此行为主要由 GCPTrafficDistributionPolicy 和 GCPBackendPolicy 定义,前者在集群 A 中定义算法,后者在集群 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
    

后续步骤