部署多网络 LoadBalancer 服务

本文档介绍了如何在 GKE 中创建外部直通式网络负载平衡器和内部直通式网络负载平衡器 资源,以将多网络 Pod 公开给内部或外部 客户端。 Cloud de Confiance by S3NS 它介绍了多网络 LoadBalancer Service 的必要配置、功能和限制。

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

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

多网络 LoadBalancer Service 的工作原理

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

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

限制

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

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

准备工作

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

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

部署多网络 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
    

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

以下示例展示了为 eth1 接口添加默认路由的 initContainer

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 Service

如需在 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 Service

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

  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
    

验证 Service

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

  1. 检查 Service 的状态:

    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 Service 的外部 IP 地址。

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

    curl INTERNAL_LB_IP:80
    

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

问题排查

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

负载平衡器创建失败

如果负载均衡器创建失败,请检查 Service 事件以查找错误消息:

kubectl describe service SERVICE_NAME

SERVICE_NAME 替换为 Service 的名称。

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

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. 验证是否存在节点池,该节点池在 Service 使用的网络中具有网络接口。
  2. 验证 Service 选择的 Pod 是否正在运行。
  3. 检查 Service 的端点:

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

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

后续步骤