本文已超过一年。较旧的文章可能包含过时内容。请检查页面中的信息自发布以来是否已失效。

功能亮点:CPU Manager

这篇博文描述了 CPU管理器,这是 Kubernetes 中的一个 Beta 功能。CPU管理器功能通过为某些 Pod 容器分配独占 CPU,从而改进了 Kubernetes 节点代理 Kubelet 中工作负载的放置。

cpu manager

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

这取决于您的工作负载。一个 Kubernetes 集群中的单个计算节点可以运行许多 Pod,其中一些 Pod 可能运行 CPU 密集型工作负载。在这种情况下,Pod 可能会争用该计算节点上可用的 CPU 资源。当这种争用加剧时,工作负载可能会转移到不同的 CPU,具体取决于 Pod 是否受到限制以及调度时 CPU 的可用性。还可能存在工作负载对上下文切换敏感的情况。在上述所有情景下,工作负载的性能都可能受到影响。

如果您的工作负载对上述情景敏感,则可以启用 CPU管理器,通过为工作负载分配独占 CPU 来提供更好的性能隔离。

CPU管理器可能对具有以下特征的工作负载有帮助:

  • 对 CPU 限制效应敏感。
  • 对上下文切换敏感。
  • 对处理器缓存未命中敏感。
  • 受益于共享处理器资源(例如,数据和指令缓存)。
  • 对跨 Socket 内存流量敏感或有要求。
  • 对同一物理 CPU 核心的超线程敏感或需要超线程。

好的!我该如何使用它?

使用 CPU管理器很简单。首先,在集群计算节点上运行的 Kubelet 中启用带有静态策略的 CPU管理器。然后配置您的 Pod 属于 Guaranteed(保证)服务质量 (QoS) 等级。对于需要独占核心的容器,请求整数数量的 CPU 核心(例如,1000m4000m)。像以前一样创建您的 Pod(例如,kubectl create -f pod.yaml)。然后,瞧!CPU管理器将根据 Pod 中每个容器的 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"

请求两个独占 CPU 的 Pod 规范。

嗯…… CPU管理器是如何工作的?

对于 Kubernetes,以及本文的目的,我们将讨论大多数 Linux 发行版中可用的三种 CPU 资源控制。前两种是 CFS share(我在这个系统上的加权公平 CPU 时间份额是多少)和 CFS quota(我在一段时间内的 CPU 时间硬上限是多少)。CPU管理器使用了第三种控制方式,称为 CPU affinity(我被允许在哪些逻辑 CPU 上执行)。

默认情况下,Kubernetes 集群计算节点上运行的所有 Pod 和容器都可以在系统中的任何可用核心上执行。可分配的 share 和 quota 的总量受限于为 kubernetes 和系统守护进程明确保留的 CPU 资源。然而,可以使用 Pod 规范中的 CPU 限制来指定 CPU 时间的使用上限。Kubernetes 使用 CFS quota 对 Pod 容器强制执行 CPU 限制。

当启用“静态”策略的 CPU管理器时,它管理一个共享的 CPU 池。最初,这个共享池包含计算节点中的所有 CPU。当 Kubelet 创建一个 Guaranteed Pod 中具有整数 CPU 请求的容器时,该容器的 CPU 将从共享池中移除,并在容器的整个生命周期内独占分配。其他容器将从这些独占分配的 CPU 上迁移出去。

所有非独占 CPU 容器(Burstable, BestEffort 和具有非整数 CPU 请求的 Guaranteed Pod)都在共享池中剩余的 CPU 上运行。当一个具有独占 CPU 的容器终止时,其 CPU 将被添加回共享 CPU 池。

更多详情请看 ...

cpu manager

上图展示了 CPU 管理器的架构。CPU Manager 使用 Container Runtime Interface 的 UpdateContainerResources 方法来修改容器可以运行的 CPU。管理器会定期将每个正在运行容器的当前 CPU 资源状态与 cgroupfs 进行协调。

CPU Manager 使用策略来决定 CPU 的分配。实现了两种策略:None 和 Static。从 Kubernetes 1.10 版本开始,默认情况下启用 None 策略的 CPU Manager。

静态策略为 Guaranteed QoS 等级中请求整数 CPU 的 Pod 容器分配独占 CPU。在最佳努力的基础上,静态策略会尝试按照以下顺序从拓扑上分配 CPU:

  1. 如果可用且容器请求至少一个完整的 Socket 的 CPU,则分配同一物理 CPU Socket 中的所有 CPU。
  2. 如果可用且容器请求一个完整的核心的 CPU,则分配同一物理 CPU 核心中的所有逻辑 CPU(超线程)。
  3. 分配任何可用的逻辑 CPU,优先从同一 Socket 获取 CPU。

CPU Manager 如何改进性能隔离?

启用 CPU Manager 静态策略后,工作负载的性能可能会因以下原因得到提升:

  1. 可以为工作负载容器分配独占 CPU,而其他容器不共享这些 CPU 资源。因此,当涉及攻击性或协同定位工作负载时,我们期望由于隔离而获得更好的性能。
  2. 由于我们可以将 CPU 在工作负载之间进行分区,工作负载使用的资源之间的干扰会减少。这些资源可能不仅包括 CPU,还包括缓存层级和内存带宽。这有助于普遍提升工作负载的性能。
  3. CPU Manager 在最佳努力的基础上按照拓扑顺序分配 CPU。如果整个 Socket 空闲,CPU Manager 将独占分配空闲 Socket 的 CPU 给工作负载。这通过避免任何跨 Socket 流量来提升工作负载的性能。
  4. Guaranteed QoS Pod 中的容器受 CFS quota 的限制。非常突发的工作负载可能会被调度,在周期结束前耗尽其 quota,并被限制。在此期间,这些 CPU 可能有没有有意义的工作要做。由于 CPU quota 和静态策略分配的独占 CPU 数量之间的资源计算关系,这些容器不受 CFS 限制的影响(quota 等于 quota 周期内最大可能的 CPU 时间)。

好的!好的!有结果吗?

很高兴您问到了!为了了解在 Kubelet 中启用 CPU Manager 功能所带来的性能提升和隔离效果,我们在一个启用超线程的双 Socket 计算节点(Intel Xeon CPU E5-2680 v3)上进行了实验。该节点包含 48 个逻辑 CPU(每个物理核心有 2 路超线程,共 24 个物理核心)。在此,我们通过基准测试和真实世界的工作负载,展示了在三种不同场景下启用 CPU Manager 功能所带来的性能优势和隔离。

如何解读这些图表?

对于每种场景,我们展示了箱线图,说明了在启用和未启用 CPU Manager 的情况下,运行基准测试或真实世界工作负载的归一化执行时间及其差异性。运行的执行时间被归一化到表现最好的运行(y 轴上的 1.00 代表表现最好的运行,值越低越好)。箱线图的高度显示了性能的波动性。例如,如果箱线图是一条线,则表示在所有运行中性能没有波动。箱线图中,中间的线是中位数,上面的线是 75 百分位数,下面的线是 25 百分位数。箱线图的高度(即 75 百分位数和 25 百分位数之间的差值)定义为四分位距 (IQR)。触须(Whiskers)显示超出该范围的数据点,点表示离群值。离群值定义为低于下四分位数或高于上四分位数 1.5 倍 IQR 的任何数据点。每个实验都运行了十次。

免受攻击性工作负载的保护

我们在启用和未启用 CPU Manager 功能的情况下,运行了 PARSEC 基准测试套件中的六个基准测试(受害者工作负载),与一个 CPU stress 容器(攻击性工作负载)协同定位。CPU stress 容器作为 Pod 运行,属于 Burstable QoS 等级,请求 23 个 CPU,带有 --cpus 48 标志。基准测试作为 Pod 运行,属于 Guaranteed QoS 等级,请求一个完整 Socket 的 CPU(在此系统上为 24 个 CPU)。下图绘制了与 stress Pod 协同定位运行时,启用和未启用 CPU Manager 静态策略的基准测试的归一化执行时间。我们看到,在所有测试用例中,启用静态策略后性能有所提高,性能波动性降低。

execution time

协同定位工作负载的性能隔离

在本节中,我们演示了 CPU Manager 如何在协同定位工作负载场景中对多个工作负载带来益处。在下面的箱线图中,我们展示了 PARSEC 基准测试套件中的两个基准测试(Blackscholes 和 Canneal)在 Guaranteed (Gu) 和 Burstable (Bu) QoS 等级中相互协同定位运行时,启用和未启用 CPU Manager 静态策略的性能。

从左上方开始顺时针方向,我们分别展示了 Bu QoS 等级中的 Blackscholes(左上方)、Bu QoS 等级中的 Canneal(右上方)、Gu QoS 等级中的 Canneal(右下方)和 Gu QoS 等级中的 Blackscholes(左下方)的性能。在每种情况下,它们都分别与 Gu QoS 等级中的 Canneal(左上方)、Gu QoS 等级中的 Blackscholes(右上方)、Bu QoS 等级中的 Blackscholes(右下方)和 Bu QoS 等级中的 Canneal(左下方,从左上方顺时针方向)协同定位。例如,Bu-blackscholes-Gu-canneal 图(左上方)显示了当 Blackscholes 在 Bu QoS 等级中运行时,与 Gu QoS 等级中的 Canneal 协同定位时的性能。在每种情况下,Gu QoS 等级中的 Pod 请求一个完整 Socket 的核心(即 24 个 CPU),而 Bu QoS 等级中的 Pod 请求 23 个 CPU。

在所有测试中,两种协同定位工作负载的性能都有所提高,性能波动也较小。例如,考虑 Bu-blackscholes-Gu-canneal(左上角)和 Gu-canneal-Bu-blackscholes(右下角)的情况。它们显示了在启用和未启用 CPU 管理器的情况下同时运行 Blackscholes 和 Canneal 的性能。在这个特定情况下,Canneal 由于在 Gu QoS 等级中并请求整数数量的 CPU 核心,通过 CPU 管理器获得了独占核心。但 Blackscholes 也获得了一组独占 CPU,因为它在共享池中是唯一的工作负载。因此,Blackscholes 和 Canneal 都受益于 CPU 管理器带来的一些性能隔离优势。

performance comparison

独立工作负载的性能隔离

本节展示了 CPU Manager 为独立真实世界工作负载提供的性能提升和隔离。我们使用 TensorFlow 官方模型中的两个工作负载:wide and deepResNet。我们分别使用 census 和 CIFAR10 数据集进行 wide and deep 和 ResNet 模型。在每种情况下,Podwide and deepResNet 请求 24 个 CPU,这对应一个完整 Socket 的核心数。如图所示,CPU Manager 在两种情况下都能提供更好的性能隔离。

performance comparison

局限性

用户可能希望将 CPU 分配到靠近连接外部设备(例如加速器或高性能网卡)总线的 Socket 上,以避免跨 Socket 流量。CPU Manager 尚不支持这种对齐方式。由于 CPU Manager 在最佳努力的基础上分配属于 Socket 和物理核心的 CPU,它容易受到极端情况的影响,并可能导致碎片化。CPU Manager 不考虑 isolcpus Linux 内核引导参数,尽管据报道这对于某些低抖动用例来说是常见做法。

致谢

我们感谢为此功能做出贡献或提供反馈的社区成员,包括 WG-Resource-Management 和 SIG-Node 的成员。cmx.io(一个有趣的绘图工具)。

注意事项和免责声明

性能测试中使用的软件和工作负载可能已针对 Intel 微处理器进行性能优化。性能测试(例如 SYSmark 和 MobileMark)是使用特定的计算机系统、组件、软件、操作和功能进行测量的。对任何这些因素的任何更改都可能导致结果发生变化。您应参考其他信息和性能测试,以帮助您充分评估您的预期采购,包括该产品与其他产品结合时的性能。更多信息请访问 www.intel.com/benchmarks

Intel 技术的特性和优势取决于系统配置,可能需要启用硬件、软件或服务激活。性能因系统配置而异。任何计算机系统都不能做到绝对安全。请咨询您的系统制造商或零售商,或访问 intel.com 了解更多信息。

工作负载配置:https://gist.github.com/balajismaniam/fac7923f6ee44f1f36969c29354e3902 https://gist.github.com/balajismaniam/7c2d57b2f526a56bb79cf870c122a34c https://gist.github.com/balajismaniam/941db0d0ec14e2bc93b7dfe04d1f6c58 https://gist.github.com/balajismaniam/a1919010fe9081ca37a6e1e7b01f02e3 https://gist.github.com/balajismaniam/9953b54dd240ecf085b35ab1bc283f3c

系统配置:CPU 架构: x86_64 CPU 操作模式: 32-bit, 64-bit 字节序: Little Endian CPU(s): 48 在线 CPU(s) 列表: 0-47 每核心线程数: 2 每 Socket 核心数: 12 Socket(s): 2 NUMA 节点数: 2 厂商 ID: GenuineIntel 型号名称: Intel(R) Xeon(R) CPU E5-2680 v3 内存 256 GB 操作系统/内核 Linux 3.10.0-693.21.1.el7.x86_64

Intel, Intel logo, Xeon 是英特尔公司或其子公司在美国和/或其他国家/地区的商标。
*其他名称和品牌可能被声明为他人的财产。© 英特尔公司。