拓扑感知路由

拓扑感知路由 提供了一种机制,有助于将网络流量保留在其源自的区域内。在集群中 Pod 之间优先使用同一区域的流量有助于提高可靠性、性能(网络延迟和吞吐量)或降低成本。
特性状态: Kubernetes v1.23 [beta]

拓扑感知路由 会调整路由行为,优先将流量保留在其源自的区域内。在某些情况下,这有助于降低成本或提高网络性能。

动机

Kubernetes 集群越来越多地部署在多区域环境中。拓扑感知路由 提供了一种机制,有助于将流量保留在其源自的区域内。在计算 Service 的 Endpoint 时,EndpointSlice 控制器会考虑每个 Endpoint 的拓扑(区域和可用区),并填充 hints 字段将其分配给一个可用区。然后,kube-proxy 等集群组件可以消费这些 hints,并使用它们来影响流量的路由方式(倾向于拓扑上更近的 Endpoint)。

启用拓扑感知路由

通过将 service.kubernetes.io/topology-mode 注解设置为 Auto,可以为 Service 启用拓扑感知路由。当每个可用区都有足够多的 Endpoint 时,EndpointSlice 上会填充拓扑提示,以便将单个 Endpoint 分配给特定可用区,从而使流量更接近其源头。

何时效果最佳

当以下条件满足时,此特性效果最佳:

1. 入站流量均匀分布

如果大部分流量源自单个可用区,则该流量可能会使分配给该可用区的 Endpoint 子集过载。当预计入站流量源自单个可用区时,不建议使用此特性。

2. Service 在每个可用区有 3 个或更多 Endpoint

在一个三可用区集群中,这意味着 9 个或更多 Endpoint。如果每个可用区少于 3 个 Endpoint,EndpointSlice 控制器将有很高的概率(≈50%)无法均匀分配 Endpoint,而是回退到默认的集群范围路由方式。

工作原理

"Auto" 启发式算法会尝试按比例将一定数量的 Endpoint 分配到每个可用区。请注意,此启发式算法对于具有大量 Endpoint 的 Service 效果最佳。

EndpointSlice 控制器

当启用此启发式算法时,EndpointSlice 控制器负责在 EndpointSlice 上设置 hints。控制器会按比例将一定数量的 Endpoint 分配给每个可用区。此比例基于在该可用区运行的节点的可分配 CPU 核数。例如,如果一个可用区有 2 个 CPU 核,而另一个可用区只有 1 个 CPU 核,控制器将为拥有 2 个 CPU 核的可用区分配两倍数量的 Endpoint。

以下示例显示了填充 hints 后 EndpointSlice 的样子

apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
  name: example-hints
  labels:
    kubernetes.io/service-name: example-svc
addressType: IPv4
ports:
  - name: http
    protocol: TCP
    port: 80
endpoints:
  - addresses:
      - "10.1.2.3"
    conditions:
      ready: true
    hostname: pod-1
    zone: zone-a
    hints:
      forZones:
        - name: "zone-a"

kube-proxy

kube-proxy 组件会根据 EndpointSlice 控制器设置的 hints 过滤其路由到的 Endpoint。在大多数情况下,这意味着 kube-proxy 能够将流量路由到同一可用区中的 Endpoint。有时,控制器会分配来自不同可用区的 Endpoint,以确保 Endpoint 在可用区之间分布更均匀。这会导致一些流量被路由到其他可用区。

防护措施

Kubernetes 控制平面和每个节点上的 kube-proxy 在使用拓扑感知 hints 之前会应用一些防护规则。如果这些规则不满足,kube-proxy 会从集群中的任何位置选择 Endpoint,无论其可用区如何。

  1. Endpoint 数量不足:如果集群中的 Endpoint 数量少于可用区数量,控制器将不会分配任何 hints。

  2. 无法实现均衡分配:在某些情况下,无法实现 Endpoint 在可用区之间的均衡分配。例如,如果可用区 a 的大小是可用区 b 的两倍,但只有 2 个 Endpoint,则分配给可用区 a 的 Endpoint 可能接收到比可用区 b 多两倍的流量。如果无法将每个可用区的“预期过载”值降至可接受的阈值以下,则控制器不会分配 hints。重要的是,这并非基于实时反馈。个别 Endpoint 仍然可能发生过载。

  3. 一个或多个 Node 信息不足:如果任何节点没有 topology.kubernetes.io/zone 标签或未报告可分配 CPU 的值,控制平面就不会设置任何拓扑感知 Endpoint hints,因此 kube-proxy 也不会按可用区过滤 Endpoint。

  4. 一个或多个 Endpoint 没有可用区 hint:发生这种情况时,kube-proxy 假定正在进行从或到拓扑感知 hints 的转换。在此状态下过滤 Service 的 Endpoint 将是危险的,因此 kube-proxy 会回退到使用所有 Endpoint。

  5. 某个可用区未在 hints 中表示:如果 kube-proxy 找不到至少一个带有针对其运行可用区 hint 的 Endpoint,它会回退到使用来自所有可用区的 Endpoint。这种情况最可能发生在向现有集群添加新可用区时。

约束

  • 当 Service 的 internalTrafficPolicy 设置为 Local 时,不会使用拓扑感知 hints。可以在同一个集群中的不同 Service 上使用这两种特性,但不能在同一个 Service 上使用。

  • 这种方法不适用于大量流量源自部分可用区的 Service。相反,它假设入站流量大致与每个可用区中 Node 的容量成比例。

  • EndpointSlice 控制器在计算每个可用区的比例时会忽略未就绪的节点。如果大量节点未就绪,这可能会导致意外后果。

  • EndpointSlice 控制器会忽略带有 node-role.kubernetes.io/control-planenode-role.kubernetes.io/master 标签集的节点。如果工作负载也运行在这些节点上,这可能会产生问题。

  • EndpointSlice 控制器在部署或计算每个可用区的比例时,不考虑tolerations。如果 Service 后端的 Pod 仅限于集群中的节点子集,则不会考虑这一点。

  • 这可能与自动扩缩容配合得不好。例如,如果大量流量源自单个可用区,则只有分配给该可用区的 Endpoint 会处理该流量。这可能导致Horizontal Pod Autoscaler 未检测到此事件,或者新添加的 Pod 启动在不同的可用区。

定制启发式算法

Kubernetes 的部署方式多种多样,没有一种通用的启发式算法适用于所有用例来将 Endpoint 分配到可用区。此特性的一个关键目标是,如果内置的启发式算法不适用于你的用例,则可以开发定制的启发式算法。启用定制启发式算法的第一步已包含在 1.27 版本中。这是一个有限的实现,可能尚未涵盖某些相关且合理的情况。

接下来

最后修改时间:2024 年 6 月 4 日 11:40 AM PST:修复 topology-aware-routing.md 中的断链 (b0b5779581)