GKE 集群上的高级负载均衡

本页介绍了如何使用 Kubernetes API 为托管式 Cloud Service Mesh (TD) 用户在 GKE 集群上配置高级负载均衡。如需查看使用Google Cloud API 配置高级负载均衡的对应用户指南,请参阅设置高级负载均衡

您可以使用高级负载均衡功能来:

  • 将流量保留在服务可用区,直到本地容量耗尽。
  • 将流量发送到“主要”位置中的服务,并在主要位置中的足够端点变得不健康时故障切换到次要位置。
  • 控制故障切换发生的时间(基于健康主机的百分比)。

限制

  • 在 Google Cloud 上使用高级负载均衡的常规限制适用。
  • 此功能仅适用于将 Traffic Director 用作控制平面的托管式 Cloud Service Mesh 用户,并且需要数据平面版本 1.19.10-asm.22 或更高版本。
  • 托管式 Service Mesh (TD) 不支持 GCPTrafficDistributionPolicy 和 GCPBackendPolicy 中的所有字段。支持的字段如下:
    • GCPTrafficDistributionPolicy
      • ServiceLbAlgorithm
      • AutoCapacityDrain
      • FailoverConfig
    • GCPBackendPolicy
      • MaxRatePerEndpoint
      • BackendPreference
  • 高级负载均衡只能应用于由以下平台上运行的工作负载支持的 Kubernetes 服务: Google Cloud。不支持外部服务或工作负载(例如 ServiceEntry)。
  • 负载均衡政策只能应用于单个 Kubernetes 服务。不支持命名空间级/网格级负载均衡政策。
  • 仅支持 QPS 容量。
  • 仅支持 GKE 1.31.1 及更高版本。
  • 服务网格高级负载均衡政策只能应用于仅处理网格流量的服务。不得将其应用于用作 GKE 网关后端的服务。当高级负载均衡流量定位到同时处理网格流量和来自 GKE 网关的流量的 Kubernetes 服务时,流量行为未定义。

配置高级负载均衡

您可以使用以下自定义资源在 GKE 上配置高级负载均衡。您可以在 gke-gateway-api 代码库中找到详细的资源定义。

GCPTrafficDistributionPolicy

GCPTrafficDistributionPolicy 用于为 Kubernetes 服务配置服务级负载均衡政策。借助该应用,您可以:

如果多个 GCPTrafficDistributionPolicy 以同一服务为目标,系统会强制执行最早的政策。

GCPBackendPolicy

GCPBackendPolicy 用于配置会影响负载均衡行为的服务后端属性,包括:

如果多个 GCPBackendPolicy 以集群中的同一服务为目标,系统会强制执行最早的政策。

政策状态

GCPTrafficDistributionPolicy 和 GCPBackendPolicy 都有一个 status 字段,用于指示政策的附加状态。

例如,运行 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 中的 Service 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 配置为首选后端

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

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

高级负载均衡多集群服务网格

在 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
    

后续步骤