在 GKE Dataplane V2 中使用 Maglev 负载均衡

本文档介绍了如何为 GKE Dataplane V2 中的 Service 配置和验证 Maglev 负载均衡。

Maglev 是一种一致哈希算法,可提供高吞吐量和低延迟的负载均衡。Maglev 有助于确保同一流始终映射到同一后端,从而在后端 Pod 扩缩、更新或重新调度时最大限度地减少数据包丢弃和连接中断。

如需了解详情,请参阅 Maglev 一致哈希研究论文。

对于具有长期连接的工作负载或后端更改不应中断现有流的有状态应用,我们建议使用此功能。

如需了解资源开销和可伸缩性注意事项,请参阅 GKE Dataplane V2 概念。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。如果您之前安装了 gcloud CLI,请通过运行 gcloud components update 命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。

前提条件和限制

  • GKE 版本:1.36.0-gke.2882000 及更高版本
  • GKE Dataplane V2:已启用
  • 集群模式:Autopilot 和 Standard

使用 GKE Dataplane V2 创建 GKE 集群

如需使用 Maglev,您必须拥有一个启用了 GKE Dataplane V2 的 GKE 集群。

Autopilot

Autopilot 集群默认启用 GKE Dataplane V2。如需创建 Autopilot 集群并检索其配置,请运行以下命令:

gcloud container clusters create-auto CLUSTER_NAME \
    --region=COMPUTE_REGION \
    --release-channel=rapid
gcloud container clusters get-credentials CLUSTER_NAME \
    --region=COMPUTE_REGION

标准

如需在 Standard 集群上启用 GKE Dataplane V2,请使用 --enable-dataplane-v2 标志。如需创建 Standard 集群并检索其配置,请运行以下命令:

gcloud container clusters create CLUSTER_NAME \
    --zone=COMPUTE_ZONE \
    --enable-dataplane-v2 \
    --cluster-version=1.36.0-gke.2882000
gcloud container clusters get-credentials CLUSTER_NAME \
    --zone=COMPUTE_ZONE

部署后端应用

在配置负载均衡服务之前,请先部署后端应用来处理流量。此 Deployment 运行 hello-app 示例应用的 5 个副本。

  1. 将以下清单保存为 echo-backend.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: echo-backend
    spec:
      replicas: 5
      selector:
        matchLabels:
          app: echo-backend
      template:
        metadata:
          labels:
            app: echo-backend
        spec:
          containers:
          - name: hello
            image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
            ports:
            - containerPort: 8080
    
  2. 应用清单:

    kubectl apply -f echo-backend.yaml
    

配置负载均衡服务

您可以将服务配置为使用 Maglev 负载均衡算法或默认的随机负载均衡算法。这两个服务都以在上一步中创建的 echo-backend Deployment 为目标。

配置 Maglev 服务

如需启用 Maglev 负载均衡,请在创建时向服务元数据添加 gke.networking.io/lb-algorithm: "maglev" 注解。

  1. 将以下清单保存为 maglev-service.yaml:

    apiVersion: v1
    kind: Service
    metadata:
      name: maglev-service
      annotations:
        gke.networking.io/lb-algorithm: "maglev"
    spec:
      selector:
        app: echo-backend
      ports:
        - protocol: TCP
          port: 80
          targetPort: 8080
    
  2. 应用清单:

    kubectl apply -f maglev-service.yaml
    

配置随机服务

默认情况下,服务使用随机负载均衡算法。您无需指定注解即可使用默认算法,但以下示例明确配置了该算法以进行比较。

  1. 将以下清单保存为 random-service.yaml:

    apiVersion: v1
    kind: Service
    metadata:
      name: random-service
      annotations:
        gke.networking.io/lb-algorithm: "random"
    spec:
      selector:
        app: echo-backend
      ports:
        - protocol: TCP
          port: 80
          targetPort: 8080
    
  2. 应用清单:

    kubectl apply -f random-service.yaml
    

验证流量一致性

您可以部署从固定源端口发送流量的测试客户端 Pod,以验证 Maglev 和随机负载均衡之间的路由一致性差异。

验证 Maglev 流量一致性

Maglev 会将来自同一源端口的请求始终路由到同一后端 Pod。

  1. 将以下清单保存为 client-maglev.yaml:

    apiVersion: v1
    kind: Pod
    metadata:
      name: client-maglev
    spec:
      restartPolicy: Never
      containers:
      - name: curl
        image: curlimages/curl:8.2.0
        command: ["/bin/sh", "-c"]
        args:
        - |
          while true; do
            curl -s -H "Connection: close" http://maglev-service:80 --local-port 54321 | grep Hostname
            sleep 0.5
          done
    

    --local-port 标志会强制使用来源端口,而 Connection: close 标头有助于确保客户端可以立即将来源端口重新用于后续请求。

  2. 应用清单:

    kubectl apply -f client-maglev.yaml
    
  3. 在 Pod 运行期间,检查日志:

    kubectl logs client-maglev
    

    预期输出:

    输出结果会显示重复打印的相同主机名,表明来自客户端的所有流量始终路由到同一后端 Pod:

    Hostname: echo-backend-5c78f66dbf-abcde
    Hostname: echo-backend-5c78f66dbf-abcde
    

验证默认(随机)流量分配

默认服务会将来自同一来源端口的流量分配到不同的后端 Pod。

  1. 将以下清单保存为 client-random.yaml:

    apiVersion: v1
    kind: Pod
    metadata:
      name: client-random
    spec:
      restartPolicy: Never
      containers:
      - name: curl
        image: curlimages/curl:8.2.0
        command: ["/bin/sh", "-c"]
        args:
        - |
          while true; do
            curl -s -H "Connection: close" http://random-service:80 --local-port 54321 | grep Hostname
            sleep 0.5
          done
    
  2. 应用清单:

    kubectl apply -f client-random.yaml
    
  3. 在 Pod 运行期间,检查日志:

    kubectl logs client-random
    

    预期输出:

    输出显示了多个不同的主机名,表明流量分布在不同的 Pod 中:

    Hostname: echo-backend-5c78f66dbf-abcde
    Hostname: echo-backend-5c78f66dbf-fghij
    Hostname: echo-backend-5c78f66dbf-klmno
    ...
    

清理

如需清理本教程中使用的资源,请运行以下命令:

  1. 删除客户端 Pod、Service 和 Deployment:

    kubectl delete service maglev-service random-service
    kubectl delete deployment echo-backend
    kubectl delete pod client-maglev client-random
    
  2. 删除 GKE 集群:

Autopilot

gcloud container clusters delete CLUSTER_NAME --region=COMPUTE_REGION

标准

gcloud container clusters delete CLUSTER_NAME --zone=COMPUTE_ZONE