本文档介绍了如何在 GKE 中创建 Google Cloud 外部直通式网络负载平衡器和内部直通式网络负载平衡器资源,以将多网络 Pod 向内部或外部客户端公开。其中介绍了多网络 LoadBalancer 服务的必需配置、功能和限制。
如果您将工作负载连接到多个 VPC 网络,请使用类型为 LoadBalancer 的 Kubernetes 服务将流量路由到特定辅助网络上的 Pod。创建服务时,GKE 会创建一个直通式网络负载平衡器来管理此流量。
如需详细了解 GKE 中的多网络,请参阅 Pod 的多网络支持简介。
多网络 LoadBalancer 服务的工作原理
如需公开多网络工作负载,请创建 type: LoadBalancer 的 Service。
该服务必须包含一个特殊选择器,用于根据 Pod 的辅助接口的网络来定位 Pod。添加注解以指定是创建内部负载均衡器还是外部负载均衡器。
选择器中的 networking.gke.io/network 标签可按网络过滤端点。此标签可确保负载均衡器仅将流量发送到连接到指定网络的 Pod 接口。
限制
多网络负载平衡器具有以下限制:
- 不支持使用
externalTrafficPolicy: Cluster的服务。 - 不支持以
hostNetworkPod 为目标的服务。 - 不支持 IPv6 和双栈网络。
- 您无法更改现有服务的网络。
- 仅支持第 3 层网络。
- 不支持基于目标池或实例组后端的负载平衡器。
- 辅助(非默认)网络不支持 ClusterIP 和 NodePort 服务。
准备工作
在开始之前,请完成以下任务:
- 按照为 Pod 设置多网络支持中的步骤操作,准备 VPC 网络并创建具有额外网络的 GKE 集群。
- 确保您的集群已为第 4 层内部负载平衡器启用子集。如需启用此功能,请在创建或更新集群时使用
--enable-l4-ilb-subsetting标志。 - 确保您的集群运行的是 GKE 1.37 版或更高版本。
部署多网络 Pod
如需将 Pod 附加到其他网络,请使用 networking.gke.io/interfaces 注解创建 Deployment。此注解用于指定 Pod 的网络和接口。
将以下清单保存为
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 的默认接口。将清单应用到您的集群:
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。
将以下清单保存为
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。
将清单应用到您的集群:
kubectl apply -f internal-lb-service.yaml
部署外部 LoadBalancer 服务
如需将 web-app Deployment 公开给外部客户端,请创建外部 LoadBalancer 服务。
将以下清单保存为
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。
将清单应用到您的集群:
kubectl apply -f external-lb-service.yaml
验证服务
部署服务后,验证负载平衡器是否已正确创建和配置。
检查服务状态:
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网络。列出项目中的转发规则:
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描述内部负载均衡器的转发规则,以验证其是否已附加到正确的网络:
gcloud compute forwarding-rules describe k8s2-tcp-xhvzqabw-default-web-app-internal-lb-vp1x1d6a --region=$REGION将
REGION替换为集群的区域。输出类似于以下内容:验证
network和subnetwork字段是否与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
测试负载平衡器
如需测试外部负载均衡器,请向其外部 IP 地址发送请求:
curl EXTERNAL_LB_IP:80将
EXTERNAL_LB_IP替换为web-app-external-lb服务的外部 IP 地址。如需测试内部负载均衡器,请从与负载均衡器位于同一 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 替换为您的网络名称。
在有效配置中,ParamsReady 和 Ready 条件均为 True。如果 ParamsReady 不是 True,请确保 Network 规范中的 parametersRef 正确匹配现有 GKENetworkParamSet 资源的名称、种类和组。
如果 Network 资源正确但仍未就绪,请检查所引用 GKENetworkParamSet 的状态是否存在错误,例如缺少子网:
kubectl get gkenetworkparamsets GNP_NAME -o yaml
将 GNP_NAME 替换为 GKENetworkParamSet 的名称。
负载平衡器没有后端
如果负载均衡器已配置,但没有健康状况良好的后端,请执行以下操作:
- 验证是否存在节点池,该节点池的网络接口位于服务所使用的网络中。
- 验证服务选择的 Pod 是否正在运行。
检查服务的端点:
kubectl describe endpointslice -l kubernetes.io/service-name=SERVICE_NAMEmultinet-endpointslice-controller.gke.io控制器会创建多网络端点。EndpointSlice 中列出的 Pod IP 地址属于 Service 使用的网络。如果 EndpointSlice 没有端点,请验证服务选择器标签是否与正在运行的 Pod 匹配,以及网络选择器是否与 Pod 的网络匹配。
后续步骤
- 了解 Pod 的多网络支持。
- 了解多网络服务。