创建内部负载均衡器


本页面介绍了如何在 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 子集化。

控制台

  1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 点击 创建

  3. 根据需要配置集群。

  4. 在导航窗格的集群下,点击网络

  5. 选中启用 L4 内部负载均衡器的子集复选框。

  6. 点击创建

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 集群,请参阅以下示例:

resource "google_container_cluster" "default" {
  name               = "gke-standard-regional-cluster"
  location           = "us-central1"
  initial_node_count = 1

  enable_l4_ilb_subsetting = true

  # Set `deletion_protection` to `true` will ensure that one cannot
  # accidentally delete this instance by use of Terraform.
  deletion_protection = false
}

如需详细了解如何使用 Terraform,请参阅针对 GKE 的 Terraform 支持

在现有 Standard 集群中启用 GKE 子集化

您可以使用 gcloud CLI 或 Google Cloud 控制台为现有 Standard 集群启用 GKE 子集化。启用 GKE 子集化后,便无法将其停用。

控制台

  1. 在 Google Cloud 控制台中,转到 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 在集群列表中,点击您要修改的集群的名称。

  3. 网络下的 L4 内部负载均衡器的子集字段旁边,点击 启用 L4 内部负载均衡器的子集

  4. 选中启用 L4 内部负载均衡器的子集复选框。

  5. 点击保存更改

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。

  1. 将清单保存为 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
    
  2. 将清单应用到您的集群:

    kubectl apply -f ilb-deployment.yaml
    

创建内部 LoadBalancer Service

以下示例使用 TCP 端口 8080 创建内部 LoadBalancer Service。GKE 部署内部直通网络负载均衡器,其转发规则使用端口 8080

  1. 将清单保存为 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 匹配。
      • porttargetPort 值不必相同。节点始终执行目标 NAT,从而将目标负载均衡器转发规则 IP 地址和 port 更改为目标 Pod IP 地址和 targetPort。 如需了解详情,请参阅 LoadBalancer Service 概念文档中的节点上的目标网络地址转换

    您的清单可以包含以下内容:

    • spec.ipFamilyPolicyipFamilies,用于定义 GKE 如何将 IP 地址分配给 Service。GKE 支持单栈(仅 IPv4 或仅 IPv6)或双栈 IP LoadBalancer Service。双栈 LoadBalancer Service 通过两个单独的内部直通网络负载均衡器转发规则实现:一个用于 IPv4 流量,另一个用于 IPv6 流量。GKE 双栈 LoadBalancer Service 提供 1.29 版或更高版本。如需了解详情,请参阅 IPv4/IPv6 双栈 Service

    如需了解详情,请参阅 LoadBalancer Service 参数

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

    kubectl apply -f ilb-svc.yaml
    
  3. 获取有关 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;在此示例中分配了端口 30521nodePort 与内部直通网络负载均衡器无关。
  4. 检查 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,请执行以下步骤:

  1. 转到 Google Cloud 控制台中的工作负载页面。

    转到“工作负载”

  2. 选择要删除的 Deployment,然后点击 删除

  3. 当系统提示您确认时,请选中删除与所选 Deployment 关联的 Pod 横向自动扩缩器复选框,然后点击删除

删除 Service

要删除 Service,请执行以下步骤:

  1. 转到 Google Cloud 控制台中的 Service 和 Ingress 页面。

    打开“Service 和 Ingress”

  2. 选择要删除的 Service,然后点击 删除

  3. 当系统提示您确认时,点击删除

共享 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,请按以下步骤操作:

  1. 使用 --purpose SHARED_LOADBALANCER_VIP 创建静态内部 IP。必须创建一个具有此用途的 IP 地址,才能共享此 IP 地址。 如果您在共享 VPC 中创建静态内部 IP 地址,则必须在将使用该 IP 地址的实例所属的服务项目中创建 IP 地址,即使该 IP 地址的值将会出现从共享 VPC 网络的选定共享子网中的可用 IP 范围中。如需了解详情,请参阅“预配共享 VPC”页面上的预留静态内部 IP 地址

  2. loadBalancerIP 字段中使用此静态 IP 的内部 LoadBalancer Service 最多可部署 10 个。内部直通网络负载均衡器由 GKE 服务控制器进行协调,并使用同一前端 IP 地址进行部署。

以下示例演示了如何执行此过程,以针对同一内部负载均衡器 IP 支持多个 TCP 和 UDP 端口。

  1. 在 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:共享子网的名称。
  2. 将以下 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
    
  3. 针对您的集群应用此 Service 定义:

    kubectl apply -f tcp-service.yaml
    
  4. 将以下 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
    
  5. 针对您的集群应用此文件:

    kubectl apply -f udp-service.yaml
    
  6. 通过列出这些规则并进行静态 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 控制器也会在高级网络层级中创建内部直通网络负载均衡器。

后续步骤