Gateway 流量管理

本页面介绍了 Gateway 流量管理的工作原理。

概览

Google Kubernetes Engine (GKE) 网络基于 Cloud Load Balancing 构建而成。

借助 GKE Gateway Controller,GKE 用户可以以声明式 Kubernetes 原生方式控制流量管理。

流量管理

负载均衡、自动扩缩和容量管理是流量管理系统的基础。它们会协同工作,以使系统负载均衡且稳定。

  • 负载均衡会根据位置、健康状况和不同的负载均衡算法将流量分配到后端 Pod 中。
  • 自动扩缩会扩缩工作负载副本以创建更多容量,从而吸收更多流量。
  • 容量管理会监控 Service 的利用率,以便流量可以溢出到具有容量的后端,而不会影响应用的可用性或性能。

流量管理功能

Gateway、HTTPRoute、Service 和 Policy 资源提供了用于在 GKE 中管理流量的控制功能。GKE Gateway 控制器是监控这些资源的控制平面。

在 GKE 中部署 Service 时,可以使用以下流量管理功能:

  • Service 容量:能够指定在 Pod 自动扩缩或流量溢出到其他可用集群之前 Service 可以接收的流量容量。
  • 基于流量的自动扩缩:根据每秒收到的 HTTP 请求数在 Service 内自动扩缩 Pod。
  • 流量拆分:在后端中进行明确基于权重的流量分配。 正式版的单集群 Gateway 支持流量分配。

流量管理支持

可用的流量管理功能取决于您部署的 GatewayClass。如需查看功能支持的完整列表,请参阅 GatewayClass 功能。下表汇总了 GatewayClass 对流量管理的支持:

GatewayClass Service 容量 流量自动扩缩 多集群负载均衡 流量分配1
gke-l7-regional-external-managed
gke-l7-rilb
1 正式版的单集群 Gateway 支持流量分配。

区域和可用区负载均衡

Service 容量、位置和健康状况都决定了负载均衡器发送到给定后端的流量。负载均衡决策是在以下级别做出的:

  • 区域:流量会按可用区的可用服务容量的比例跨可用区进行负载均衡。如需了解详情,请参阅区域负载均衡
  • Zonal:在确定特定可用区的流量后,负载均衡器会在该可用区内的后端之间均匀地分配流量。现有的 TCP 连接和会话持久性设置会保留,因此只要后端 Pod 健康状况良好,未来的请求就会转到相同的后端。如需了解详情,请参阅可用区负载均衡

阻止流量溢出

流量溢出有助于防止任何可能影响性能或可用性的应用容量超额。

但是,您可能不希望让流量溢出。比方说,对延迟敏感的应用可能不会因流量溢出到更远的后端而受益。

您可以使用以下任一方法阻止流量溢出:

  • 仅使用单集群 Gateway,该 Gateway 只能在单个集群中托管 Service。
  • 将 Service 容量设置为足够高,除非绝对必要,否则流量容量绝不会实际超出。

区域内的负载均衡

在一个区域内,流量会根据后端的可用容量分配到可用区中。这种情况不使用溢出,而是与每个可用区中的 Service 容量成正比进行负载均衡。任何单个流或会话都会始终发送到单个一致的后端 Pod,并且不会拆分。

下图展示了流量在区域内的分配方式:

流量在区域内分配

在图中:

  • Service 部署在区域级 GKE 集群中。该 Service 有 4 个 Pod,不均匀地部署在可用区中。3 个 Pod 位于可用区 A 中,1 个 Pod 位于可用区 B 中,0 个 Pod 位于可用区 C 中。
  • 该 Service 配置为 maxRatePerEndpoint="10"。可用区 A 的总容量为 30 RPS,可用区 B 的总容量为 10 RPS,可用区 C 的容量为 0 RPS,因为其没有 Pod。
  • Gateway 总共收到来自不同客户端的 16 RPS 的流量。此流量会按每个可用区中的剩余容量的比例分配到可用区中。
  • 根据会话持久性设置,来自任何单个来源或客户端的流量流都会始终负载均衡到单个后端 Pod。流量分配会跨不同的来源流量流进行拆分,因此任何单个流都不会拆分。因此,若要在后端中精细地分配流量,则需要最少的来源或客户端多样性。

例如,如果传入流量从 16 RPS 激增到 60 RPS,则没有其他集群可供此流量溢出。即使传入流量超过总容量,流量仍会根据相对可用区容量进行分配。因此,可用区 A 收到 45 RPS,可用区 B 收到 15 RPS。

可用区内的负载均衡

流量发送到某个可用区后,它会在该可用区内的所有后端之间均匀分配。HTTP 会话会根据会话亲和性设置进行保留。除非后端变得不可用,否则现有 TCP 连接绝不会移动到其他后端。这意味着,即使新连接因容量有限而溢出,长期有效的连接仍会转到同一后端 Pod。负载均衡器会优先维护现有连接,而不是新连接。

Service 容量

借助 Service 容量,您可以在 Service 中定义每个 Pod 的每秒请求数 (RPS) 值。此值表示 Service 可以接收的平均每个 Pod 的 RPS 上限。此值可在 Service 中配置,用于确定基于流量的自动扩缩和基于容量的负载均衡。

要求

Service 容量有以下要求和限制:

  • 只有在您使用基于流量的自动扩缩时,才会影响负载均衡。否则,Service 容量不会影响网络流量。

配置 Service 容量

单集群网关

确保您的 GKE 集群运行的是 1.31.1-gke.2008000 或更高版本。早期版本可以使用“多集群网关”标签页中所述的 networking.gke.io/max-rate-per-endpoint 注解。

如需使用单集群网关配置 Service 容量,请创建 Service 和关联的 GCPBackendPolicy。使用以下清单创建 Service:

apiVersion: v1
kind: Service
metadata:
  name: store
spec:
  ports:
  - port: 8080
    targetPort: 8080
    name: http
  selector:
    app: store
  type: ClusterIP

使用 maxRatePerEndpoint 字段配置 GCPBackendPolicy 对象,并设置最高 RPS。使用以下清单配置 GCPBackendPolicy 对象:

apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
  name: store
spec:
  default:
    maxRatePerEndpoint: "RATE_PER_SECOND"
  targetRef:
    group: ""
    kind: Service
    name: store

多集群网关

如需使用多集群网关配置 Service 容量,请使用 networking.gke.io/max-rate-per-endpoint 注解创建 Service。使用以下清单创建具有最大 RPS 的 Service:

apiVersion: v1
kind: Service
metadata:
  name: store
annotations:
  networking.gke.io/max-rate-per-endpoint: "RATE_PER_SECOND"
spec:
  ports:
  - port: 8080
    targetPort: 8080
    name: http
  selector:
    app: store
  type: ClusterIP

RATE_PER_SECOND 替换为该 Service 中单个 Pod 应接收的每秒 HTTP/HTTPS 请求数上限。

maxRatePerEndpoint 值会根据 Service 中的 Pod 数量创建 Service 的动态容量。Service 总容量值的计算方法是将 maxRatePerEndpoint 值与副本数相乘,如以下公式所述:

Total Service capacity = maxRatePerEndpoint * number of replicas

如果自动扩缩器纵向扩容 Service 中的 Pod 数量,则系统会相应地计算 Service 的总容量。如果 Service 纵向缩容到零个 Pod,则它的容量为零,并且不会收到来自负载均衡器的任何流量。

Service 容量和独立 NEG

使用独立 NEG 时也可以配置 Service 容量,但它不使用 maxRatePerEndpoint 设置。使用独立 NEG 时,您可以在将 NEG 添加到后端服务资源时手动配置 maxRatePerEndpoint。使用 gcloud compute backend-services add-backend 命令时,--max-rate-per-endpoint 标志可以单独为每个 NEG 配置容量。

这在使用独立 NEG 手动部署内部和外部负载均衡器时非常有用。

使用独立 NEG 配置服务容量时,在功能上并没有区别。系统同时支持流量自动扩缩和流量溢出。

确定 Service 的容量

确定 maxRatePerEndpoint 的值需要了解应用的性能特征和负载均衡目标。以下策略可帮助您定义应用性能特征:

  • 在没有 Service 容量的情况进行配置时,在测试和生产环境中观察您的应用。
  • 使用 Cloud Monitoring 在流量请求与性能服务等级目标 (SLO) 之间创建相关性。
  • 定义哪些性能 SLO 适用于您的应用。这可能是以下一项或多项,具体取决于哪些您认为是“不佳”或“不稳定”性能。您可以从 Cloud Monitoring 负载均衡器指标中收集以下所有项:
    • 响应错误代码
    • 响应或总延迟时间
    • 后端健康状况不佳或停机
  • 在测试和生产环境中观察流量负载状态下的应用。在测试环境中,在请求负载增加的情况下对应用施加压力,以便您了解不同的性能指标在流量增加时的影响。在生产环境中,观察实际流量模式级别。

默认 Service 容量

关联到 GKE 资源的所有 Service 都配置了默认 Service 容量,即使它未明确配置也是如此。如需了解详情,请参阅默认 Service 容量

下表介绍了默认容量:

负载均衡资源类型 默认 maxRatePerEndpoint
Ingress(内部和外部) 1 RPS
Gateway(所有 GatewayClass) 1 亿 RPS

基于流量的自动扩缩

基于流量的自动扩缩是 GKE 的一项功能,以原生方式集成来自负载均衡器的流量信号,从而自动扩缩 Pod。 只有单集群 Gateway 才支持基于流量的自动扩缩。

基于流量的自动扩缩具有以下优势:

  • 非严格受限于 CPU 或内存的应用可能具有容量限制,这些限制不会反映在 CPU 或内存用量中。
  • 在某些情况下,流量或每秒请求次数 (RPS) 是更易于理解的指标,因为该指标与应用使用情况和业务指标(如网页浏览量或日活跃用户数 (DAU))更一致。
  • 与作为滞后指标的 CPU 或内存相比,流量是表示瞬时需求的先行指标。
  • 如果将 CPU、内存和流量自动扩缩指标组合,可全面地自动扩缩使用多个维度的应用,以确保容量得到适当预配。

下图展示了基于流量的自动扩缩的工作原理:

基于流量的自动扩缩

在图中:

  • Service 所有者为 Deployment 配置 Service 容量和目标利用率。
  • Gateway 从转到 store Service 的客户端接收流量。Gateway 将利用率遥测数据发送到 GKE Pod 自动扩缩器。利用率等于单个 Pod 收到的实际流量除以 Pod 配置的容量。
  • GKE Pod 自动扩缩器根据配置的目标利用率纵向扩容或纵向缩容 Pod。

自动扩缩行为

下图展示了基于流量的自动扩缩在通过负载均衡器接收 10 RPS 的应用上的工作原理:

10 RPS 时基于流量的自动扩缩

在该图中,服务所有者将 store Service 的容量配置为 10 RPS,这意味着每个 Pod 最多可接收 10 RPS。HorizontalPodAutoscaler 在 averageValue 设置为 70 时进行配置,这意味着目标利用率为每个 Pod 10 RPS 的 70%。

自动扩缩器会尝试扩缩副本以实现以下等式:

replicas = ceiling[ current traffic / ( averageValue * maxRatePerEndpoint) ]

在该图中,此等式计算为:

ceiling[ 10 rps / (0.7 * 10 rps) ] = ceiling[ 1.4 ] = 2 replicas

10 RPS 的流量会生成 2 个副本。每个副本会收到 5 RPS,这低于目标利用率 7 RPS。

流量拆分

流量拆分使用显式比率(称为权重),用于定义发送到 Service 的 HTTP 请求的比例。HTTPRoute 资源可让您在 Service 列表中配置权重。Service 之间的相对权重定义了它们之间的流量拆分。在发布、Canary 版更改或紧急情况时拆分流量非常有用。

下图描述了流量拆分配置示例:

流量拆分配置

在图中:

  • 服务所有者为单个路由配置两个服务,其规则为将 90% 流量分配到 store-v1,将 10% 流量分配到 store-v2
  • Gateway 接收从客户端到商店应用的流量,并且流量会根据配置的规则进行分配。90% 的流量路由到 store-v1,而 10% 的流量路由到 store-v2

流量分配用于在应用版本发布时分配流量。 使用流量分配示例时,您会有两个单独的 Deployment store-v1store-v2,每个 Deployment 均有自己的 Service store-v1store-v2。两个 Service 之间的权重配置为逐步迁移流量,直到 store-v2 全面发布。

权重与容量

权重和容量都用于控制将多少流量发送到不同 Service。虽然效果类似,但它们的工作方式和使用场景不同。尽管它们用于不同用途,但可以且应该结合使用。

权重

权重是显式控制流量。它定义了流量的准确比例,这与传入流量和后端利用率无关。在流量拆分示例中,如果 store-v2 容量过大,或者其所有副本都失败,则仍有 10% 的流量分配到 store-v2,这可能导致流量被丢弃。这是因为权重不会根据利用率或健康状况更改流量比例。

权重最适合以下使用场景:

  • 在 Service 的不同版本之间迁移流量以进行发布。
  • 使用明确的流量分配手动初始配置 Service。
  • 出于紧急或维护目的,将流量从一组后端迁出。

容量

容量是隐式控制流量。它间接定义了流量比例,因为该比例取决于传入流量、后端利用率和流量来源位置。容量是 Service 的固有属性,通常更新频率会低得多。

容量最适合以下使用场景:

  • 防止流量高峰期间的后端利用率过高。
  • 控制与流量相关的自动扩缩速率。

后续步骤