Gateway 流量管理


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

概览

Google Kubernetes Engine (GKE) 网络基于 Cloud Load Balancing 构建而成。借助 Cloud Load Balancing,您可以使用单个任播 IP 地址来实现全球流量管理。Google 的流量管理具有全球和区域负载均衡、自动扩缩和容量管理功能,可提供均衡、稳定且低延迟的流量分配。借助 GKE Gateway 控制器,GKE 用户可以以声明式 Kubernetes 原生方式利用 Google 的全球流量管理控制。

如需尝试集群之间的流量溢出,请参阅部署基于容量的负载均衡。如需尝试基于流量的自动扩缩,请参阅基于负载均衡器流量的自动扩缩

流量管理

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

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

这些功能可以根据您的目标以不同的方式进行组合。例如:

  • 如果您想利用低费用的 Spot 虚拟机,则可能需要进行优化,从而将流量均匀地分配到 Spot 虚拟机中,但会影响延迟时间。使用负载均衡和容量管理时,GKE 会根据容量在各区域之间溢出流量,以便在任何可用位置充分利用 Spot 虚拟机。
  • 如果要以过度预配为代价优化用户延迟,您可以将 GKE 集群部署在多个区域中,并在负载增加时动态增加容量。使用负载均衡和自动扩缩时,GKE 会在流量高峰时自动扩缩 Pod 的数量,使流量无需溢出到其他区域。区域容量将增加,以便其能够尽可能靠近用户的位置完全处理负载。

下图展示了负载均衡、自动扩缩和容量管理协同工作:

“负载均衡、自动扩缩和容量管理”图

在该图中,gke-us 集群中的工作负载失败。负载均衡和健康检查会排空活跃连接,并将流量重定向到下一个最近的集群。gke-asia 中的工作负载收到的流量会超出其容量,因此会将负载分散到 gke-eugke-eu 由于 gke-usgke-asia 中的事件而收到超出正常负载的负载,因此 gke-eu 会自动扩缩以增加其流量容量。

如需详细了解 Cloud Load Balancing 如何处理流量管理,请参阅全球容量管理

流量管理功能

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

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

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

流量管理支持

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

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

全球、区域和可用区负载均衡

Service 容量、位置和健康状况都决定了负载均衡器发送到给定后端的流量。负载均衡决策是在以下级别做出的,从全球(表示全球负载均衡器)和区域(表示区域负载均衡器)开始:

  • 全球:流量会发送到最靠近客户端的 Google Cloud 区域,该客户端包含具有容量且健康状况良好的后端。只要区域有容量,就会接收其所有最近的流量。如果一个区域没有容量,则超额的流量会溢出到具有容量的次近区域。如需了解详情,请参阅全球负载均衡
  • 区域:流量会由负载均衡器发送到特定区域。流量会按可用区的可用服务容量的比例跨可用区进行负载均衡。如需了解详情,请参阅区域负载均衡
  • 可用区:在确定特定可用区的流量后,负载均衡器会在该可用区内的后端之间均匀地分配流量。现有的 TCP 连接和会话持久性设置会保留,因此只要后端 Pod 健康状况良好,未来的请求就会转到相同的后端。如需了解详情,请参阅可用区负载均衡

全球负载均衡和流量溢出

如需在您自己的集群中试用以下概念,请参阅基于容量的负载均衡

在正常情况下,流量会发送到最靠近客户端的后端。流量会在最靠近客户端的 Google 接入点 (PoP) 终止,然后遍历 Google 骨干网,直至到达最近的后端(由网络延迟时间确定)。如果一个区域中的后端没有剩余容量,则流量会溢出到包含具有容量的健康状况良好的后端的次近集群。如果某个可用区内不到 50% 的后端 Pod 健康状况不佳,则无论配置的容量如何,流量都会逐步故障切换到其他可用区或区域。

流量溢出仅会在以下情况下发生:

  • 您使用的是多集群 Gateway
  • 跨多个集群部署同一 Service,该 Service 由多集群 Gateway 处理。
  • 您配置了 Service 容量,使流量在一个集群中超出 Service 容量,但在其他集群中未超出。

下图展示了全球负载均衡如何与流量溢出配合工作:

全球负载均衡与流量溢出

在图中:

  • 多集群网关为 store Service 提供全球互联网负载均衡。该服务部署在两个 GKE 集群中:一个位于 us-west1,另一个位于 europe-west1。每个集群都在运行 2 个副本。
  • 每个 Service 都配置为 max-rate-per-endpoint="10",这意味着每个 Service 在每个集群中的总容量为 2 个副本 * 10 RPS = 20 RPS。
  • 北美的 Google PoP 收到 6 RPS。所有流量都会发送到具有容量且健康状况良好的最近后端,即 us-west1 中的 GKE 集群。
  • 欧洲 PoP 累计收到 30 RPS最近的后端位于 europe-west1 中,但它们的容量只有 20 RPS。由于 us-west1 中的后端容量超额,因此 10 RPS 会溢出到 us-west1,使其总共收到 16 RPS,并为每个 pod 分配 8 RPS。

阻止流量溢出

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

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

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

  • 仅使用单集群 Gateway,该 Gateway 只能在单个集群中托管 Service。
  • 即使使用多集群 Gateway,跨多个集群部署的应用的副本也可以部署为单独的 Service。从 Gateway 的角度来看,这可实现多集群负载均衡,但不会在集群之间聚合 Service 的所有端点。
  • 将 Service 容量设置为足够高,除非绝对必要,否则流量容量绝不会实际超出。

区域内的负载均衡

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

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

流量在区域内分配

在图中:

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

例如,如果传入流量从 16 RPS 急剧增加到 60 RPS,则会出现以下任一情况:

  • 如果使用单集群 Gateway,则没有其他集群或区域可供此流量溢出。即使传入流量超过总容量,流量仍会根据相对可用区容量进行分配。因此,可用区 A 收到 45 RPS,可用区 B 收到 15 RPS。
  • 如果将多集群 Gateway 与跨多个集群分布的 Service 搭配使用,则流量可以溢出到其他集群和其他区域,如全球负载均衡和流量溢出中所述。可用区 A 收到 30 RPS,可用区 B 收到 10 RPS,20 RPS 溢出到其他集群。

可用区内的负载均衡

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

Service 容量

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

要求

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

  • 只有在您使用基于流量的自动扩缩或多集群网关时,才会影响负载均衡。如果您没有使用这些功能,则 Service 容量不会影响网络流量。

配置 Service 容量

如需配置 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 请求数上限。

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

Total Service capacity = max-rate-per-endpoint * number of replicas

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

Service 容量和独立 NEG

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

这对于以下任何工作流都可能非常有用:

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

确定 Service 的容量

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

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

默认 Service 容量

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

下表介绍了默认容量:

负载均衡资源类型 默认 max-rate-per-endpoint
Ingress(内部和外部) 1 RPS
Gateway(所有 GatewayClass) 1 亿 RPS
MultiClusterIngress 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 在 averageUtilization 设置为 70 时进行配置,这意味着目标利用率为每个 Pod 10 RPS 的 70%。

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

replicas = ceiling[ current traffic / ( averageUtilization * max-rate-per-endpoint) ]

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

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

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

流量拆分

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

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

流量拆分配置

在图中:

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

同一集群中的 Service 之间以及不同集群中的 Service 之间都支持流量拆分:

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

  • ServiceImport 之间的流量拆分:用于在维护、迁移或紧急情况时,将流量迁移到或迁移出特定集群。ServiceImport 表示多集群 Service,支持在不同集群上的不同 Service 之间进行流量拆分。通过 Gateway 进行蓝绿多集群路由练习演示了如何跨集群拆分流量。

权重与容量

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

权重

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

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

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

容量

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

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

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

配置 Service 容量以溢出流量可能并不总是您期望的行为。请考虑全局负载均衡示例。Service 容量通过溢出流量来防止后端利用率过高,但对于已溢出的请求,这可能会导致额外的延迟时间,因为这些请求会传送到更远程的区域。

如果您的应用对过度利用率不是非常敏感,那么您可能需要配置非常高的 Service 容量,以使流量不太可能溢出到其他区域。如果应用的可用性或延迟时间对利用率过高很敏感,则溢出到其他集群或区域的流量可能比在利用率过高的后端吸收过多流量要好。如需详细了解如何为应用配置 Service 容量,请参阅确定 Service 的容量

后续步骤