在节点上控制拓扑管理策略
Kubernetes v1.27 [稳定]
越来越多的系统利用 CPU 和硬件加速器的组合来支持延迟敏感的执行和高吞吐量的并行计算。其中包括电信、科学计算、机器学习、金融服务和数据分析等领域的工作负载。这种混合系统构成了一个高性能环境。
为了获得最佳性能,需要进行与 CPU 隔离、内存和设备局部性相关的优化。然而,在 Kubernetes 中,这些优化由一组不相关的组件处理。
拓扑管理器是 kubelet 组件,旨在协调负责这些优化的一组组件。
开始之前
你需要有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具以与你的集群通信。建议在至少有两个不充当控制平面主机的节点的集群上运行本教程。如果你还没有集群,可以使用 minikube 创建一个集群,或者可以使用以下 Kubernetes 游乐场之一
你的 Kubernetes 服务器必须是 v1.18 或更高版本。要检查版本,请输入kubectl version
。拓扑管理器的工作原理
在引入拓扑管理器之前,Kubernetes 中的 CPU 和设备管理器彼此独立地做出资源分配决策。这可能会导致在多插槽系统上出现不良分配,并且对性能/延迟敏感的应用程序将因这些不良分配而受到影响。此处的不良分配意味着,例如,从不同的 NUMA 节点分配 CPU 和设备,从而导致额外的延迟。
拓扑管理器是一个 kubelet 组件,它充当事实来源,以便其他 kubelet 组件可以做出拓扑对齐的资源分配选择。
拓扑管理器为组件(称为提示提供程序)提供接口,以发送和接收拓扑信息。拓扑管理器有一组节点级策略,这些策略将在下面进行解释。
拓扑管理器从提示提供程序接收拓扑信息,该信息是一个位掩码,表示可用的 NUMA 节点和一个首选的分配指示。拓扑管理器策略对提供的提示执行一组操作,并收敛到策略确定的提示,以提供最佳结果。如果存储了不良提示,则该提示的首选字段将设置为 false。在当前策略中,首选是最窄的首选掩码。所选提示作为拓扑管理器的一部分存储。根据配置的策略,可以根据所选提示从节点接受或拒绝 Pod。然后,将该提示存储在拓扑管理器中,供提示提供程序在做出资源分配决策时使用。
Windows 支持
Kubernetes v1.32 [alpha]
(默认禁用:false)可以通过使用 WindowsCPUAndMemoryAffinity
特性门控在 Windows 上启用拓扑管理器支持,并且它需要在容器运行时中提供支持。
拓扑管理器作用域和策略
拓扑管理器当前
- 对齐所有 QoS 类的 Pod。
- 对齐提示提供程序提供拓扑提示的请求资源。
如果满足这些条件,拓扑管理器将对齐请求的资源。
为了自定义如何执行此对齐,拓扑管理器提供了两个不同的选项:scope
和 policy
。
scope
定义你希望执行资源对齐的粒度,例如,在 pod
或 container
级别。policy
定义用于执行对齐的实际策略,例如,best-effort
、restricted
和 single-numa-node
。有关当前可用的各种 scope
和 policy
的详细信息,请参见下文。
注意
要在 Pod 规约中将 CPU 资源与其他请求的资源对齐,应在节点上启用 CPU 管理器并配置适当的 CPU 管理器策略。请参阅控制节点上的 CPU 管理策略。注意
要在 Pod 规约中将内存(和巨页)资源与其他请求的资源对齐,应在节点上启用内存管理器并配置适当的内存管理器策略。请参阅内存管理器文档。拓扑管理器作用域
拓扑管理器可以处理几个不同作用域中的资源对齐
container
(默认)pod
可以通过在kubelet 配置文件中设置 topologyManagerScope
,在 kubelet 启动时选择任一选项。
container
作用域
默认情况下使用 container
作用域。你也可以在kubelet 配置文件中将 topologyManagerScope
显式设置为 container
。
在此作用域内,拓扑管理器执行多个连续的资源对齐,即,对于每个容器(在一个 Pod 中),计算单独的对齐。换句话说,对于此特定作用域,没有将容器分组到一组特定 NUMA 节点的概念。实际上,拓扑管理器对各个容器执行到 NUMA 节点的任意对齐。
为了支持将容器分组的概念,在以下作用域(例如 pod
作用域)中有意地实施了此概念。
pod
作用域
要选择 pod
作用域,请在kubelet 配置文件中将 topologyManagerScope
设置为 pod
。
此作用域允许将 Pod 中的所有容器分组到一组公共的 NUMA 节点。也就是说,拓扑管理器将 Pod 视为一个整体,并尝试将整个 Pod(所有容器)分配给单个 NUMA 节点或一组公共的 NUMA 节点。以下示例说明了拓扑管理器在不同情况下产生的对齐
- 所有容器可以并且分配给单个 NUMA 节点;
- 所有容器可以并且分配给一组共享的 NUMA 节点。
根据有效请求/限制公式计算整个 Pod 所需的特定资源总量,因此,此总值等于以下项的最大值
- 所有应用程序容器请求的总和,
- 初始化容器请求的最大值,
对于资源。
将 pod
作用域与 single-numa-node
拓扑管理器策略结合使用,对于延迟敏感的工作负载或执行 IPC 的高吞吐量应用程序尤其有价值。通过组合这两个选项,你可以将 Pod 中的所有容器放置在单个 NUMA 节点上;因此,可以消除该 Pod 的 NUMA 间通信开销。
在 single-numa-node
策略的情况下,仅当在可能的分配中存在合适的 NUMA 节点集时,才接受 Pod。重新考虑上面的示例
- 仅包含一个 NUMA 节点的集合 - 它导致 Pod 被接纳,
- 而包含更多 NUMA 节点的集合 - 它会导致 Pod 被拒绝(因为需要两个或更多 NUMA 节点来满足分配,而不是一个 NUMA 节点)。
总而言之,拓扑管理器首先计算一组 NUMA 节点,然后根据拓扑管理器策略对其进行测试,这会导致拒绝或接纳 Pod。
拓扑管理器策略
拓扑管理器支持四种分配策略。你可以通过 kubelet 标志 --topology-manager-policy
设置策略。支持四种策略
none
(默认)best-effort
restricted
single-numa-node
注意
如果拓扑管理器配置了 pod 作用域,则策略考虑的容器反映了整个 Pod 的需求,因此 Pod 中的每个容器都将导致 相同 的拓扑对齐决策。none
策略
这是默认策略,不执行任何拓扑对齐。
best-effort
策略
对于 Pod 中的每个容器,kubelet 在使用 best-effort
拓扑管理策略时,会调用每个 Hint Provider 来发现它们的资源可用性。利用这些信息,拓扑管理器会存储该容器的首选 NUMA 节点亲和性。如果亲和性不是首选的,拓扑管理器会存储此信息,但仍然允许 Pod 进入节点。
Hint Providers 可以在做出资源分配决策时使用此信息。
restricted
策略
对于 Pod 中的每个容器,kubelet 在使用 restricted
拓扑管理策略时,会调用每个 Hint Provider 来发现它们的资源可用性。利用这些信息,拓扑管理器会存储该容器的首选 NUMA 节点亲和性。如果亲和性不是首选的,拓扑管理器将拒绝该 Pod 进入节点。这将导致 Pod 进入 Terminated
状态,并出现 Pod 准入失败。
一旦 Pod 进入 Terminated
状态,Kubernetes 调度器将不会尝试重新调度该 Pod。建议使用 ReplicaSet 或 Deployment 来触发 Pod 的重新部署。也可以实现外部控制循环来触发具有 Topology Affinity
错误的 Pod 的重新部署。
如果 Pod 被允许进入,那么 Hint Providers 可以在做出资源分配决策时使用此信息。
single-numa-node
策略
对于 Pod 中的每个容器,kubelet 在使用 single-numa-node
拓扑管理策略时,会调用每个 Hint Provider 来发现它们的资源可用性。利用这些信息,拓扑管理器会确定是否可以实现单一 NUMA 节点亲和性。如果可以,拓扑管理器将存储此信息,并且 Hint Providers 可以在做出资源分配决策时使用此信息。但是,如果这不可能,则拓扑管理器将拒绝该 Pod 进入节点。这将导致 Pod 进入 Terminated
状态,并出现 Pod 准入失败。
一旦 Pod 进入 Terminated
状态,Kubernetes 调度器将不会尝试重新调度该 Pod。建议使用带有副本的 Deployment 来触发 Pod 的重新部署。也可以实现外部控制循环来触发具有 Topology Affinity
错误的 Pod 的重新部署。
拓扑管理器策略选项
对拓扑管理器策略选项的支持需要启用 TopologyManagerPolicyOptions
特性门控(默认情况下已启用)。
您可以根据其成熟度级别,使用以下特性门控来切换各组选项的启用和禁用状态
TopologyManagerPolicyBetaOptions
默认启用。启用后显示 Beta 级别的选项。TopologyManagerPolicyAlphaOptions
默认禁用。启用后显示 Alpha 级别的选项。
您仍然必须使用 TopologyManagerPolicyOptions
kubelet 选项来启用每个选项。
prefer-closest-numa-nodes
prefer-closest-numa-nodes
选项自 Kubernetes 1.32 起为 GA。在 Kubernetes 1.32 中,只要启用了 TopologyManagerPolicyOptions
特性门控,默认情况下此策略选项是可见的。
默认情况下,拓扑管理器不了解 NUMA 距离,并且在做出 Pod 准入决策时不会考虑它们。此限制在多插槽以及单插槽多 NUMA 系统中都会出现,并且如果拓扑管理器决定将资源对齐在非相邻的 NUMA 节点上,则可能导致延迟敏感型执行和高吞吐量应用程序的性能显著下降。
如果您指定 prefer-closest-numa-nodes
策略选项,则 best-effort
和 restricted
策略在做出准入决策时会倾向于选择彼此之间距离较短的 NUMA 节点集。
您可以通过将 prefer-closest-numa-nodes=true
添加到拓扑管理器策略选项来启用此选项。
默认情况下(没有此选项),拓扑管理器会将资源对齐在单个 NUMA 节点上,或者在需要多个 NUMA 节点的情况下,使用最少数量的 NUMA 节点。
max-allowable-numa-nodes
(beta)
max-allowable-numa-nodes
选项自 Kubernetes 1.31 起为 Beta 版本。在 Kubernetes 1.32 中,只要启用了 TopologyManagerPolicyOptions
和 TopologyManagerPolicyBetaOptions
特性门控,默认情况下此策略选项是可见的。
准入 Pod 的时间与物理机器上的 NUMA 节点数量相关。默认情况下,Kubernetes 不会在检测到超过 8 个 NUMA 节点的任何(Kubernetes)节点上运行启用拓扑管理器的 kubelet。
注意
如果您选择max-allowable-numa-nodes
策略选项,则允许在具有超过 8 个 NUMA 节点的节点上启用拓扑管理器运行。Kubernetes 项目仅对在具有超过 8 个 NUMA 节点的(Kubernetes)节点上使用拓扑管理器的影响进行了有限的数据收集。由于缺乏数据,不建议在 Kubernetes 1.32 中使用此策略选项,风险自负。您可以通过将 max-allowable-numa-nodes=true
添加到拓扑管理器策略选项来启用此选项。
设置 max-allowable-numa-nodes
的值本身不会影响 Pod 准入的延迟,但是将 Pod 绑定到具有许多 NUMA 的(Kubernetes)节点确实会产生影响。未来,Kubernetes 的潜在改进可能会提高 Pod 准入性能,并改善随着 NUMA 节点数量增加而出现的高延迟问题。
Pod 与拓扑管理器策略的交互
考虑以下 Pod 清单中的容器
spec:
containers:
- name: nginx
image: nginx
此 Pod 在 BestEffort
QoS 类中运行,因为未指定任何资源 requests
或 limits
。
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
此 Pod 在 Burstable
QoS 类中运行,因为 requests 小于 limits。
如果选择的策略不是 none
,拓扑管理器将考虑这些 Pod 规范。拓扑管理器将咨询 Hint Providers 以获取拓扑提示。在 static
的情况下,CPU 管理器策略将返回默认拓扑提示,因为这些 Pod 未明确请求 CPU 资源。
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "2"
example.com/device: "1"
requests:
memory: "200Mi"
cpu: "2"
example.com/device: "1"
此具有整数 CPU 请求的 Pod 在 Guaranteed
QoS 类中运行,因为 requests
等于 limits
。
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "300m"
example.com/device: "1"
requests:
memory: "200Mi"
cpu: "300m"
example.com/device: "1"
此具有共享 CPU 请求的 Pod 在 Guaranteed
QoS 类中运行,因为 requests
等于 limits
。
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
example.com/deviceA: "1"
example.com/deviceB: "1"
requests:
example.com/deviceA: "1"
example.com/deviceB: "1"
此 Pod 在 BestEffort
QoS 类中运行,因为没有 CPU 和内存请求。
拓扑管理器将考虑上述 Pod。拓扑管理器将咨询 Hint Providers,即 CPU 和设备管理器,以获取 Pod 的拓扑提示。
对于具有整数 CPU 请求的 Guaranteed
Pod,static
CPU 管理器策略将返回与独占 CPU 相关的拓扑提示,设备管理器将返回所请求设备的提示。
对于具有共享 CPU 请求的 Guaranteed
Pod,由于没有独占 CPU 请求,static
CPU 管理器策略将返回默认拓扑提示,设备管理器将返回所请求设备的提示。
在上述两个 Guaranteed
Pod 的案例中,none
CPU 管理器策略将返回默认拓扑提示。
对于 BestEffort
Pod,由于没有 CPU 请求,static
CPU 管理器策略将返回默认拓扑提示,设备管理器将返回每个请求设备的提示。
使用此信息,拓扑管理器计算 Pod 的最佳提示并存储此信息,Hint Providers 在进行资源分配时将使用该信息。
已知限制
拓扑管理器允许的最大 NUMA 节点数为 8。当尝试枚举可能的 NUMA 亲和性并生成它们的提示时,超过 8 个 NUMA 节点会导致状态爆炸。有关更多选项,请参阅
max-allowable-numa-nodes
(beta)。调度器不感知拓扑,因此可能会被调度到某个节点上,然后由于拓扑管理器而在该节点上失败。