共计 5484 个字符,预计需要花费 14 分钟才能阅读完成。
<Kubelet 从入门到放弃 > 系列将对 Kubelet 组件由基础知识到源码进行深刻梳理。上一篇 zouyee 带各位看了 CPU 治理的相干内容,其中提及拓扑治理,本文将对此进行具体分析, 拓扑治理在 Kubernetes 1.18 时晋升为 Beta。TopologyManager 性能可实现 CPU、内存和外围设备(例如 SR-IOV VF 和 GPU)的 NUMA 对齐,从而使集群满足低提早需要。
一、背景介绍
注:下文 TopologyManager 简称为拓扑管理器
1.1 需要阐明
随着单服务器节点内的处理器数量、硬件加速器及其他外围设备日益增多,越来越多的零碎利用 CPU 和硬件加速器的组合来反对对提早要求较高的工作和高吞吐量的并行计算。这类负载包含电信、科学计算、机器学习、金融服务和数据分析等。如何优化提早敏感型的高性能并行计算利用的性能成了一个重大的挑战。
在引入拓扑管理器之前,CPU、内存和设施管理器在资源分配决策上彼此独立。这可能导致在多解决零碎上呈现与冀望不符的资源分配,因为这些与冀望不统一的调配,对性能或提早敏感的利用将受到影响,例如,CPU 和设施是从不同的 NUMA 节点调配的,因而会导致额定的提早。为了获得最佳性能,须要进行与 CPU 隔离、内存和设施局部性等无关的优化。
拓扑管理器是 Kubelet 中 ContainerManager 组件的一部分,充当存储分配资源信息的角色,以便 ContainerManager 组件能够做出与拓扑构造相适应的资源分配决策,以便在资源分配的时候实现拓扑构造上的对齐。留神拓扑治理不是独自起作用的,它和 CPU manager、memory manager、Device manager 独特为 Pod 分配资源,优化资源拜访。
1.2 NUMA
在 CPU 治理中,咱们曾经介绍了 NUMA 技术(再回顾一遍)。
NUMA
NUMA,以内存拜访的不一致性为代价,加重对总线和 memory 的带宽需要。这种构造对过程调度算法的要求较高,尽量减少跨 Node 的内存拜访次数,以晋升零碎性能。Core 之间会共享总线、内存等资源。如果 Core 的数量较少,则没什么问题,但随着 Core 的增多,对总线以及内存带宽的需要就会显著增大,最终总线和内存会成为零碎性能的瓶颈。
如下图所示,一个 NUMA Node 包含一个或者多个 Socket,以及与之相连的 local memory。一个多核的 Socket 有多个 Core。如果 CPU 反对 HT,OS 还会把这个 Core 看成 2 个 Logical Processor。
- Socket 是一个物理上的概念,指的是主板上的 cpu 插槽
- Node 是一个逻辑上的概念,上图中没有提及。因为 SMP 体系中各个 CPU 拜访内存只能通过繁多的通道,导致内存拜访成为瓶颈,cpu 再多也无用。起初引入了 NUMA,通过划分 node,每个 node 有本地 RAM,这样 node 内拜访 RAM 速度会十分快。但跨 Node 的 RAM 拜访代价会绝对高一点, 咱们用 Node 之间的间隔(Distance,形象的概念)来定义各个 Node 之间互访资源的开销。
- Core 就是一个物理 cpu, 一个独立的硬件执行单元,比方寄存器,计算单元等
- Thread 就是超线程(HyperThreading)的概念,是一个逻辑 cpu,共享 core 上的执行单元
- *
二、性能介绍
2.1 相干配置
在 Kubernetes 1.18 版本之前若须要启用拓扑管理器,须要在 Kublet 的个性门控处启用该个性。从 Kubernetes 1.18 版本开始,这一个性默认启动。--feature-gates="...,TopologyManager=<true|false>"
为了满足定制对齐形式需要,拓扑管理器提供了两种不同的形式:scope
和 policy
。
scope
定义了资源对齐的粒度(以后提供pod
与container
两种级别)。policy
定义了对齐时理论应用的策略(以后提供best-effort
、none
、restricted
、single-numa-node
等)。
留神:为了将 Pod 中的 CPU 与其余申请资源对齐,须要启用 CPU 治理并且配置适当的 CPU 管理策略。
a. 作用域
正如上文所述,拓扑管理器提供以下两种不同的资源对齐粒度:
container
(默认)pod
在 kubelet 启动时,能够应用
--topology-manager-scope
标记来配置其中任一粒度。1)容器作用域
默认应用的是
container
作用域,拓扑治理顺次进行一系列的资源对齐,即对每一个容器(蕴含在一个 Pod 里)独自计算对齐。拓扑治理会把单个容器任意地对齐到 NUMA 节点上。2)Pod 作用域
在启动 kubelet 时,配置
--topology-manager-scope=pod
,即可对齐粒度为pod
。该作用域容许把一个 Pod 里的所有容器作为一个分组,调配到一个独特的 NUMA 节点,即拓扑治理会把一个 Pod 当成一个整体,并且试图把整个 Pod(所有容器)调配到一个单个的 NUMA 节点或者一个独特的 NUMA 节点集。下例阐明了拓扑管理器在不同的场景下应用的对齐形式:
- 所有容器能够被调配到一个繁多的 NUMA 节点;
- 所有容器能够被调配到一个共享的 NUMA 节点汇合。
整个 Pod 申请的某种资源总量通过
request/limit
公式计算,因而,对某一种资源而言,该总量等于以下数值中的最大值: - 所有利用容器申请之和
- Init 容器申请的最大值
对于提早敏感或者 IPC 高吞吐量工作负载,在配置
Pod
作用域及single-numa-node
拓扑管理策略时,能够把一个 Pod 里的所有容器都放到繁多 NUMA 节点,使得该 Pod 打消了 NUMA 之间的通信开销。在
single-numa-node
策略下,只有当可能的调配计划中存在适合的 NUMA 节点集时,Kubelet 才会准入该 Pod。如下述的示例: - 节点集只蕴含单个 NUMA 节点时,Pod 就会被准入
- 节点集蕴含多个 NUMA 节点时,Pod 会被回绝
简而言之,拓扑管理器首先计算出 NUMA 节点集,而后应用拓扑管理策略来测试该汇合,从而决定回绝或者承受 Pod。
b. 策略
拓扑治理反对四种调配策略,在 Kubelet 启动时,能够通过 Kubelet 命令行
--topology-manager-policy
设置。以后反对的策略有四种:none
(默认)best-effort
restricted
single-numa-node
1)none
这是默认策略,不执行任何拓扑对齐。
2)best-effort
对于 Guaranteed 类 Pod 中的每个容器,配置
best-effort
拓扑管理策略的 kubelet 将调用每个Hint Provider
以确定资源可用性。应用此信息,拓扑管理器存储该容器的首选亲和性 NUMA 节点。如果亲和性不是首选,则拓扑管理器将存储该亲和性,并且无论如何都将 Pod 接收到该节点。之后
Hint Provider
在进行资源分配决策时应用该信息。3)restricted 策略
对于 Guaranteed 类 Pod 中的每个容器,配置了
restricted
拓扑管理策略的 Kubelet 调用每个Hint Provider
以确定其资源可用性。应用此信息,拓扑管理器存储该容器的首选亲和性 NUMA 节点。如果亲和性不是首选,则拓扑管理器将从节点中回绝此 Pod。这将导致 Pod 处于Terminated
状态。Pod 调度失败,Kubernetes 调度器不会尝试从新调度该 Pod,倡议应用 ReplicaSet 或者 Deployment 部署 Pod。如果 Pod 被容许运行在某节点,则
Hint Provider
能够在做出资源分配决策时应用此信息。4)single-numa-node 策略
对于 Guaranteed 类 Pod 中的每个容器,配置了
single-numa-nodde
拓扑管理策略的 Kubelet 调用每个Hint Provider
以确定其资源可用性。应用此信息,拓扑管理器确定繁多 NUMA 节点亲和性是否可能。如果是这样,则拓扑管理器将存储此信息,而后Hint Provider
能够在做出资源分配决定时应用此信息。如果不满足,则拓扑管理器将回绝该 Pod,这将导致 Pod 处于Terminated
状态。一旦 Pod 处于
Terminated
状态,Kubernetes 调度器将不会尝试从新调度该 Pod。倡议应用 ReplicaSet 或者 Deployment 来重新部署 Pod。2.2 Pod 配置
留神:对于 Pod 三种 QoS 介绍,后续会具体阐明。
因为没有指定资源
requests
或limits
,该 Pod 以BestEffort
QoS 运行。spec:
containers:- name: nginx
image: nginx
因为 requests 少于 limits,该 Pod 以
Burstable
QoS 运行。spec:
containers:- name: nginx
image: nginx
resources:
limits:
memory: “200Mi”
requests:
memory: “100Mi”针对上述 Pod,如果抉择的策略是
none
以外的任何其余策略,拓扑管理器都会评估这些 Pod 的资源应用。拓扑管理器会调用Hint Provider
,取得拓扑后果。若策略为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”上述 Pod 因为其
requests
值等于limits
值,因而以Guaranteed
QoS 运行。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 因为未指定 CPU 和内存申请,所以 Pod 以
BestEffort
QoS 类运行。总结如下:
- 对于
Guaranteed
类的 Pod, 如果 CPU 申请数为整数,CPU 管理器策略为static
时,将返回与 CPU 申请无关的 hint,而设施管理器将返回无关所申请设施的 hint。对于Guaranteed
类的 CPU 申请可共享的 Pod(非整数 CPU),CPU 管理器策略为static
时,将返回默认的拓扑 hint,因为没有排他性的 CPU 申请,而设施管理器则针对所申请的设施返回无关 hint。在上述两种Guaranteed
Pod 的状况中,CPU 管理器策略为none
时,返回默认的拓扑 hint。 - 对于
BestEffort
Pod,因为没有 CPU 申请,CPU 管理器策略为static
时,将发送默认 hint,而设施管理器将为每个申请的设施发送 hint。
基于此信息,拓扑管理器将为 Pod 计算最佳 hint 并存储该信息,为
Hint Provider
在进行资源分配时应用。2.3 示范阐明
例如,在图 1 中,蕴含 2 个 NUMA 节点,2 个 Socket(每个 Socket 具备 4 个 CPU,2 个 GPU 和 2 个 NIC),CPU 0-3、GPU 0 和 NIC 0 在 Socket 0 中,其属于 NUMA 0 节点,CPU 4-7、GPU 1 和 NIC 1 在 Socket 1 中,其属于 NUMA 1 节点。
只有相应外设实现 Device Plugin 接口,且 Kubelet 启用 Device Manager 时,Pod 才可能从设施插件提供的可用资源中申请设施资源(例如 intel.com/sriov、nvidia.com/gpu 等)。例如曾经实现 Device Plugin 接口的 Nvidia GPU 设施插件和 Intel SRIOV 网络设备插件。
假如 Kubelet 对于 CPUManager 启用了
static
策略,并且gpu-vendor.com
和nic-vendor.com
的设施插件已实现 Device Plugin 接口,则上面的 Pod 配置能够应用拓扑管理器以运行其选定的策略:spec:
containers:- name: numa-aligned-container
image: alpine
resources:
limits:
cpu: 2
memory: 200Mi
gpu-vendor.com/gpu: 1
nic-vendor.com/nic: 1依照图 1 资源状况,资源对齐后果如下所示:
{cpu: {0, 1}, gpu: 0, nic: 0}
{cpu: {0, 2}, gpu: 0, nic: 0}
{cpu: {0, 3}, gpu: 0, nic: 0}
{cpu: {1, 2}, gpu: 0, nic: 0}
{cpu: {1, 3}, gpu: 0, nic: 0}
{cpu: {2, 3}, gpu: 0, nic: 0}
{cpu: {4, 5}, gpu: 1, nic: 1}
{cpu: {4, 6}, gpu: 1, nic: 1}
{cpu: {4, 7}, gpu: 1, nic: 1}
{cpu: {5, 6}, gpu: 1, nic: 1}
{cpu: {5, 7}, gpu: 1, nic: 1}
{cpu: {6, 7}, gpu: 1, nic: 1}留神:(再次申明)如果某个 Pod 被拓扑管理器回绝,它的状态将为
Terminated
,并带有一个 Pod 准入谬误和“TopologyAffinityError
的起因阐明。一旦 Pod 处于该状态,Kubernetes 调度程序将不会尝试从新调度。