Kubernetes中CPU Manager的工作方式

注意事项 佩雷夫 :本文发表在Kubernetes官方博客上,由两名直接参与CPU Manager开发的英特尔员工撰写,CPU Manager是我们在1.8版本评估中所介绍的Kubernetes的一项新功能。 目前(例如,对于K8s 1.11),此功能处于beta状态,请在稍后的注释中进一步了解其功能。

该出版物讨论了CPU管理器 (Kubernetes中的beta功能)。 CPU Manager使您可以更好地在Kubelet中分配工作负载,即 通过将专用CPU分配给特定炉床的容器,在Kubernetes主机代理上运行。



听起来不错! 但是CPU管理器会帮助我吗?


取决于工作量。 Kubernetes集群中唯一的计算节点可以运行许多炉床,其中一些可以运行活跃于CPU消耗的负载。 在这种情况下,炉床可以争夺该节点上可用的过程资源。 当竞争加剧时,工作负载可能会转移到其他CPU,具体取决于它是否受到限制 ,以及在计划时可用的CPU。 另外,在某些情况下,工作负载对上下文切换很敏感。 在所有这些情况下,工作负载性能可能会受到影响。

如果您的工作负载对这种情况敏感,则可以通过将特定的CPU分配给负载来使CPU Manager提供更好的性能隔离。

CPU管理器可以通过以下功能帮助进行装载:

  • 对CPU节流效果敏感
  • 对上下文切换敏感;
  • 处理器高速缓存未命中;
  • 受益于划分处理器资源(例如,数据缓存和指令);
  • 处理器套接字之间的内存敏感内存(在Unix Stack Exchange上详细介绍了作者的想法- 大约翻译
  • 对CPU敏感或需要相同物理内核的超线程。

好吧 如何使用?


使用CPU Manager很容易。 首先, 使用在群集的计算节点上运行的Kubelet中的静态策略启用它 。 然后为壁炉配置保证服务质量(QoS)类。 为需要专用内核的容器请求整数个CPU内核(例如1000m4000m )。 按照前面的方法创建(例如, kubectl create -f pod.yaml )...瞧-CPU管理器将根据每个炉床容器的CPU需求为其分配专用的处理器内核。

 apiVersion: v1 kind: Pod metadata: name: exclusive-2 spec: containers: - image: quay.io/connordoyle/cpuset-visualizer name: exclusive-2 resources: # Pod is in the Guaranteed QoS class because requests == limits requests: # CPU request is an integer cpu: 2 memory: "256M" limits: cpu: 2 memory: "256M" 

需要2个专用CPU的炉膛规格。

CPU管理器如何工作?


我们考虑了大多数Linux发行版中可用的三种CPU资源控制类型,它们与Kubernetes和本出版物的目的有关。 前两个是CFS份额(我在系统中CPU时间的加权“诚实”份额)和CFS配额(这期间为我分配的最大CPU时间)。 CPU Manager还使用第三个,称为CPU亲和力(允许在其上执行逻辑CPU的计算)。

默认情况下,在Kubernetes集群节点上运行的所有Pod和容器都可以在任何可用的系统内核上运行。 分配的份额和配额总数受为Kubernetes和系统守护程序保留的CPU资源限制。 但是,可以使用炉床规格中的CPU限制来确定对使用的CPU时间的限制 。 Kubernetes使用CFS配额对炉膛容器实施CPU限制。

使用静态策略启用CPU管理器时,它将管理专用的CPU池。 最初,该池包含计算节点的整个CPU。 当Kubelet在炉膛中创建一个具有保证数量的专用处理器核心的容器时,分配给该容器的CPU将在其生存期内分配给它,并从共享池中删除。 其余容器的负载从这些专用核心转移到其他核心。

所有没有专用CPU的容器( BurstableBestEffort带有非整数CPU的保证容器)都在共享池中剩余的内核上运行。 当具有专用CPU的容器停止工作时,其内核将返回到共享池。

更多详细信息,请...




上图显示了CPU Manager的结构。 它使用容器运行时接口(CRI)中的UpdateContainerResources方法来更改运行容器的CPU。 Manager会定期将cgroupfs与每个正在运行的容器的CPU资源的当前状态匹配。

CPU管理器使用策略来决定CPU内核的分配。 实现了两个策略: NoneStatic 。 默认情况下,从Kubernetes版本1.10开始,通过None策略启用它。

静态策略将分配给CPU的Pod容器分配给保证的QoS类,该类请求整数个内核。 静态策略尝试以最佳拓扑方式并按以下顺序指定CPU:

  • 将所有CPU分配给一个处理器插槽(如果有),并且该容器要求一个CPU的数量至少为整个CPU插槽的数量。
  • 分配一个物理CPU内核的所有逻辑CPU(超线程)(如果可用),并且容器至少需要整个内核的CPU。
  • 分配任何可用的逻辑CPU优先于来自单个插槽的CPU。

CPU Manager如何改善计算隔离性?


在CPU管理器中启用静态策略后,由于以下原因之一,工作负载可以表现更好:

  • 可以将专用CPU分配给具有工作负载的容器,但不能分配给其他容器。 这些(其他)容器不使用相同的CPU资源。 因此,由于出现“攻击者” (CPU要求严格的进程- 大约Transl。或相邻工作负载的情况下的隔离,我们期望有更好的性能。
  • 工作负载使用的资源竞争较少,因为我们可以按工作负载本身划分CPU。 这些资源不仅可以包括CPU,还可以包括缓存层次结构和内存带宽。 这样可以提高整体工作负载性能。
  • CPU Manager根据可用的最佳选项以拓扑顺序分配CPU。 如果整个套接字都空闲,它将为其所有CPU分配工作负载。 由于套接字之间缺少流量,因此可以提高工作负载性能。
  • 具有QoS 保证的 Pod中的容器受CFS配额限制。 可以计划易于突然爆发的工作量,并在分配的期限结束之前超过其配额,从而限制了工作量。 此时所涉及的CPU既可以完成重要工作,又不是非常有用的工作。 但是,当配额CPU由专用CPU分配策略补充时,此类容器将不受CFS限制。

好吧 你有结果吗?


为了查看Kubelet中包含CPU Manager所提供的性能改进和隔离,我们在具有两个插槽(Intel Xeon CPU E5-2680 v3)和启用超线程的计算节点上进行了实验。 该节点由48个逻辑CPU(24个物理内核,每个具有超线程)组成。 下面显示了在三种不同情况下基准测试和实际工作负载所获得的CPU Manager的性能和隔离优势。

如何解释图表?


对于每种情况,都显示了图表( 跨度图 ,箱形图),这些图表说明了在启动基准测试或实际负载(打开和关闭CPU管理器)时的标准化执行时间及其可变性。 将运行时间归一化为表现最佳的启动(Y轴上的1.00代表最佳启动时间:图形的值越小越好)。 图表上绘图的高度显示了性能的变化。 例如,如果站点是一条线路,则这些启动的性能没有变化。 在这些区域中,中线是中位数,顶部是第75个百分点,而底部是第25个百分点。 图的高度(即第75个百分位数与第25个百分位数之间的差)定义为四分位间距(IQR)。 “胡子”显示此间隔之外的数据,点显示异常值。 排放定义为与IQR相差1.5倍(小于或大于相应四分位数)的任何数据。 每个实验进行10次。

积极防护


我们从一组PARSEC (工作量-“受害者”)中启动了六个基准测试[更多关于受害者工作量的信息,例如, 在这里 - 大约。 佩雷夫 ],然后在已打开和关闭CPU管理器的容器中加载CPU(“攻击者”工作负载)。

攻击者容器将与Burstable QoS类一起启动请求23个CPU标志--cpus 48 。 基准作为具有QoS 保证类的Pod运行,这需要一个完整插槽中的一组CPU(即该系统上的24个CPU)。 下图显示了标准化的Pod启动时间,在Pod攻击者旁边有一个基准,带有CPU Manager 静态策略,而没有CPU Manager 静态策略。 在所有测试案例中,启用该策略都可以提高性能,并减少性能差异。



相邻负载的绝缘


这证明了CPU管理器对于许多并置工作负载的有用性。 下面的跨度图显示了PARSEC集合( BlackscholesCanneal )中针对彼此相邻的保证 (Gu)和Burstable (Bu)QoS类启动的两个基准的性能,其中静态策略已打开和关闭。

从左上图顺时针方向看,我们看到Black chols的Bu QoS性能(左上), Canneal的Bu QoS性能(右上), Canneal的Gu QoS性能(右下)和Blackscholes的Gu QoS性能(左下)。 在每个图表上,它们都与Canneal(用于Gu QoS)(左上), Blackscholes用于Gu QoS(右上), Blackscholes用于Bu QoS(右下)和Canneal用于Bu QoS(左下)一起定位(再次沿顺时针方向)。相应地。 例如, Bu-blackscholes-Gu-canneal图 (左上方)显示了运行Bu QoS并位于Gu QoS类Canneal旁边的Blackscholes的性能。 在每种情况下,类别为Gu的QoS需要一个完整的套接字内核(即24个CPU),而类别为Bu QoS的则需要23个CPU。

在所有测试中,两个相邻工作负载都有更好的性能,并且性能差异较小。 例如,查看Bu-blackscholes-Gu-canneal (左上)和Gu-canneal-Bu-blackscholes (右下)。 它们显示了在打开和关闭CPU Manager的情况下运行BlackscholesCanneal的性能。 在这种情况下, Canneal从CPU管理器接收更多专用内核,因为它属于Gu QoS类,并请求整数个CPU内核。 但是, Blackscholes还获得了一组专用的CPU,因为这是共享池中唯一的工作负载。 因此,使用CPU Manager时, BlackscholesCanneal都可以利用负载隔离。



独立负载的绝缘


它展示了CPU Manager对于现实生活中的独立工作负载有多么有用。 我们从官方TensorFlow模型中提取了两个负载: 宽和深以及ResNet 。 将使用典型数据集(分别为人口普查和CIFAR10)。 在这两种情况下, 炉床wide和deepResNet )都需要24个CPU,相当于一个完整的插槽。 如图所示,在两种情况下,CPU Manager都可以提供更好的隔离。



局限性


用户可能希望在靠近总线的套接字上分配CPU,该总线连接到诸如加速器或高性能网卡之类的外部设备,以避免套接字之间的通信。 CPU管理器尚不支持这种类型的配置。 由于CPU Manager提供了最佳的插槽或物理核心CPU分配,因此它对极端情况敏感,并可能导致碎片。 尽管在某些情况下它是一种常用的做法,但CPU Manager并没有考虑isolcpus Linux内核的启动参数(有关此参数的更多详细信息,请参见,例如, 此处 - 大约翻译

译者的PS


另请参阅我们的博客:

Source: https://habr.com/ru/post/zh-CN418269/


All Articles