部署多网络 LoadBalancer 服务

本文档介绍了如何在 GKE 中创建 Google Cloud 外部直通式网络负载平衡器和内部直通式网络负载平衡器资源,以将多网络 Pod 向内部或外部客户端公开。其中介绍了多网络 LoadBalancer 服务的必需配置、功能和限制。

如果您将工作负载连接到多个 VPC 网络,请使用类型为 LoadBalancer 的 Kubernetes 服务将流量路由到特定辅助网络上的 Pod。创建服务时,GKE 会创建一个直通式网络负载平衡器来管理此流量。

如需详细了解 GKE 中的多网络,请参阅 Pod 的多网络支持简介

多网络 LoadBalancer 服务的工作原理

如需公开多网络工作负载,请创建 type: LoadBalancerService。 该服务必须包含一个特殊选择器,用于根据 Pod 的辅助接口的网络来定位 Pod。添加注解以指定是创建内部负载均衡器还是外部负载均衡器。

选择器中的 networking.gke.io/network 标签可按网络过滤端点。此标签可确保负载均衡器仅将流量发送到连接到指定网络的 Pod 接口。

限制

多网络负载平衡器具有以下限制:

  • 不支持使用 externalTrafficPolicy: Cluster 的服务。
  • 不支持以 hostNetwork Pod 为目标的服务。
  • 不支持 IPv6 和双栈网络。
  • 您无法更改现有服务的网络。
  • 仅支持第 3 层网络。
  • 不支持基于目标池或实例组后端的负载平衡器。
  • 辅助(非默认)网络不支持 ClusterIP 和 NodePort 服务。

准备工作

在开始之前,请完成以下任务:

  1. 按照为 Pod 设置多网络支持中的步骤操作,准备 VPC 网络并创建具有额外网络的 GKE 集群。
  2. 确保您的集群已为第 4 层内部负载平衡器启用子集。如需启用此功能,请在创建或更新集群时使用 --enable-l4-ilb-subsetting 标志。
  3. 确保您的集群运行的是 GKE 1.37 版或更高版本。

部署多网络 Pod

如需将 Pod 附加到其他网络,请使用 networking.gke.io/interfaces 注解创建 Deployment。此注解用于指定 Pod 的网络和接口。

  1. 将以下清单保存为 web-app-deployment.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web-app
      labels:
        app: web-app
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: web-app
      template:
        metadata:
          labels:
            app: web-app
          annotations:
            networking.gke.io/default-interface: 'eth1'
            networking.gke.io/interfaces: '[
              {"interfaceName":"eth0","network":"default"},
              {"interfaceName": "eth1","network": "dmz"}
            ]'
    spec:
      containers:
      - name: whereami
        image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1
        ports:
        - containerPort: 8080
    

    此清单创建了一个名为 web-app 的 Deployment,其中包含三个 Pod。Pod 有两个接口:eth0 连接到 default 网络,eth1 连接到 dmz 网络。networking.gke.io/default-interface 注解将 eth1 设置为 Pod 的默认接口。

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

    kubectl apply -f web-app-deployment.yaml
    

如果您为服务使用非默认接口,则必须在 Pod 内配置路由。如需配置路由,请向具有 NET_ADMIN 功能的 Pod 规范添加 initContainer

以下示例展示了一个 initContainer,用于为 eth1 接口添加默认路由:

initContainers:
      - name: init-routes-busybox
        image: busybox
        command: ['sh', '-c', 'ip route add default dev eth1 table 200 && ip rule add from 172.16.1.0/24 table 200']
        securityContext:
          capabilities:
            add: ["NET_ADMIN"]

initContainer 命令中,将 172.16.1.0/24 替换为 Pod 网络的次要 IP 地址范围。

部署内部 LoadBalancer 服务

如需在 dmz 网络上公开 web-app Deployment,请创建内部 LoadBalancer Service。

  1. 将以下清单保存为 internal-lb-service.yaml

    apiVersion: v1
    kind: Service
    metadata:
      name: web-app-internal-lb
      namespace: default
      annotations:
        networking.gke.io/load-balancer-type: "Internal"
    spec:
      externalTrafficPolicy: Local
      ports:
      -   port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        networking.gke.io/network: dmz
        app: web-app
      type: LoadBalancer
    

    此清单创建了一个具有以下属性的 Service:

    • networking.gke.io/load-balancer-type: "Internal":指定内部直通式网络负载平衡器。
    • selector:选择具有标签 app: web-app 且连接到 dmz 网络的 Pod。
  2. 将清单应用到您的集群:

    kubectl apply -f internal-lb-service.yaml
    

部署外部 LoadBalancer 服务

如需将 web-app Deployment 公开给外部客户端,请创建外部 LoadBalancer 服务。

  1. 将以下清单保存为 external-lb-service.yaml

    apiVersion: v1
    kind: Service
    metadata:
      name: web-app-external-lb
      namespace: default
      annotations:
        cloud.google.com/l4-rbs: "enabled"
    spec:
      externalTrafficPolicy: Local
      ports:
      -   port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        networking.gke.io/network: dmz
        app: web-app
      type: LoadBalancer
    

    此清单创建了一个具有以下属性的 Service:

    • cloud.google.com/l4-rbs: "enabled":指定基于后端服务的外部直通式网络负载平衡器。
    • selector:选择具有标签 app: web-app 且连接到 dmz 网络的 Pod。
  2. 将清单应用到您的集群:

    kubectl apply -f external-lb-service.yaml
    

验证服务

部署服务后,验证负载平衡器是否已正确创建和配置。

  1. 检查服务状态:

    kubectl get services
    

    输出类似于以下内容:

    NAME                  TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE
    web-app-external-lb   LoadBalancer   10.8.47.77    35.239.57.231   80:31550/TCP   5m
    web-app-internal-lb   LoadBalancer   10.8.43.251   172.16.0.43     80:32628/TCP   6m
    kubernetes            ClusterIP      10.8.32.1     <none>          443/TCP        43h
    

    内部负载均衡器的 EXTERNAL-IP 地址属于 dmz 网络。

  2. 列出项目中的转发规则:

    gcloud compute forwarding-rules list
    

    输出类似于以下内容:

    NAME                                                   REGION        IP_ADDRESS     IP_PROTOCOL  TARGET
    af901673cc0f24907a6aa8c3ce4afc21                       us-central1   35.239.57.231  TCP          us-central1/backendServices/k8s2-xhvzqabw-default-web-app-external-lb-u4xbs4ot
    k8s2-tcp-xhvzqabw-default-web-app-internal-lb-vp1x1d6a us-central1   172.16.0.43    TCP          us-central1/backendServices/k8s2-xhvzqabw-default-web-app-internal-lb-vp1x1d6a
    
  3. 描述内部负载均衡器的转发规则,以验证其是否已附加到正确的网络:

    gcloud compute forwarding-rules describe k8s2-tcp-xhvzqabw-default-web-app-internal-lb-vp1x1d6a --region=$REGION
    

    REGION 替换为集群的区域。

    输出类似于以下内容:验证 networksubnetwork 字段是否与 dmz 网络的详细信息一致。

    IPAddress: 172.16.0.43
    IPProtocol: TCP
    ...
    loadBalancingScheme: INTERNAL
    name: k8s2-tcp-xhvzqabw-default-web-app-internal-lb-vp1x1d6a
    network: https://www.googleapis.com/compute/v1/projects/projectId/global/networks/dmz-vpc
    ...
    subnetwork: https://www.googleapis.com/compute/v1/projects/projectId/regions/us-central1/subnetworks/dmz-subnet
    

测试负载平衡器

  1. 如需测试外部负载均衡器,请向其外部 IP 地址发送请求:

    curl EXTERNAL_LB_IP:80
    

    EXTERNAL_LB_IP 替换为 web-app-external-lb 服务的外部 IP 地址。

  2. 如需测试内部负载均衡器,请从与负载均衡器位于同一 VPC 中的主机发送请求:

    curl INTERNAL_LB_IP:80
    

    INTERNAL_LB_IP 替换为 web-app-internal-lb 服务的 IP 地址。

问题排查

本部分介绍了如何排查多网络负载平衡器的问题。

负载平衡器创建失败

如果负载均衡器创建失败,请检查服务事件中是否有错误消息:

kubectl describe service SERVICE_NAME

SERVICE_NAME 替换为Service的名称。

如果出现类似 network some-other-network does not exist 的错误消息,则表示服务选择器中指定的网络未在集群中定义。验证网络是否存在:

kubectl get networks

如果网络存在,请验证 Network 对象是否正确引用了有效的 GKENetworkParamSet 资源。如需检查是否存在配置错误,请检查 Network 资源状态:

kubectl get networks NETWORK_NAME -o yaml

NETWORK_NAME 替换为您的网络名称。

在有效配置中,ParamsReadyReady 条件均为 True。如果 ParamsReady 不是 True,请确保 Network 规范中的 parametersRef 正确匹配现有 GKENetworkParamSet 资源的名称、种类和组。

如果 Network 资源正确但仍未就绪,请检查所引用 GKENetworkParamSet 的状态是否存在错误,例如缺少子网:

kubectl get gkenetworkparamsets GNP_NAME -o yaml

GNP_NAME 替换为 GKENetworkParamSet 的名称。

负载平衡器没有后端

如果负载均衡器已配置,但没有健康状况良好的后端,请执行以下操作:

  1. 验证是否存在节点池,该节点池的网络接口位于服务所使用的网络中。
  2. 验证服务选择的 Pod 是否正在运行。
  3. 检查服务的端点:

    kubectl describe endpointslice -l kubernetes.io/service-name=SERVICE_NAME
    

    multinet-endpointslice-controller.gke.io 控制器会创建多网络端点。EndpointSlice 中列出的 Pod IP 地址属于 Service 使用的网络。如果 EndpointSlice 没有端点,请验证服务选择器标签是否与正在运行的 Pod 匹配,以及网络选择器是否与 Pod 的网络匹配。

后续步骤