k8s中为什么要用CPU Manager?

默认情况下,kubelet 使用CFS配额来执行 Pod 的 CPU 约束。Kubernetes的Node节点会运行多个Pod,其中会有部分的Pod属于CPU密集型的工作负载。在这种情况下,Pod之间会争抢节点的CPU资源。当争抢剧烈的时候,Pod会在不同的CPU Core之间进行频繁的切换,更糟糕的是在NUMA Node之间的切换。这种大量的上下文切换,会影响程序运行的性能。

什么是cpu密集型?

通俗来讲就是对cpu依赖很高,操作cpu的频率非常高,充分的使用cpu资源来实现本地计算任务。

另外还有io密集型:

io密集型就是讲磁盘/内存的io操作会非常频繁,文件读写、网络请求等,这种一般cpu利用率会非常低

CPU Manager有什么缺点?

CPU Manager特性是节点级别的CPU调度选择,所以无法在集群维度中选择最优的CPU Core组合。同时CPU Manager特性要求Pod是Guaranteed时(Pod中的每个容器必须指定CPU Request和CPU Limit,并且两者要相等)才能生效,且无法适用于所有类型的Pod。

如何开启CPU Manager

cpu Manager 在 Kubernetes v1.12 引用为 [beta],故想要更好的使用它,版本需>=v1.12。

CPU 管理策略通过 kubelet 参数 --cpu-manager-policy 或 KubeletConfiguration 中的 cpuManagerPolicy 字段来指定。支持两种策略:

  • none: 默认策略,表示现有的调度行为。可以理解为不开启cpu manager。
  • static: 允许为节点上具有某些资源特征的 Pod 赋予增强的 CPU 亲和性和独占性。

none 策略

none 策略显式地启用现有的默认 CPU 亲和方案,不提供操作系统调度器默认行为之外的亲和性策略。通过 CFS 配额来实现 Guaranteed Pods和 Burstable Pods的 CPU 使用限制。

static 策略

static 策略针对具有整数型 CPU requests 的 Guaranteed Pod ,它允许该类 Pod中的容器访问节点上的独占 CPU 资源。这种独占性是使用cpuset cgroup 控制器来实现的。

CPU 管理器定期通过 CRI 写入资源更新,以保证内存中 CPU 分配与 cgroupfs 一致。同步频率通过新增的 Kubelet 配置参数 --cpu-manager-reconcile-period 来设置。如果不指定,默认与 --node-status-update-frequency 的周期(默认10s)相同。

Static 策略的行为可以使用 --cpu-manager-policy-options 参数来微调。该参数采用一个逗号分隔的 key=value 策略选项列表。此特性可以通过 CPUManagerPolicyOptions 特性门控来完全禁用。

更改CPU Manager策略

由于 CPU 管理器策略只能在 kubelet 生成新 Pod 时应用,所以简单地从 "none" 更改为 "static"将不会对现有的 Pod 起作用。因此,为了正确更改节点上的 CPU 管理器策略,请执行以下步骤:

  1. 腾空节点。就是将pod都在此节点驱逐,或者索性stop container。
  2. 停止 kubelet。
  3. 删除旧的 CPU 管理器状态文件。该文件的路径默认为 /var/lib/kubelet/cpu_manager_state。这将清除CPUManager 维护的状态,以便新策略设置的 cpu-sets 不会与之冲突。
  4. 编辑 kubelet 配置以将 CPU 管理器策略更改为所需的值。
  5. 启动 kubelet。

    对需要更改其 CPU 管理器策略的每个节点重复此过程。

说明: CPU 管理器不支持运行时下线和上线 CPUs。此外,如果节点上的 CPUs 集合发生变化,则必须驱逐节点上的 Pod,并通过删除 kubelet 根目录中的状态文件cpu_manager_state来手动重置 CPU Manager。

CPU Manager使用注意事项

此策略管理一个 CPU 共享池,该共享池最初包含节点上所有的 CPU 资源。可独占性 CPU 资源数量等于节点的 CPU 总量减去通过 kubelet --kube-reserved 或 --system-reserved参数保留的 CPU 资源。从 1.17 版本开始,可以通过 kubelet --reserved-cpus 参数显式地指定 CPU 预留列表。由 --reserved-cpus 指定的显式 CPU 列表优先于由 --kube-reserved 和 --system-reserved指定的 CPU 预留。通过这些参数预留的 CPU 是以整数方式,按物理核心 ID 升序从初始共享池获取的。共享池是 BestEffort 和 Burstable Pod 运行的 CPU 集合。Guaranteed Pod 中的容器,如果声明了非整数值的 CPU requests,也将运行在共享池的 CPU 上。只有 Guaranteed Pod 中,指定了整数型 CPU requests 的容器,才会被分配独占 CPU 资源。

说明: 当启用 static 策略时,要求使用 --kube-reserved 和/或 --system-reserved 或--reserved-cpus 来保证预留的 CPU 值大于零。这是因为零预留 CPU 值可能使得共享池变空。

例如:--kube-reserved=cpu=1,memory=0

当 Guaranteed Pod 调度到节点上时,如果其容器符合静态分配要求,相应的 CPU 会被从共享池中移除,并放置到容器的 cpuset 中。因为这些容器所使用的 CPU 受到调度域本身的限制,所以不需要使用 CFS 配额来进行 CPU 的绑定。换言之,容器 cpuset 中的 CPU 数量与 Pod 规约中指定的整数型 CPU limit 相等。这种静态分配增强了 CPU 亲和性,减少了 CPU 密集的工作负载在节流时引起的上下文切换。

CPU Manager yaml模板

正确模板:

spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "2"
requests:
memory: "200Mi"
cpu: "2"

该 Pod 属于 Guaranteed QoS 类型,因为其 requests 值与 limits相等。同时,容器对 CPU 资源的限制值是一个大于或等于 1 的整数值。所以,该 nginx 容器被赋予 2 个独占 CPU。

spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "2"

该 Pod 属于 Guaranteed QoS 类型,因其指定了 limits 值,同未指定requests,requests 值被设置为与 limits 值相等。同时,容器对 CPU 资源的限制值是一个大于或等于 1 的整数值。所以,该 nginx 容器被赋予 2 个独占 CPU。

错误模板:

spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "1.5"
requests:
memory: "200Mi"
cpu: "1.5"

该 Pod 属于 Guaranteed QoS 类型,因为其 requests 值与 limits相等。但是容器对 CPU 资源的限制值是一个小数。所以该容器运行在共享 CPU 池中。

spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "2"
requests:
memory: "100Mi"
cpu: "1"

该 Pod 属于 Burstable QoS 类型,因为其资源 requests 不等于 limits。所以该容器运行在共享 CPU 池中。

Static 策略选项

你可以使用以下特性门控根据成熟度级别打开或关闭选项组:

  • CPUManagerPolicyBetaOptions 默认启用。禁用以隐藏 beta 级选项。
  • CPUManagerPolicyAlphaOptions 默认禁用。启用以显示 alpha 级选项。

必须使用CPUManagerPolicyOptions kubelet 选项启用某个选项。

静态 CPUManager 策略存在以下策略选项:

  • full-pcpus-only(beta,默认可见)
  • distribute-cpus-across-numa(alpha,默认隐藏)

如果使用 full-pcpus-only 策略选项,static 策略总是会分配完整的物理核心。默认情况下,如果不使用该选项,static 策略会使用拓扑感知最适合的分配方法来分配 CPU。在启用了 SMT 的系统上,此策略所分配是与硬件线程对应的、独立的虚拟核。这会导致不同的容器共享相同的物理核心,该行为进而会导致吵闹的邻居问题。

启用该选项之后,只有当一个 Pod 里所有容器的 CPU 请求都能够分配到完整的物理核心时,kubelet 才会接受该 Pod。如果 Pod 没有被准入,它会被置于 Failed 状态,错误消息是SMTAlignmentError。

如果使用 distribute-cpus-across-numa 策略选项,在需要多个 NUMA 节点来满足分配的情况下,static 策略会在 NUMA 节点上平均分配 CPU。默认情况下,CPUManager 会将 CPU 分配到一个 NUMA 节点上,直到它被填满,剩余的 CPU 会简单地溢出到下一个 NUMA 节点。这会导致依赖于同步屏障(以及类似的同步原语)的并行代码出现不期望的瓶颈,因为此类代码的运行速度往往取决于最慢的工作线程(由于至少一个 NUMA 节点存在可用 CPU 较少的情况,因此速度变慢)。通过在 NUMA 节点上平均分配 CPU,应用程序开发人员可以更轻松地确保没有某个工作线程单独受到 NUMA 影响,从而提高这些类型应用程序的整体性能。

可以通过将 full-pcups-only=true 添加到 CPUManager 策略选项来启用 full-pcpus-only 选项。同样地,可以通过将 distribute-cpus-across-numa=true添加到 CPUManager 策略选项来启用 distribute-cpus-across-numa 选项。当两者都设置时,它们是“累加的”,因为 CPU 将分布在 NUMA 节点的 full-pcpus 块中,而不是单个核心。

Kubernetes-23:详解如何将CPU Manager做到游刃有余的更多相关文章

  1. [CB]Intel 2018架构日详解:新CPU&新GPU齐公布 牙膏时代有望明年结束

    Intel 2018架构日详解:新CPU&新GPU齐公布 牙膏时代有望明年结束 北京时间12月12日晚,Intel在圣克拉拉举办了架构日活动.在五个小时的演讲中,Intel揭开了2021年CP ...

  2. kubernetes 控制器详解【持续完善中】

    目录 资源创建详解 一:Pod及常用参数 1.简介 2.模板 3.删除pod 4.设置Pod主机名 5.镜像拉取策略(ImagePullPolicy) 二:RC 1.简介 2.模板 三:Deploym ...

  3. k8s入坑之路(2)kubernetes架构详解

    每个微服务通过 Docker 进行发布,随着业务的发展,系统中遍布着各种各样的容器.于是,容器的资源调度,部署运行,扩容缩容就是我们要面临的问题.   基于 Kubernetes 作为容器集群的管理平 ...

  4. 【转载】k8s入坑之路(2)kubernetes架构详解

    每个微服务通过 Docker 进行发布,随着业务的发展,系统中遍布着各种各样的容器.于是,容器的资源调度,部署运行,扩容缩容就是我们要面临的问题. 基于 Kubernetes 作为容器集群的管理平台被 ...

  5. Kubernetes Pod详解

    目录 基本概念 pod资源配额 容器的健康检查 静态pod 基本概念 Pod是kubernetes集群中最基本的资源对象.每个pod由一个或多个业务容器和一个根容器(Pause容器)组成.Kubern ...

  6. Kubernetes Controller详解

    运行容器化应用是Kubernetes最重要的核心功能.为满足不同的业务需要,Kubernetes提供了多种Controller,主要包括Deployment.DaemonSet.Job.CronJob ...

  7. Kubernetes ConfigMap详解,多种方式创建、多种方式使用

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 配置是程序绕不开的话题,在Kubernetes中使用ConfigMap来配置,它本质其实就是键值对.本文讲解如何 ...

  8. k8s入坑之路(10)kubernetes coredns详解

    概述 作为服务发现机制的基本功能,在集群内需要能够通过服务名对服务进行访问,那么就需要一个集群范围内的DNS服务来完成从服务名到ClusterIP的解析. DNS服务在kubernetes中经历了三个 ...

  9. 详解六大国产CPU处理器

    一个执着于技术的公众号 CPU作为计算机设备的运算和控制核心,负责指令读取.译码与执行,因研发门槛高.生态构建难,被认为是集成电路产业中的"珠穆朗玛峰". 纵观全球,Intel.A ...

随机推荐

  1. 直接远程下载或上传文件到linux系统中的简单办法

    如果执行sz 或者rz 没有这个命令,则安装lrzsz包执行:yum install lrzsz 等待安装完毕,然后一直输入Y即可. sz:将选定的文件发送(send)到本地机器 -a 以文本方式传输 ...

  2. 如何满足一个前端对 Mock 的全部幻想

    ​ 前端的痛苦 作为前端,最痛苦的是什么时候? 每个迭代,需求文档跟设计稿都出来了,静态页面唰唰两天就做完了.可是做前端又不是简单地把后端吐出来的数据放到页面上就完了,还有各种前端处理逻辑啊. 后端接 ...

  3. SprigCloud入门踩坑之创建bean失败

    昨天也是报同样的错误,恰好要去吃饭,着急就没找到问题,把项目删了,后续看了路飞大佬的通过pom导入依赖的方式,但是资源导入太慢随放弃. 昨晚熄灯前二十分钟又从头敲了一遍,敲好就断电了,没来得及启动,今 ...

  4. 日常使用mobx的小技巧

    日常使用mobx的小技巧 由于自己开发的项目都是中小型项目,所以在技术选型上使用了mobx.但是使用过程中发现关于mobx的技术文章并不多.于是萌发出写这篇文章的想法.请轻喷. 更新控制store渲染 ...

  5. petite-vue源码剖析-逐行解读@vue-reactivity之Map和Set的reactive

    本篇我们会继续探索reactive函数中对Map/WeakMap/Set/WeakSet对象的代理实现. Map/WeakMap/Set/WeakSet的操作 由于WeakMap和WeakSet分别是 ...

  6. Redis 内存满了怎么办?这样设置才正确!

    上回在<Redis 数据过期了会被立马删除么?>说到如果过期的数据太多,定时删除无法删除完全(每次删除完过期的 key 还是超过 25%),同时这些 key 再也不会被客户端请求,就无法走 ...

  7. 【学习笔记】CDQ分治(等待填坑)

    因为我对CDQ分治理解不深,所以这篇博客只是我现在的浅显理解有任何不对的,希望大佬指出. 首先就是CDQ分治适用的题型: (1)带修改,但修改互相独立 (2)必须允许离线 (3)解决数据结构的题,能把 ...

  8. 在centos 7 中 conda 环境和Python2.7 中安装远程jupyter

    折腾了半天,为了能够方便学习TensorFlow,搞了远程的jupyter,方便在本地使用它,今天填了不少坑. 装完后截图: 下面是一些步骤: 检查 Python 环境 CentOS 7.2 中默认集 ...

  9. Linux服务器如何识别移动硬盘?

    序言 通常我们使用的移动硬盘或U盘一般都是ntfs或fat32的文件系统,常跟服务器打交道的小伙伴,会经常遇到把移动硬盘或U盘上的数据拷贝到Linux服务器上.绝大多数Linux发行版内核支持fat3 ...

  10. linux网络配置,查看IP地址

    linux等等学习参考博客:https://www.cnblogs.com/pyyu/p/9276851.html 1.在安装好的linux上面输入cd /etc/sysconfig/network- ...