本页面介绍了如何在 Google Kubernetes Engine (GKE) 上创建内部直通式网络负载均衡器或内部负载均衡器。如需创建外部直通网络负载均衡器,请了解如何创建 LoadBalancer 类型的 Service。
使用内部直通网络负载均衡器子集化
内部直通网络负载均衡器使集群的 Service 可供集群 VPC 网络中的客户端以及与集群 VPC 网络连接的网络中的客户端访问。客户端不必位于集群中。例如,内部 LoadBalancer Service 可供位于集群 VPC 网络中的虚拟机 (VM) 实例访问。
使用 GKE 子集化
GKE 子集化可提高内部 LoadBalancer Service 的可伸缩性,因为它使用 GCE_VM_IP
网络端点组 (NEG)(而不是实例组)作为后端。启用 GKE 子集化后,GKE 会为每个内部 LoadBalancer Service 的每个计算可用区创建一个 NEG。NEG 中的成员端点是至少具有该 Service 的一个服务 Pod 的节点的 IP 地址。如需详细了解 GKE 子集化,请参阅节点分组。
要求和限制
GKE 子集化有以下要求和限制:
- 您可以在 GKE 1.18.19-gke.1400 版及更高版本的新 Standard 集群和现有 Standard 集群中启用 GKE 子集化。GKE 子集化一旦启用就无法停用。
- 在 Autopilot 集群中,GKE 子集化始终处于启用状态。
- GKE 子集要求启用
HttpLoadBalancing
插件。默认情况下,此插件处于启用状态。在 Autopilot 集群中,您无法停用这一必需的插件。 - 网络端点组的配额适用。Google Cloud 会为每个可用区的每个内部 LoadBalancer Service 创建一个
GCE_VM_IP
NEG。 - 需要遵循转发规则、后端服务和健康检查的配额。如需了解详情,请参阅配额和限制。
- GKE 子集化不能与注解结合使用,以便在多个负载均衡器之间共享后端服务 (
alpha.cloud.google.com/load-balancer-backend-share
)。 - 您必须使用 Google Cloud CLI 345.0.0 版或更高版本。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行
gcloud components update
以获取最新版本。
在新的 Standard 集群中启用 GKE 子集化
您可以使用 Google Cloud CLI、Google Cloud 控制台或 Terraform 创建启用了 GKE 子集化的 Standard 集群。创建时启用了 GKE 子集化的集群会始终使用 GKE 子集化。
控制台
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
点击 add_box 创建。
根据需要配置集群。
在导航窗格的集群下,点击网络。
选中启用 L4 内部负载均衡器的子集复选框。
点击创建。
gcloud
gcloud container clusters create CLUSTER_NAME \
--cluster-version=VERSION \
--enable-l4-ilb-subsetting \
--location=COMPUTE_LOCATION
替换以下内容:
CLUSTER_NAME
:新集群的名称。VERSION
:GKE 版本,必须为 1.18.19-gke.1400 或更高版本。您还可以使用--release-channel
选项来选择发布渠道。发布渠道必须具有默认版本 1.18.19-gke.1400 或更高版本。COMPUTE_LOCATION
:集群的 Compute Engine 位置。
Terraform
如需使用 Terraform 创建启用了 GKE 子集化的 Standard 集群,请参阅以下示例:
如需详细了解如何使用 Terraform,请参阅针对 GKE 的 Terraform 支持。
在现有 Standard 集群中启用 GKE 子集化
您可以使用 gcloud CLI 或 Google Cloud 控制台为现有 Standard 集群启用 GKE 子集化。启用 GKE 子集化后,便无法将其停用。
控制台
在 Google Cloud 控制台中,转到 Google Kubernetes Engine 页面。
在集群列表中,点击您要修改的集群的名称。
在网络下的 L4 内部负载均衡器的子集字段旁边,点击 edit 启用 L4 内部负载均衡器的子集。
选中启用 L4 内部负载均衡器的子集复选框。
点击保存更改。
gcloud
gcloud container clusters update CLUSTER_NAME \
--enable-l4-ilb-subsetting
替换以下内容:
CLUSTER_NAME
:集群的名称。
启用 GKE 子集化不会中断现有的内部 LoadBalancer Service。如果您要迁移现有的内部 LoadBalancer Service 以使用将 GCE_VM_IP
NEG 作为后端的后端服务,则必须部署替换 Service 清单。如需了解详情,请参阅 LoadBalancer Service 概念文档中的节点分组。
部署工作负载
以下清单描述了一个运行示例 Web 应用容器映像的 Deployment。
将清单保存为
ilb-deployment.yaml
:apiVersion: apps/v1 kind: Deployment metadata: name: ilb-deployment spec: replicas: 3 selector: matchLabels: app: ilb-deployment template: metadata: labels: app: ilb-deployment spec: containers: - name: hello-app image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
将清单应用到您的集群:
kubectl apply -f ilb-deployment.yaml
创建内部 LoadBalancer Service
以下示例使用 TCP 端口 8080
创建内部 LoadBalancer Service。GKE 部署内部直通网络负载均衡器,其转发规则使用端口 8080
:
将清单保存为
ilb-svc.yaml
:apiVersion: v1 kind: Service metadata: name: ilb-svc annotations: networking.gke.io/load-balancer-type: "Internal" spec: type: LoadBalancer externalTrafficPolicy: Cluster selector: app: ilb-deployment ports: - name: tcp-port protocol: TCP port: 8080 targetPort: 8080
您的清单必须包含以下内容:
- 内部 LoadBalancer Service 的
name
,在本例中为ilb-svc
。 - 指定您需要内部 LoadBalancer Service 的注解。对于 GKE 1.17 版及更高版本,请使用注解
networking.gke.io/load-balancer-type: "Internal"
,如示例清单中所示。对于早期版本,请改用cloud.google.com/load-balancer-type: "Internal"
。 type: LoadBalancer
。spec: selector
字段,用于指定 Service 应针对的 Pod,例如app: hello
。- 端口信息:
port
表示内部直通网络负载均衡器的转发规则接收数据包的目标端口。targetPort
必须与每个服务 Pod 上定义的containerPort
匹配。port
和targetPort
值不必相同。节点始终执行目标 NAT,从而将目标负载均衡器转发规则 IP 地址和port
更改为目标 Pod IP 地址和targetPort
。 如需了解详情,请参阅 LoadBalancer Service 概念文档中的节点上的目标网络地址转换。
您的清单可以包含以下内容:
spec.ipFamilyPolicy
和ipFamilies
,用于定义 GKE 如何将 IP 地址分配给 Service。GKE 支持单栈(仅 IPv4 或仅 IPv6)或双栈 IP LoadBalancer Service。双栈 LoadBalancer Service 通过两个单独的内部直通网络负载均衡器转发规则实现:一个用于 IPv4 流量,另一个用于 IPv6 流量。GKE 双栈 LoadBalancer Service 提供 1.29 版或更高版本。如需了解详情,请参阅 IPv4/IPv6 双栈 Service。
如需了解详情,请参阅 LoadBalancer Service 参数
- 内部 LoadBalancer Service 的
将清单应用到您的集群:
kubectl apply -f ilb-svc.yaml
获取有关 Service 的详细信息:
kubectl get service ilb-svc --output yaml
输出类似于以下内容:
apiVersion: v1 kind: Service metadata: annotations: cloud.google.com/neg: '{"ingress":true}' cloud.google.com/neg-status: '{"network_endpoint_groups":{"0":"k8s2-pn2h9n5f-default-ilb-svc-3bei4n1r"},"zones":["ZONE_NAME","ZONE_NAME","ZONE_NAME"]}' kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{"networking.gke.io/load-balancer-type":"Internal"},"name":"ilb-svc","namespace":"default"},"spec":{"externalTrafficPolicy":"Cluster","ports":[{"name":"tcp-port","port":8080,"protocol":"TCP","targetPort":8080}],"selector":{"app":"ilb-deployment"},"type":"LoadBalancer"}} networking.gke.io/load-balancer-type: Internal service.kubernetes.io/backend-service: k8s2-pn2h9n5f-default-ilb-svc-3bei4n1r service.kubernetes.io/firewall-rule: k8s2-pn2h9n5f-default-ilb-svc-3bei4n1r service.kubernetes.io/firewall-rule-for-hc: k8s2-pn2h9n5f-l4-shared-hc-fw service.kubernetes.io/healthcheck: k8s2-pn2h9n5f-l4-shared-hc service.kubernetes.io/tcp-forwarding-rule: k8s2-tcp-pn2h9n5f-default-ilb-svc-3bei4n1r creationTimestamp: "2022-07-22T17:26:04Z" finalizers: - gke.networking.io/l4-ilb-v2 - service.kubernetes.io/load-balancer-cleanup name: ilb-svc namespace: default resourceVersion: "51666" uid: d7a1a865-7972-44e1-aa9e-db5be23d6567 spec: allocateLoadBalancerNodePorts: true clusterIP: 10.88.2.141 clusterIPs: - 10.88.2.141 externalTrafficPolicy: Cluster internalTrafficPolicy: Cluster ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - name: tcp-port nodePort: 30521 port: 8080 protocol: TCP targetPort: 8080 selector: app: ilb-deployment sessionAffinity: None type: LoadBalancer status: loadBalancer: ingress: - ip: 10.128.15.245
该输出具备以下特性:
- 内部直通网络负载均衡器的转发规则的 IP 地址包含在
status.loadBalancer.ingress
中。该 IP 地址与clusterIP
的值不同。在此示例中,负载均衡器的转发规则 IP 地址为10.128.15.245
。 - 具有
app: ilb-deployment
标签的任何 Pod 都是 Service 的服务 Pod。这些是接收内部直通网络负载均衡器路由的数据包的 pod。 - 客户端使用 Service 清单的
port
字段中指定的loadBalancer
IP 地址和 TCP 目标端口来调用 Service。如需全面了解节点在收到数据包后如何路由数据包,请参阅数据包处理。 - GKE 为 Service 分配了
nodePort
;在此示例中分配了端口30521
。nodePort
与内部直通网络负载均衡器无关。
- 内部直通网络负载均衡器的转发规则的 IP 地址包含在
检查 Service 的网络端点组:
kubectl get svc ilb-svc -o=jsonpath="{.metadata.annotations.cloud\.google\.com/neg-status}"
输出类似于以下内容:
{"network_endpoint_groups":{"0":"k8s2-knlc4c77-default-ilb-svc-ua5ugas0"},"zones":["ZONE_NAME"]}
响应表明 GKE 已创建名为
k8s2-knlc4c77-default-ilb-svc-ua5ugas0
的网络端点组。此注解存在于使用 GKE 子集化的LoadBalancer
类型的 Service 中,不存在于不使用 GKE 子集化的 Service 中。
验证内部直通网络负载均衡器组件
在创建内部 LoadBalancer Service部分中包含的示例中,内部直通网络负载均衡器的转发规则 IP 地址为 10.128.15.245
。您可以使用 Google Cloud CLI 看到该转发规则包含在集群项目的转发规则列表中:
gcloud compute forwarding-rules list --filter="loadBalancingScheme=INTERNAL"
输出包括相关的内部直通网络负载均衡器转发规则、其 IP 地址,以及该转发规则引用的后端服务(在此示例中为 k8s2-pn2h9n5f-default-ilb-svc-3bei4n1r
)。
NAME ... IP_ADDRESS ... TARGET
...
k8s2-tcp-pn2h9n5f-default-ilb-svc-3bei4n1r 10.128.15.245 ZONE_NAME/backendServices/k8s2-pn2h9n5f-default-ilb-svc-3bei4n1r
您可以使用 Google Cloud CLI 描述负载均衡器的后端服务:
gcloud compute backend-services describe k8s2-tcp-pn2h9n5f-default-ilb-svc-3bei4n1r --region=COMPUTE_REGION
将 COMPUTE_REGION
替换为后端服务的计算区域。
输出包括 Service 的一个或多个后端 GCE_VM_IP
NEG(在此示例中为 k8s2-pn2h9n5f-default-ilb-svc-3bei4n1r
):
backends:
- balancingMode: CONNECTION
group: .../ZONE_NAME/networkEndpointGroups/k8s2-pn2h9n5f-default-ilb-svc-3bei4n1r
...
kind: compute#backendService
loadBalancingScheme: INTERNAL
name: aae3e263abe0911e9b32a42010a80008
...
要确定服务的某个子集中的节点列表,请使用以下命令:
gcloud compute network-endpoint-groups list-network-endpoints NEG_NAME \
--zone=COMPUTE_ZONE
替换以下内容:
NEG_NAME
:GKE 控制器创建的网络端点组的名称。COMPUTE_ZONE
:要操作的网络端点组的计算可用区。
如需确定内部直通网络负载均衡器的运行状况良好的节点列表,请使用以下命令:
gcloud compute backend-services get-health SERVICE_NAME \
--region=COMPUTE_REGION
替换以下内容:
SERVICE_NAME
:后端服务的名称。此值与 GKE 控制器创建的网络端点组的名称相同。COMPUTE_REGION
:要操作的后端服务的计算区域。
测试与内部直通网络负载均衡器的连接
通过 SSH 连接到与集群位于同一 VPC 网络和同一区域的虚拟机实例,然后运行以下命令:
curl LOAD_BALANCER_IP
将 LOAD_BALANCER_IP
替换为负载均衡器的转发规则 IP 地址。
响应会显示 ilb-deployment
的输出:
Hello, world!
Version: 1.0.0
Hostname: ilb-deployment-77b45987f7-pw54n
内部直通式网络负载均衡器只能在同一 VPC 网络(或连接的网络)中访问。默认情况下,负载均衡器的转发规则已停用全球访问权限,因此客户端虚拟机、Cloud VPN 隧道或 Cloud Interconnect 连接 (VLAN) 必须与内部直通网络负载均衡器位于同一区域。如需支持所有区域中的客户端,您可以通过在 Service 清单中添加全球访问权限注解,对负载均衡器的转发规则启用全球访问权限。
删除内部 LoadBalancer Service 和负载均衡器资源
您可以使用 kubectl delete
或 Google Cloud 控制台删除 Deployment 和 Service。
kubectl
删除 Deployment
要删除 Deployment,请运行以下命令:
kubectl delete deployment ilb-deployment
删除 Service
要删除 Service,请运行以下命令:
kubectl delete service ilb-svc
控制台
删除 Deployment
要删除 Deployment,请执行以下步骤:
转到 Google Cloud 控制台中的工作负载页面。
选择要删除的 Deployment,然后点击 delete 删除。
当系统提示您确认时,请选中删除与所选 Deployment 关联的 Pod 横向自动扩缩器复选框,然后点击删除。
删除 Service
要删除 Service,请执行以下步骤:
转到 Google Cloud 控制台中的 Service 和 Ingress 页面。
选择要删除的 Service,然后点击 delete 删除。
当系统提示您确认时,点击删除。
共享 IP 地址
内部直通网络负载均衡器允许在多个转发规则之间共享虚拟 IP 地址。这对于扩充同一 IP 上的并发端口数或接受同一 IP 上的 UDP 和 TCP 流量非常有用。它允许每个 IP 地址最多有 50 个公开端口。具有内部 LoadBalancer Service 的 GKE 集群会以原生方式支持共享 IP。部署时,Service 的 loadBalancerIP
字段用于指示应在 Service 之间共享的 IP。
限制
多个负载均衡器的共享 IP 具有以下限制和功能:
- 每个 Service(或转发规则)最多可以有五个端口。
- 最多 10 个服务(转发规则)可以共享一个 IP 地址。这会导致每个共享 IP 最多 50 个端口。
- 共享相同 IP 地址的每个转发规则都必须使用唯一的协议和端口组合。因此,每个内部 LoadBalancer Service 都必须使用一组唯一的协议和端口。
- 同一共享 IP 支持将仅使用 TCP 的 Service 和仅使用 UDP 的服务相组合,但您无法在同一 Service 中公开 TCP 端口和 UDP 端口。
启用共享 IP
如需允许内部 LoadBalancer Service 共享公共 IP,请按以下步骤操作:
使用
--purpose SHARED_LOADBALANCER_VIP
创建静态内部 IP。必须创建一个具有此用途的 IP 地址,才能共享此 IP 地址。 如果您在共享 VPC 中创建静态内部 IP 地址,则必须在将使用该 IP 地址的实例所属的服务项目中创建 IP 地址,即使该 IP 地址的值将会出现从共享 VPC 网络的选定共享子网中的可用 IP 范围中。如需了解详情,请参阅“预配共享 VPC”页面上的预留静态内部 IP 地址。在
loadBalancerIP
字段中使用此静态 IP 的内部 LoadBalancer Service 最多可部署 10 个。内部直通网络负载均衡器由 GKE 服务控制器进行协调,并使用同一前端 IP 地址进行部署。
以下示例演示了如何执行此过程,以针对同一内部负载均衡器 IP 支持多个 TCP 和 UDP 端口。
在 GKE 集群所在的区域中创建静态 IP。子网必须是负载均衡器使用的子网,默认情况下是 GKE 集群节点 IP 使用的子网。
如果您的集群和 VPC 网络位于同一项目中:
gcloud compute addresses create IP_ADDR_NAME \ --project=PROJECT_ID \ --subnet=SUBNET \ --addresses=IP_ADDRESS \ --region=COMPUTE_REGION \ --purpose=SHARED_LOADBALANCER_VIP
如果您的集群位于共享 VPC 服务项目中,但在宿主项目中使用共享 VPC 网络:
gcloud compute addresses create IP_ADDR_NAME \ --project=SERVICE_PROJECT_ID \ --subnet=projects/HOST_PROJECT_ID/regions/COMPUTE_REGION/subnetworks/SUBNET \ --addresses=IP_ADDRESS \ --region=COMPUTE_REGION \ --purpose=SHARED_LOADBALANCER_VIP
替换以下内容:
IP_ADDR_NAME
:IP 地址对象的名称SERVICE_PROJECT_ID
:服务项目的 ID。PROJECT_ID
:您的项目的 ID(单个项目)。HOST_PROJECT_ID
:共享 VPC 宿主项目的 ID。COMPUTE_REGION
:包含共享子网的计算区域。IP_ADDRESS
:所选子网的主要 IP 地址范围中未使用的内部 IP 地址。如果您省略 IP 地址,Google Cloud 会从所选子网的主要 IP 地址范围中选择未使用的内部 IP 地址。如需确定自动选择的地址,您需要运行gcloud compute addresses describe
。SUBNET
:共享子网的名称。
将以下 TCP Service 配置保存到名为
tcp-service.yaml
的文件中,然后部署到集群。将IP_ADDRESS
替换为您在上一步中选择的 IP 地址。apiVersion: v1 kind: Service metadata: name: tcp-service namespace: default annotations: networking.gke.io/load-balancer-type: "Internal" spec: type: LoadBalancer loadBalancerIP: IP_ADDRESS selector: app: myapp ports: - name: 8001-to-8001 protocol: TCP port: 8001 targetPort: 8001 - name: 8002-to-8002 protocol: TCP port: 8002 targetPort: 8002 - name: 8003-to-8003 protocol: TCP port: 8003 targetPort: 8003 - name: 8004-to-8004 protocol: TCP port: 8004 targetPort: 8004 - name: 8005-to-8005 protocol: TCP port: 8005 targetPort: 8005
针对您的集群应用此 Service 定义:
kubectl apply -f tcp-service.yaml
将以下 UDP Service 配置保存到名为
udp-service.yaml
的文件中,然后进行部署。它还可使用上一步中指定的IP_ADDRESS
。apiVersion: v1 kind: Service metadata: name: udp-service namespace: default annotations: networking.gke.io/load-balancer-type: "Internal" spec: type: LoadBalancer loadBalancerIP: IP_ADDRESS selector: app: my-udp-app ports: - name: 9001-to-9001 protocol: UDP port: 9001 targetPort: 9001 - name: 9002-to-9002 protocol: UDP port: 9002 targetPort: 9002
针对您的集群应用此文件:
kubectl apply -f udp-service.yaml
通过列出这些规则并进行静态 IP 过滤,验证是否已在各负载均衡器转发规则之间共享 VIP。这表明有 UDP 和 TCP 转发规则都在监听共享
IP_ADDRESS
上的 7 个不同端口(在此示例中为10.128.2.98
)。gcloud compute forwarding-rules list | grep 10.128.2.98 ab4d8205d655f4353a5cff5b224a0dde us-west1 10.128.2.98 UDP us-west1/backendServices/ab4d8205d655f4353a5cff5b224a0dde acd6eeaa00a35419c9530caeb6540435 us-west1 10.128.2.98 TCP us-west1/backendServices/acd6eeaa00a35419c9530caeb6540435
限制和限额
内部直通网络负载均衡器所存在的限制
- 如果是运行 Kubernetes 1.7.4 及更高版本的集群,除了搭配使用自动模式子网外,您还可以搭配使用内部负载均衡器与自定义模式子网。
- 如果您通过将
--purpose
标志设置为SHARED_LOADBALANCER_VIP
来创建预留 IP 地址,运行 Kubernetes 1.7.X 及更高版本的集群支持为内部直通网络负载均衡器使用预留的 IP 地址。如需查看分步说明,请参阅启用共享 IP。如果 Service 引用内部直通网络负载均衡器的内部 IP 地址,则 GKE 仅保留该 IP 地址。否则,如果 Service 已更新(例如,如果端口已更改),则 GKE 可能会更改负载均衡器的 IP 地址 (spec.loadBalancerIP
)。 - 即使负载均衡器的 IP 地址发生更改(请参阅上一点),
spec.clusterIP
也会保持不变。
内部 UDP 负载均衡器所存在的限制
- 内部 UDP 负载均衡器不支持使用
sessionAffinity: ClientIP
。
已知问题
连接每 10 分钟超时一次
使用子集功能创建的内部 LoadBalancer Service 可能大约每 10 分钟观察到一次流量中断。以下版本中已修复此错误:
- 1.18.19-gke.1700 及更高版本
- 1.19.10-gke.1000 及更高版本
- 1.20.6-gke.1000 及更高版本
在标准层级中创建负载均衡器时出错
在将项目默认网络层级设置为“标准”的项目中创建内部直通网络负载均衡器时,系统会显示以下错误消息:
Error syncing load balancer: failed to ensure load balancer: googleapi: Error 400: STANDARD network tier (the project's default network tier) is not supported: Network tier other than PREMIUM is not supported for loadBalancingScheme=INTERNAL., badRequest
要在 1.23.3-gke.900 之前的 GKE 版本中解决此问题,请将项目默认网络层级配置为高级。
此问题已在启用 GKE 子集的 GKE 1.23.3-gke.900 版及更高版本中解决了。
即使项目默认网络层级设置为标准,GKE 控制器也会在高级网络层级中创建内部直通网络负载均衡器。