Kubernetes v1.23 [beta]拓扑感知路由 会调整路由行为,优先将流量保留在发起流量的区域内。在某些情况下,这有助于降低成本或提高网络性能。
Kubernetes 集群越来越多地部署在多区域环境中。拓扑感知路由 提供了一种机制,有助于将流量保持在发起流量的区域内。在计算 Service 的端点时,EndpointSlice 控制器会考虑每个端点的拓扑结构(区域和可用区),并填充提示(hints)字段以将其分配给特定的可用区。集群组件(如 kube-proxy)随后可以使用这些提示,并利用它们来影响流量的路由方式(偏向于拓扑上更近的端点)。
service.kubernetes.io/topology-aware-hints 注解进行控制。您可以通过将 service.kubernetes.io/topology-mode 注解设置为 Auto 来为 Service 启用拓扑感知路由。当每个区域都有足够的可用端点时,EndpointSlice 上会填充拓扑提示,将各个端点分配给特定的区域,从而使流量被路由到更接近其发起位置的地方。
此特性在以下情况下效果最佳
如果大量流量来自单个区域,该流量可能会导致分配给该区域的端点子集过载。当预计入站流量来自单个区域时,不建议使用此特性。
在三区域集群中,这意味着 9 个或更多的端点。如果每个区域的端点少于 3 个,EndpointSlice 控制器有很大(≈50%)的概率无法均匀分配端点,而是退回到默认的全集群范围路由方式。
“Auto”启发式算法会尝试按比例将一定数量的端点分配给每个区域。请注意,此启发式算法对于具有大量端点的 Service 效果最佳。
当启用了此启发式算法时,EndpointSlice 控制器负责在 EndpointSlice 上设置提示。控制器会为每个区域分配成比例的端点。此比例基于在该区域运行的节点的 可分配 (allocatable) CPU 核心数。例如,如果一个区域有 2 个 CPU 核心,而另一个区域只有 1 个 CPU 核心,控制器会向拥有 2 个 CPU 核心的区域分配两倍的端点。
以下示例展示了填充了提示后的 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 组件会根据 EndpointSlice 控制器设置的提示来过滤其路由的目标端点。在大多数情况下,这意味着 kube-proxy 能够将流量路由到同一区域的端点。有时,控制器会分配来自不同区域的端点,以确保各区域之间端点的分布更均匀。这会导致部分流量被路由到其他区域。
Kubernetes 控制平面和每个节点上的 kube-proxy 在使用拓扑感知提示之前会应用一些保障规则。如果这些检查未通过,kube-proxy 会选择集群中任何位置的端点,而不考虑区域。
端点数量不足: 如果端点总数少于集群中的区域数,控制器将不会分配任何提示。
无法实现平衡分配: 在某些情况下,无法在各区域之间实现端点的平衡分配。例如,如果 zone-a 的规模是 zone-b 的两倍,但总共只有 2 个端点,那么分配给 zone-a 的端点可能接收的流量是 zone-b 的两倍。如果控制器无法将这种“预期过载”值降低到每个区域可接受的阈值以下,它就不会分配提示。重要的是,这不是基于实时反馈的。各个端点仍然有可能变得过载。
一个或多个节点缺少信息: 如果任何节点没有 topology.kubernetes.io/zone 标签,或者没有报告可分配 CPU 的值,控制平面就不会设置任何拓扑感知的端点提示,因此 kube-proxy 不会按区域过滤端点。
一个或多个端点没有区域提示: 当发生这种情况时,kube-proxy 会假定正在进行到拓扑感知提示的转换或反向转换。在这种状态下过滤 Service 的端点是危险的,因此 kube-proxy 会退回到使用所有端点。
提示中未包含某个区域: 如果 kube-proxy 无法找到至少一个指向其所在区域的提示端点,它将退回到使用所有区域的端点。这种情况最有可能在向现有集群添加新区域时发生。
当 Service 上的 internalTrafficPolicy 设置为 Local 时,不会使用拓扑感知提示。可以在同一个集群中对不同的 Service 使用这两个特性,但不能在同一个 Service 上同时使用。
对于大量流量源自部分区域的 Service,此方法效果不佳。此方法假设入站流量与每个区域中节点的容量大致成正比。
EndpointSlice 控制器在计算每个区域的比例时会忽略未就绪的节点。如果大量节点处于未就绪状态,可能会导致意外后果。
EndpointSlice 控制器会忽略设置了 node-role.kubernetes.io/control-plane 或 node-role.kubernetes.io/master 标签的节点。如果工作负载也在这些节点上运行,这可能会有问题。
EndpointSlice 控制器在部署或计算每个区域的比例时,不会考虑 污点容忍度 (tolerations)。如果支撑 Service 的 Pod 被限制在集群中的一部分节点上,这一点将不会被考虑在内。
此特性可能无法很好地与自动扩缩配合使用。例如,如果大量流量来自单个区域,则只有分配给该区域的端点才会处理这些流量。这可能导致 水平 Pod 自动扩缩器 (HPA) 无法捕获此事件,或者新添加的 Pod 启动在其他区域。
Kubernetes 的部署方式多种多样,没有单一的端点分配启发式算法能适用于所有场景。此特性的一个主要目标是,如果内置的启发式算法不适用于您的用例,能够开发自定义的启发式算法。在 1.27 版本中包含了启用自定义启发式算法的第一步。这是一个有限的实现,可能尚未涵盖某些相关且合理的场景。
service.kubernetes.io/topology-mode 注解密切相关,并为 Kubernetes 内的流量路由提供了灵活的选项。