适用于 HTTP(S) 负载平衡的 GKE Ingress

本页面简要介绍了适用于 HTTP(S) 负载平衡的 Ingress 的工作原理。Google Kubernetes Engine (GKE) 提供了一个名为 GKE Ingress 的代管式内置 Ingress 控制器。此控制器实现 Ingress 资源,作为 Google Cloud 负载平衡器,用于 GKE 中的 HTTP(S) 工作负载。

概览

在 GKE 中,Ingress 对象定义用于将 HTTP(S) 流量路由到集群中运行的应用的规则。一个 Ingress 对象与一个或多个 Service 对象相关联,每个 Service 对象与一组 Pod 相关联。

当您创建 Ingress 对象时,GKE Ingress 控制器会根据 Ingress 中的信息及其关联的 Service 创建 Google Cloud HTTP(S) 负载平衡器并对其进行配置。

适用于外部和内部流量的 Ingress

GKE Ingress 资源有两种类型:

HTTP(S) 负载平衡的功能

Ingress 配置的 HTTP(S) 负载平衡包含以下功能:

  • Service 的灵活配置。Ingress 定义了流量如何到达 Service 以及流量如何路由到您的应用。此外,Ingress 可为集群中的多个 Service 提供单个 IP 地址。
  • 与 Google Cloud 网络服务集成
  • 支持多个 TLS 证书。Ingress 可以指定使用多个 TLS 证书来终止请求。

如需查看完整列表,请参阅 Ingress 功能

容器原生负载平衡

容器原生负载平衡是使用网络端点组 (NEG) 直接将负载平衡到 GKE 中的 Pod 端点的做法。

使用实例组时,Compute Engine 负载平衡器会将流量发送到作为后端的虚拟机 IP。在虚拟机上运行共用同一个主机接口的容器时,存在一些限制:

  • 这会产生负载平衡的两个跃点:一个是从负载平衡器到虚拟机 NodePort 的跃点,另一个是通过 kube-proxy 到 Pod IP(可能位于其他虚拟机)的跃点。
  • 额外的跃点会增加延迟时间,并使流量路径更加复杂。
  • Compute Engine 负载平衡器无法直接查看 Pod,导致流量平衡不理想。
  • 虚拟机或 Pod 丢失等环境事件更有可能因双流量跃点而导致流量间歇性丢失。

借助 NEG,流量负载会从负载平衡器直接平衡到 Pod IP,而不是遍历虚拟机 IP 和 kube-proxy 网络。此外,系统会实现 Pod 就绪性门控,以便从负载平衡器的角度(而不仅仅是从 Kubernetes 集群内运行状况探测角度)确定 Pod 的运行状况。这样,负载平衡器基础架构就可以感知 Pod 启动、Pod 丢失或虚拟机丢失等生命周期事件,从而提高总体流量稳定性。这些功能可解决上述限制,从而使网络性能更高更稳定。

当满足下述所有条件时,系统将默认为 Service 启用容器原生负载平衡:

  • 适用于在 GKE 集群 1.17.6-gke.7 及更高版本中创建的 Service
  • 使用 VPC 原生集群
  • 不使用共享 VPC
  • 不使用 GKE 网络政策

在这些条件下,Service 会自动使用 cloud.google.com/neg: '{"ingress": true}' 进行注释,表明应创建 NEG 以镜像 Service 中的 Pod IP。NEG 可让 Compute Engine 负载平衡器直接与 Pod 通信。请注意,Service Controller 不会自动注释在 GKE 1.17.6-gke.7 及更高版本之前创建的现有 Service。

对于自动添加 NEG 注释的 GKE 1.17.6-gke.7 及更高版本的集群,可以停用 NEG,并在必要时强制 Compute Engine 负载平衡器将实例组用作其后端。这可以通过使用 cloud.google.com/neg: '{"ingress": false}' 明确注释 Service 来实现。

对于 NEG 不是默认设置的集群,我们强烈建议使用容器原生负载平衡,但必须按 Service 明确启用。您应该按照以下方式将注释应用于 Service:

kind: Service
...
  annotations:
    cloud.google.com/neg: '{"ingress": true}'
...

多个后端服务

每个外部 HTTP(S) 负载平衡器或内部 HTTP(S) 负载平衡器都使用单个网址映射,该网址映射会引用一个或多个后端服务。一个后端服务对应于 Ingress 引用的每个 Service。

例如,您可以配置负载平衡器,以根据网址路径将请求路由到不同的后端服务。发送到 your-store.example 的请求可路由到显示全价商品的后端服务,而发送到 your-store.example/discounted 的请求可路由到显示打折商品的后端服务。

您还可以将负载平衡器配置为根据主机名路由请求。发送到 your-store.example 的请求可转到一个后端服务,而发送到 your-experimental-store.example 的请求可转到另一个后端服务。

在 GKE 集群中,您可以通过创建 Kubernetes Ingress 对象来创建和配置 HTTP(S) 负载平衡器。一个 Ingress 对象必须与一个或多个 Service 对象相关联,每个 Service 对象与一组 Pod 相关联。

以下是名为 my-ingress 的 Ingress 的清单:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: my-products
          servicePort: 60000
      - path: /discounted
        backend:
          serviceName: my-discounted-products
          servicePort: 80

创建 Ingress 时,GKE Ingress 控制器会根据该 Ingress 及关联 Service 中的信息创建并配置外部 HTTP(S) 负载平衡器或内部 HTTP(S) 负载平衡器。此外,负载平衡器会获取稳定的 IP 地址,您可以将该 IP 地址与域名关联。

在上述示例中,假设您已将负载平衡器的 IP 地址与域名 your-store.example 关联。当客户端向 your-store.example 发送请求时,请求将路由到端口 60000 上名为 my-products 的 Kubernetes Service。当客户端向 your-store.example/discounted 发送请求时,请求将路由到端口 80 上名为 my-discounted-products 的 Kubernetes Service。

Ingress 的 path 字段唯一支持的通配符是 * 字符。* 字符必须紧跟在正斜线 (/) 之后,并且必须是格式中的最后一个字符。例如,/*/foo/*/foo/bar/* 是有效格式,但 *、/foo/bar*、/foo/*/bar 不是有效格式。

较具体的格式优先于不太具体的格式。如果您同时拥有 /foo/*/foo/bar/*,则选择 /foo/bar/bat 来匹配 /foo/bar/*

如需详细了解路径限制和格式匹配,请参阅网址映射文档

my-products Service 的清单可能如下所示:

apiVersion: v1
kind: Service
metadata:
  name: my-products
spec:
  type: NodePort
  selector:
    app: products
    department: sales
  ports:
  - protocol: TCP
    port: 60000
    targetPort: 50000

在该 Service 清单中,除非您使用容器原生负载平衡,否则必须使用 type: NodePort。如果使用容器原生负载平衡,请使用 type: ClusterIP

在该 Service 清单中,selector 字段指示同时具有 app: products 标签和 department: sales 标签的任何 Pod 都是该 Service 的成员。

当请求到达端口 60000 上的 Service 时,请求将被路由到 TCP 端口 50000 上的其中一个成员 Pod。

每个成员 Pod 必须有一个侦听 TCP 端口 50000 的容器。

my-discounted-products Service 的清单可能如下所示:

apiVersion: v1
kind: Service
metadata:
  name: my-discounted-products
spec:
  type: NodePort
  selector:
    app: discounted-products
    department: sales
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

在 Service 清单中,selector 字段显示,同时具有 app: discounted-products 标签和 department: sales 标签的任何 Pod 都是该 Service 的成员。

当请求到达端口 80 上的 Service 时,请求将被路由到 TCP 端口 8080 上的其中一个成员 Pod。

每个成员 Pod 必须有一个侦听 TCP 端口 8080 的容器。

默认后端

您可以通过在 Ingress 清单中提供 backend 字段来指定默认后端。与 rules 字段中的路径不匹配的任何请求都将发送到 backend 字段中指定的 Service 和端口。例如,在以下 Ingress 中,与 //discounted 不匹配的任何请求都将发送到端口 60001 上名为 my-products 的 Service。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: my-products
    servicePort: 60001
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: my-products
          servicePort: 60000
      - path: /discounted
        backend:
          serviceName: my-discounted-products
          servicePort: 80

如果未指定默认后端,则 GKE 会提供返回 404 的默认后端。

Ingress 与 Compute Engine 资源的映射

GKE Ingress 控制器会根据集群中部署的 Ingress 资源来部署和管理 Compute Engine 负载平衡器资源。Compute Engine 资源的映射取决于 Ingress 资源的结构。了解这些资源映射有助于您进行规划、设计和问题排查。

多个后端服务部分中显示的 my-ingress 清单通过两个网址路径匹配项(引用两个不同的 Kubernetes Service)指定了一个外部 Ingress 资源。以下是一些代表 my-ingress 创建的 Compute Engine 资源:

  • 转发规则和 IP 地址。
  • 允许针对负载平衡器运行状况检查的流量和来自 Google Front End 或 Envoy 代理的应用流量的 Compute Engine 防火墙规则。
  • 目标 HTTP 代理和目标 HTTPS 代理(如果您配置了 TLS)。
  • 具有一个引用单个路径匹配器的路径规则的网址映射。该路径匹配器有两个路径规则,一个针对 /*,另一个针对 /discounted。每个路径规则均映射到一个唯一的后端服务。
  • 包含作为端点的每个 Service 的 Pod IP 地址列表的 NEG。这些 NEG 是基于 my-discounted-productsmy-products Service 而创建的。下图简要展示了 Ingress 与 Compute Engine 资源的映射情况。

Ingress 与 Compute Engine 资源的映射图

提供 SSL 证书的方式

您可以通过三种方式为 HTTPS 负载平衡器提供 SSL 证书:

Google 管理的证书
您可以为自己的网域预配、部署、续订和管理 Google 管理的 SSL 证书。托管式证书不支持通配符网域。
与 Google Cloud 共享的自行管理证书
您可以在 Google Cloud 项目中预配自己的 SSL 证书并创建证书资源。然后,您可以在 Ingress 上的注释中列出该证书资源,以创建使用该证书的 HTTP(S) 负载平衡器。如需了解详情,请参阅预共享证书说明
作为 Secret 资源的自行管理证书
您可以预配自己的 SSL 证书并创建一个 Secret 来保存该证书。然后,您可以在 Ingress 规范中引用该 Secret,以创建使用该证书的 HTTP(S) 负载平衡器。如需了解详情,请参阅在 Secret 中使用证书的说明

运行状况检查

当您使用默认 Ingress 控制器通过 Ingress 公开一个或多个 Service 时,GKE 会创建一个 Google Cloud 外部 HTTP(S) 负载平衡器或 Google Cloud 内部 HTTP(S) 负载平衡器。这两个负载平衡器均支持单个网址映射上的多个后端服务。每个后端服务都对应一个 Kubernetes 服务,并且每个后端服务必须引用 Google Cloud 运行状况检查。此运行状况检查与 Kubernetes 活跃性探测或就绪性探测不同,因为运行状况检查在集群外部实现。

GKE 采用以下过程为与 Kubernetes Service 对应的每个后端服务创建运行状况检查:

  • 如果该 Service 引用包含 healthCheck 信息的 BackendConfig CRD,则 GKE 会使用该 CRD 来创建运行状况检查。Anthos Ingress 控制器和 GKE Ingress 控制器都支持以这种方式创建运行状况检查。

  • 如果该 Service 不引用 BackendConfig CRD:

    • 如果服务 Pod 使用的 Pod 模板具有其就绪性探测特性可解读为运行状况检查参数的容器,则 GKE 可推断运行状况检查的部分或全部参数。如需了解实现详情,请参阅来自就绪性探测的参数;如需查看可用于创建运行状况检查参数的特性列表,请参阅默认参数和推断的参数。只有 GKE Ingress 控制器支持从就绪性探测推断参数。

    • 如果该 Service 的服务 Pod 的 Pod 模板没有其就绪性探测特性可解读为运行状况检查参数的容器,则使用默认值来创建运行状况检查。Anthos Ingress 控制器和 GKE Ingress 控制器都只能使用默认值来创建运行状况检查。

默认参数和推断的参数

如果您没有使用 BackendConfig CRD为相应的 Service 指定运行状况检查参数,则系统会使用以下参数。

运行状况检查参数 默认值 可从就绪性探测推断的值
协议 HTTP 如果存在于服务 Pod 的 spec 中:
containers[].readinessProbe.httpGet.scheme
请求路径 / 如果存在于服务 Pod 的 spec 中:
containers[].readinessProbe.httpGet.path
请求主机标头 Host: backend-ip-address 如果存在于服务 Pod 的 spec 中:
containers[].readinessProbe.httpGet.httpHeaders
预期响应 HTTP 200 (OK) HTTP 200 (OK)
不可更改
检查时间间隔
  • 对于区域级 NEG:15 秒
  • 对于实例组:60 秒
如果存在于服务 Pod 的 spec 中:
  • 对于区域级 NEG:
    containers[].readinessProbe.periodSeconds
  • 对于实例组:
    containers[].readinessProbe.periodSeconds + 60 seconds
检查超时 5 秒 如果存在于服务 Pod 的 spec 中:
containers[].readinessProbe.timeoutSeconds
运行状况良好判断阈值 1 1
不可更改
运行状况不佳判断阈值
  • 对于区域级 NEG:2
  • 对于实例组:10
与默认值相同:
  • 对于区域级 NEG:2
  • 对于实例组:10
按编号
指定的端口
  • 对于区域级 NEG:Service 的 port
  • 对于实例组:Service 的 nodePort
如果 Ingress 对象的 backend.servicePort 引用 Service 的 port,则系统会使用该端口,前提是同时定义了以下内容:
  • 服务 Pod 的就绪性探测必须指定端口:
    spec.containers[].readinessProbe.httpGet.port
  • Service 的 targetPort 引用服务 Pod 的 containers[].spec.ports.containerPort
目的地 IP 地址
  • 对于区域级 NEG:Pod 的 IP 地址
  • 对于实例组:节点的 IP 地址
与默认值相同:
  • 对于区域级 NEG:Pod 的 IP 地址
  • 对于实例组:节点的 IP 地址

来自就绪性探测的参数

GKE 为 Service 的后端服务创建运行状况检查后,GKE 可以从该 Service 的服务 Pod 所使用的一个容器的就绪性探测中复制某些参数。仅 GKE Ingress 控制器支持此选项。

系统会列出可解读为运行状况检查参数的受支持就绪性探测特性以及默认参数和推断的参数中的默认值。默认值用于就绪性探测中未指定的任何特性,或者在完全未指定就绪性探测时使用。

如果您的 Service 的服务 Pod 包含多个容器,或者如果您使用的是 Anthos Ingress 控制器,则应使用 BackendConfig CRD 来定义运行状况检查参数。如需了解详情,请参阅何时改用 BackendConfig CRD

何时改用 BackendConfig CRD

在以下情况下,您应该通过为 Service 创建 BackendConfig CRD 来显式定义后端服务的运行状态检查参数,而不是依赖于来自 Pod 就绪性探测的参数。

  • 如果您使用的是 Anthos:Anthos Ingress 控制器支持从服务 Pod 的就绪性探测中获取运行状况检查参数。Anthos Ingress 控制器只能使用隐式参数或按 BackendConfig CRD 所定义的创建运行状况检查。

  • 如果服务 Pod 包含多个具有唯一就绪性探测的容器:如果 Service 的服务 Pod 包含多个容器,并且每个容器具有不同的就绪性探测设置,则应通过在相应 Service 上引用 BackendConfig CRD 来定义相应后端服务的运行状况检查。如果服务 Pod 中存在多个就绪性探测,则 GKE 不允许您选择从其中推断运行状况检查参数的特定就绪性探测。

  • 如果您需要控制负载平衡器的运行状况检查使用的端口:只有在就绪性探测的 containers[].readinessProbe.httpGet.port 与 Ingress spec.rules[].http.paths[].backend.servicePort 中引用的 Service 的服务端口匹配时,GKE 才将该端口用于后端服务的运行状况检查。

来自 BackendConfig CRD 的参数

您可以使用相应 Service 引用的 BackendConfig CRD 的 healthCheck 参数指定后端服务的运行状况检查参数。这样,您就可以更灵活地控制由 Ingress 创建的 Google Cloud 外部 HTTP(S) 负载平衡器或内部 HTTP(S) 负载平衡器的运行状况检查。如需了解 GKE 版本兼容性,请参阅 Ingress 特性

以下示例 BackendConfig CRD 在其 spec.healthCheck 特性中定义了运行状况检查协议(类型)、请求路径、端口和检查时间间隔:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: http-hc-config
spec:
  healthCheck:
    checkIntervalSec: 5
    port: 15020
    type: https
    requestPath: /healthz

使用多个 TLS 证书

假设您希望 HTTP(S) 负载平衡器从两个主机名(your-store.example 和 your-experimental-store.example)传送内容。此外,您希望负载平衡器为 your-store.example 使用一个证书,而为 your-experimental-store.example 使用其他证书。

您可以通过在 Ingress 清单中指定多个证书来实现此目的。如果某个证书中的公用名 (CN) 与请求中使用的主机名匹配,则负载平衡器会选择该证书。如需详细了解如何配置多个证书,请参阅将 HTTP(S) 负载平衡中的多个 SSL 证书与 Ingress 搭配使用

Kubernetes Service 与 Google Cloud 后端服务比较

Kubernetes ServiceGoogle Cloud 后端服务是不同的概念。二者之间存在密切的关系,但这种关系不一定是一对一的。GKE Ingress 控制器为 Ingress 清单中的每个 (serviceName, servicePort) 对创建 Google Cloud 后端服务。因此,一个 Kubernetes Service 对象可能与多个 Google Cloud 后端服务相关。

限制

  • 命名空间和 Ingress 名称的总长度不得超过 40 个字符。如果不遵守该规则,可能会导致 GKE Ingress 控制器发生异常。如需了解详情,请参阅 GitHub 上的此问题

  • 网址映射配额适用。

  • 如果您没有将 NEG 与 GKE Ingress 控制器搭配使用,则 GKE 集群最多只能有 1000 个节点。使用 NEG 部署服务时,GKE 节点数量没有限制。通过 Ingress 公开的任何非 NEG Service 都无法在超过 1000 个节点的集群上正常运行。

  • 如需使 GKE Ingress 控制器使用 readinessProbes 作为运行状况检查,在创建 Ingress 时必须存在 Ingress 的 Pod。如果您的副本调节至 0,则系统会应用默认的运行状况检查。如需了解详情,请参阅此问题评论

  • 在 Ingress 创建完成后,更改 Pod 的 readinessProbe 不会对其造成影响。

  • 外部 HTTP(S) 负载平衡器可在全球各处的地理位置终止 TLS,从而最大程度减少客户端与负载平衡器之间的延迟时间。如果您需要控制 TLS 终止的地理位置,应改用通过类型为 LoadBalancer 的 GKE Service 公开的自定义 Ingress 控制器,并终止位于所需地区的后端上的 TLS。

  • 不支持将多个 Ingress 资源合并到单个 Google Cloud 负载平衡器中。

后续步骤