基于节点cpu精细化调度:cpusets-controller
问:在 Kubernetes 中,运行多个集群节点是否存在隐藏成本?
答:是的,因为并非 Kubernetes 节点中的所有 CPU
和 Memory
都可用于运行 Pod
。
在一个 Kubernetes 节点
中,CPU
和 Memory
分为:
- 操作系统
- Kubelet、CNI、CRI、CSI(+ 系统守护进程)
- Pods
- 驱逐门槛(Hard Eviction threshold)
Kubelet
原生的CPU Manager
对于每一次Pod
调度 binding
到 Node
时, 都会将计算 Node CPU是否够用
Node预留CPU资源 reservedCPUs(KubeReservedCPUs + SystemReservedCPUs + HardEvictionThresholds )并向上取整,最终最为reserved cpus
虽然,对预留资源做了限制
,但对于具体的核没有做到绑核
运行。如果需要对Pod进行绑核、亲核
部署 就再精细化实现了
场景
如果需要对 kubernetes
中使用 CPU 管理器
进行如下更加精细化管理:
- 解决在一个容器中可以同时使用独占cpu和共享cpu
- 支持conatiner级别 core亲和 和 绑核
- 兼容历史申请资源,优雅cgroup cpu驱逐
- 独占CPU支持 绑核
解决 传统应用上云
,特定业务绑核
运行 和 核心业务分级CPU亲和(CPU Arrinity
)部署
方案
方案一:kubelet 的 cm上直接扩展
直接在 Kubelet
中,添加CPUSets
对象中,添加DeviceID
和具体拓扑使用,并记录到CheckPoints
文件中。
优势:性能优,并且与Kubelet预分配
资源做到协同
缺点:
1)更改原生代码,非云原生;
2)多Kubernetes
管理和升级复杂;
3)Kubernetes社区
难落地,抽象和迭代困难
方案二:做云原生调度插件,替换/选用 kubelet CPU Manager
逻辑
Cpusets Controller
提供一种 Kubernetes
的设备插件,将 CPU
内核作为可 Device
的 Kubernetes
调度程序.
支持三种类型的 CPU 管理:
- CPU独占
- CPU共享
- CPU默认(兼容默认cpu方式)
包含 3
个核心组件:
device plugin
:Kubernetes
标准Device
插件,将 CPU 池作为可调度资源无缝集成到 Kubernetescontroller
:Kubernetes
标准Informer
,确保属于不同CPU Pooler
的容器始终在物理上相互隔离管理和设置webhook
: 准入 Webhook验证, 校验 CPU 池特定的用户请求是否合法
Device Plugin
的工作是通过现有的 Device Plugin API
将 cpu分配
作为可消耗资源
注册给 Kubelet
. Device Plugin
将 CPU
作为包含物理CPU ID
列表的环境变量传递给容器。默认情况下,应用程序可以根据给定的 CPU
列表设置其进程 CPU
亲和力,或者可以将其留给标准的 Linux Completely Fair Scheduler
。对于应用程序未实现设置其进程的 CPU
亲和力的功能的边缘情况,CPU Pool
提供了代表应用程序设置它的机制。通过将应用程序进程信息配置到其 Pod 规范
的注释字段来启用此选择加入功能。
Webhook
: 以根据启动二进制文件(安装、环境变量等)的需要来改变 Pod 的规范。
Controller
子组件通过 Linux cpusets
实现容器的完全物理分离。通过 Informer
不断地监视 Kubernetes
的 Pod API
,并在创建 Pod 或更改其状态(例如重新启动等)时触发。 shared
在共享的情况下,或者默认情况下容器没有明确要求任何池化资源。Controller
然后将计算出的集合提供给容器的 cgroupfs
文件系统 (cpuset.cpus
) 。
优势: 1)对CPU进一步池化,实现部分绑核能力; 2)对现有的部署不影响 3)特定绑核使用,使大颗粒高性能服务可上云; 缺点: 1)default 与 shared共享问题 2)Kubelet CPU Manager 与 CPUSet Controller协同问题
使用方式
配置
cpuset 池化配置描述
apiVersion: v1
kind: ConfigMap
metadata:
name: cpuset-configmap
namespace: kube-system #配置所在文件中
data:
cpuset-config.yaml: | #池化配置
pools:
exclusive:
cpus : "2-3"
shared:
cpus : "1"
default:
cpus: "0"
nodeSelector:
name: xxxx
xxxx.yaml : |
xxxx: xxxx
部署使用:
---
apiVersion: v1
kind: Pod
metadata:
name: cpuset-exclusive
spec:
containers:
...
- name: sharedtestcontainer
image: dongjiang1989/busyloop:latest
resources:
limits:
cmss.cn/shared: '160'
memory: 100Mi
requests:
cmss.cn/shared: '160'
memory: 100Mi
- name: exclusivetestcontainer
image: dongjiang1989/busyloop:latest
resources:
limits:
cmss.cn/exclusive: '1'
memory: 100Mi
requests:
cmss.cn/exclusive: '1'
memory: 100Mi
具体实现方式
通过 device plugin
将CPU资源
进行扩展注入:
apiVersion: v1
kind: ConfigMap
metadata:
name: cpuset-configmap
namespace: kube-system #对集群中各个机器进行cpu划分
data:
cpuset-xxx-config.yaml: | #池化配置:必须以.yaml结尾的文件
pools: # 将cpu可以分为 3类:exclusive、shared 和 default
exclusive: # 对于 exclusive 可以继续进行分组
cpus : "15-23"
exclusive_groupx:
cpus : "24-31"
exclusive_xxx:
cpus : "32-63"
shared: # 对于 shared 可以继续进行分组
cpus : "4-7"
shared_groupx:
cpus : "8-11"
default: # 对于 default 不能继续分组: default类似原生的cpu资源
cpus: "0-3"
nodeSelector:
name: xxxx
xxxx.yaml : |
xxxx: xxxx
注意 本身exclusive、shared 和 default
类型设计:
exclusive
独占型cpu
:只能将CPU
设置[0,1]
区间;shared
和default
是共享型cpu
:CPU
设置[0,1000]
即1000微核
exclusive 、shared和 default
的 cpus,不建议重叠; 如果重叠,会影响kernal
cpu漂移问题;- 池化配置:必须以
.yaml
结尾的文件 exclusive 、shared
内部再分组: 需要以exclusive_
或者shared_
作为 prefix- 通过
nodeSelector
对相同机器配置相同策略; 内部key-value,并且是且
关系
效果demo
[root@kcs-cpu-test-m-8mzmj /]# kubectl describe node kcs-cpu-test-s-wht2b
Name: kcs-cpu-test-s-wht2b
...
Capacity:
cmss.cn/exclusive: 2
cmss.cn/shared: 1k
cpu: 4
ephemeral-storage: 102350Mi
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 15899180Ki
pods: 128
Allocatable:
cmss.cn/exclusive: 2
cmss.cn/shared: 1k
cpu: 4
ephemeral-storage: 96589578081
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 15796780Ki
pods: 128
System Info:
Machine ID: a679d9cff58d494e972f86fccd3e26a9
System UUID: A56C5525-47D0-4185-B3D9-2BA12FD70297
Boot ID: c4aae965-044c-4b24-9340-838385a65a6e
Kernel Version: 4.14.78-300.el7.bclinux.x86_64
OS Image: BigCloud Enterprise Linux For LDK 7 (Core)
Operating System: linux
Architecture: amd64
Container Runtime Version: containerd://1.4.4
Kubelet Version: v1.21.5
Kube-Proxy Version: v1.21.5
PodCIDR: 172.19.3.0/24
PodCIDRs: 172.19.3.0/24
ProviderID: ecloud://a56c5525-47d0-4185-b3d9-2ba12fd70297
Non-terminated Pods: (47 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits Age
--------- ---- ------------ ---------- --------------- ------------- ---
default cpusets-test 0 (0%) 0 (0%) 200Mi (1%) 200Mi (1%) 31d
default deployment-lvm-687bd58669-4hsdf 0 (0%) 0 (0%) 0 (0%) 0 (0%) 80d
default example-hotrod-69f444fd9d-fjfpj 100m (2%) 100m (2%) 100M (0%) 100M (0%) 86d
default nginx-test 0 (0%) 0 (0%) 0 (0%) 0 (0%) 51d
default nginx-test-dongjiang 0 (0%) 0 (0%) 0 (0%) 0 (0%) 51d
....
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 3091m (77%) 3722m (93%)
memory 4607031306240m (28%) 3600398346240m (22%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-1Gi 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)
cmss.cn/exclusive 1 1
cmss.cn/shared 160 160
Events: <none>
开源工程
代码工程:https://github.com/kubeservice-stack/cpusets-controller
「如果这篇文章对你有用,请随意打赏」
如果这篇文章对你有用,请随意打赏
使用微信扫描二维码完成支付