创建混合协议外部负载均衡器

本文档介绍如何使用混合协议外部 LoadBalancer 服务(同时支持 TCP 和 UDP 流量)将 Google Kubernetes Engine (GKE) 集群中运行的应用公开给互联网。

如需详细了解外部直通式网络负载均衡器,请参阅基于后端服务的外部直通式网络负载均衡器

概览

您可以使用两个单独的 GKE LoadBalancer 服务(具有手动协调的共享 IP 地址)公开同时使用 TCP 和 UDP 协议的应用。不过,这种方法效率不高,因为它需要为单个应用管理多个服务,并且可能会导致配置错误或 IP 地址配额耗尽等问题。

借助混合协议 LoadBalancer 服务,您可以使用单个服务来管理 TCP 和 UDP 的流量。使用单个服务可让您使用单个 IPv4 地址和一组适用于这两种协议的整合转发规则,从而简化配置。外部直通式网络负载均衡器支持此功能。

准备工作

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

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

要求

如需创建使用混合协议的外部 LoadBalancer 服务,您的集群必须满足以下要求:

  • 混合协议负载均衡仅适用于新创建的 1.34.1-gke.2190000 版或更高版本的集群。
  • 您必须在集群中启用 HttpLoadBalancing 插件。
  • 对于新的外部 LoadBalancer 服务,如需实现负载均衡器,请在服务清单中将 spec.loadBalancerClass 字段设置为 networking.gke.io/l4-regional-external。对于现有服务,您的清单已包含 cloud.google.com/l4-rbs: "enabled" 注释,您可以将该注释保留原样。

限制

  • 混合协议负载均衡器仅支持 IPv4 地址。
  • 您无法在具有以下终结器的服务清单中使用混合协议:

    • gke.networking.io/l4-ilb-v1
    • gke.networking.io/l4-netlb-v1

    如果您的清单包含这些终结器,您必须根据上述要求删除并重新创建服务。

价格

Google Cloud 按转发规则、任何外部 IP 地址和发送的数据量向您收取费用。下表介绍了指定配置所使用的转发规则和外部 IP 地址的数量。如需了解详情,请参阅 VPC 网络价格

类型 传输层 互联网层 转发规则数 外部 IP 地址数量
外部 单个(TCP 或 UDP) IPv4 1 1
IPv6 1 1
IPv4 和 IPv6(双栈) 2 2
混合(TCP 和 UDP) IPv4 2 1

部署工作负载

本部分介绍如何部署同时监听 TCP 和 UDP 端口的示例工作负载。请注意,无论您是使用混合协议 LoadBalancer 服务还是两个单独的单协议 LoadBalancer 服务,部署配置都是相同的。

  1. 以下清单适用于同时监听 TCP 和 UDP 流量的端口 8080 的示例应用。将以下清单保存为 mixed-app-deployment.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: mixed-app-deployment
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: mixed-app
      template:
        metadata:
          labels:
            app: mixed-app
        spec:
          containers:
          - image: gcr.io/kubernetes-e2e-test-images/agnhost:2.6
            name: agnhost
            args: ["serve-hostname", "--port=8080", "--tcp=true", "--udp=true", "--http=false"]
            ports:
              - name: tcp8080
                protocol: TCP
                containerPort: 8080
              - name: udp8080
                protocol: UDP
                containerPort: 8080
    
  2. 将清单应用到您的集群:

    kubectl apply -f mixed-app-deployment.yaml
    

创建混合协议负载均衡器

创建类型为 LoadBalancer 的服务,以向 TCP 和 UDP 流量公开部署。

  1. 将以下清单保存为 mixed-protocol-lb.yaml

    apiVersion: v1
    kind: Service
    metadata:
      name: mixed-protocol-lb
    spec:
      loadBalancerClass: "networking.gke.io/l4-regional-external"
      type: LoadBalancer
      selector:
        app: mixed-app
      ports:
      - name: tcp-port
        protocol: TCP
        port: 8080
      - name: udp-port
        protocol: UDP
        port: 8080
    

    上述服务有两个端口,一个用于 TCP,一个用于 UDP,两者均位于端口 8080 上。

  2. 将清单应用到您的集群:

    kubectl apply --server-side -f mixed-protocol-lb.yaml
    

验证混合协议负载均衡器

创建服务后,验证 GKE 是否已成功创建负载均衡器。

  1. 检查 Service:

    kubectl describe service mixed-protocol-lb
    

    输出显示了负载均衡器的外部 IP 地址以及 TCP 和 UDP 的转发规则。验证输出中的以下详细信息:

    • status.loadBalancer.ingress.ip 字段已填充。
    • 验证外部负载均衡器是否包含以下注释:
      • service.kubernetes.io/tcp-forwarding-rule
      • service.kubernetes.io/udp-forwarding-rule
    • Events 部分不包含任何错误消息。

更新混合协议负载均衡器

您可以通过修改服务清单来更新混合协议负载均衡器上的端口。要编辑 Service,请运行以下命令:

kubectl edit service SERVICE_NAME

SERVICE_NAME 替换为Service的名称。

更新端口

如需更新混合协议负载均衡器上的端口,请修改服务清单的 ports 部分。您可以添加、移除或修改端口。

以下示例添加了用于流式传输的 UDP 端口和用于游戏服务器元数据的 TCP 端口:

apiVersion: v1
kind: Service
metadata:
  name: mixed-protocol-lb
spec:
  loadBalancerClass: "networking.gke.io/l4-regional-external"
  type: LoadBalancer
  selector:
    app: mixed-app
  ports:
  - name: tcp-port
    protocol: TCP
    port: 8080
  - name: streaming
    protocol: UDP
    port: 10100
  - name: gameserver-metadata
    protocol: TCP
    port: 10400
  - name: https
    protocol: TCP
    port: 443

将单协议负载均衡器更新为混合协议负载均衡器

如需将单协议负载均衡器更改为混合协议负载均衡器,请修改服务以包含 TCP 和 UDP 协议的端口。

以下示例向仅限 TCP 的现有负载均衡器添加了 DNS 的 UDP 端口:

apiVersion: v1
kind: Service
metadata:
  name: already-existing-single-protocol-lb
spec:
  loadBalancerClass: "networking.gke.io/l4-regional-external"
  type: LoadBalancer
  selector:
    app: mixed-app
  ports:
  - name: http
    protocol: TCP
    port: 80
  - name: https
    protocol: TCP
    port: 443
  - name: dns
    protocol: UDP
    port: 53

将混合协议负载均衡器更新为单协议负载均衡器

如需将混合协议负载均衡器更改为单协议负载均衡器,请移除其中一种协议的所有端口。

以下示例移除了 DNS 的 UDP 端口,从而将负载均衡器转换为仅限 TCP:

apiVersion: v1
kind: Service
metadata:
  name: already-existing-mixed-protocol-lb
spec:
  loadBalancerClass: "networking.gke.io/l4-regional-external"
  type: LoadBalancer
  selector:
    app: mixed-app
  ports:
  - name: http
    protocol: TCP
    port: 80
  - name: https
    protocol: TCP
    port: 443

删除混合协议 LoadBalancer

如需删除 mixed-protocol-lb 外部 LoadBalancer 服务,请运行以下命令:

kubectl delete service mixed-protocol-lb

GKE 会自动移除为该服务创建的所有负载均衡器资源。

问题排查

本部分介绍了如何解决混合协议 LoadBalancer 服务的常见问题。

检查是否存在错误事件

问题排查的第一步是检查与您的服务相关联的事件。

  1. 获取服务的详细信息:

    kubectl describe service mixed-protocol-lb
    
  2. 查看输出末尾的 Events 部分,了解是否有任何错误消息。

错误:LoadBalancer 不支持混合协议

如果您使用 cloud.google.com/l4-rbs: "enabled" 注释创建了服务,则在创建混合协议负载均衡器后,您可能会看到来自原始服务控制器的警告事件:mixed-protocol is not supported for LoadBalancer

您可以放心地忽略此消息,因为支持混合协议的新控制器会正确配置负载均衡器。

更新后缺少端口定义

具体情况:

当您更新同时使用 TCP 和 UDP 的同一端口(例如端口 8080)的服务时,更新后的服务会缺少其中一个端口定义。

原因:

这是 Kubernetes 中的已知问题。当您更新在同一端口上具有多个协议的服务时,客户端补丁计算可能会错误地合并端口列表,从而导致其中一个端口定义被移除。此问题会影响使用客户端修补的客户端,例如 kubectl apply 和使用合并补丁的 Go 客户端。

解决方案:

此问题的解决方法取决于您的客户。

  • 对于 kubectl:将 --server-side 标志与 kubectl apply 搭配使用:

    kubectl apply --server-side -f YOUR_SERVICE_MANIFEST.yaml
    

    YOUR_SERVICE_MANIFEST 替换为您的服务清单的名称。

  • 对于 Go 客户端:请勿使用合并补丁。请改用更新调用来替换服务。这需要一个包含整个服务对象规范的 HTTP PUT 请求。

后续步骤