k8s cpu独占优化
控制节点上的 CPU 管理策略
1.前言
在业务中使用Kubernetes编排容器时,通常会使用到Request & Limits参数对容器进行CPU与内存的使用限制.
但是对于某些比较消耗系统资源的业务,可能需要进行资源的独占分配(以保证其运行的性能).
所以使用单一的资源限制,还不能达到pod运行的性能,所以需要进行资源独占的分配编排.
在Kubernetes 版本> v1.12中,有CPU Manager技术去实现Pod级别的绑定运行CPU.
1.1 理解CPU Manager作用
每个worker节点运行多个pod,某些Pods可能会运行高CPU负载的业务,这些高负载的pod,很有可能在当前的节点上
抢占CPU的资源,影响当前节点上其他pod的运行性能.所以采用此技术来解决这个问题.
1.2 CPU 管理策略配置
CPU 管理策略通过 kubelet 参数 --cpu-manager-policy 来指定。Kubernetes 支持两种管理策略:
none: 默认策略,表示现有的调度行为。
static: 允许为节点上的某些消耗CPU资源的pod对cpu有独占性。
CPU管理器定期通过CRI写入资源更新,以保证内存中CPU分配与cgroupfs一致.
同步频率通过新增的 Kubelet 配置参数 --cpu-manager-reconcile-period 来设置.
如果不指定,默认与 --node-status-update-frequency 的周期相同。
1.3 none策略
none 策略显式地启用现有的默认CPU亲和方式,
不提供操作系统调度器默认行为之外的亲和性策略.
通过 CFS 配额来实现 Guaranteed pods 的 CPU 使用限制.
1.4 static 策略
static 策略针对具有整数型(容器对 CPU 资源的限制值是一个大于或等于1的整数值) CPU requests的 Guaranteed Pod,
它允许该类 Pod 中的容器访问节点上的独占CPU资源.
这种独占性是使用 cpuset cgroup 控制器来实现的.
#独占的CPU资源计算
可用的独占性 CPU 资源数量等于节点的 CPU 总量减去通过 --kube-reserved 或 --system-reserved 参数保留的 CPU 。
#注意事项
当启用static策略时,要求使用--kube-reserved
或 --system-reserved 或 --reserved-cpus 来保证预留的CPU值大于零.(避免cpu共享池为空)
1.5 具体配置
#增加参数配置
--cpu-manager-policy=static
--kube-reserved=cpu=0.5,memory=1G
--feature-gates=CPUManager=true
#配置项(注意修改主机名)
[root@node-1 bin]#cat >/etc/kubernetes/cfg/kubelet<<EOF
KUBELET_OPTS="--logtostderr=true \
--v=4 \
--hostname-override=192.168.91.21 \
--kubeconfig=/etc/kubernetes/cfg/kubelet.kubeconfig \
--bootstrap-kubeconfig=/etc/kubernetes/cfg/bootstrap.kubeconfig \
--config=/etc/kubernetes/cfg/kubelet.config \
--cert-dir=/etc/kubernetes/ssl \
--kube-reserved=cpu=0.5,memory=1G \
--cpu-manager-policy="static" \
--feature-gates="CPUManager=true" \
--pod-infra-container-image=docker.io/kubernetes/pause:latest"
EOF
#说明
--kube-reserved:节点保留的cpu与内存
#重启服务
[root@node-1 ~]# systemctl daemon-reload && systemctl restart kubelet
1.6 测试
#注意测试之前需要将节点cpu调整到4 CORE
#查询当前机器的核心
[root@node-1 ~]# cat /proc/cpuinfo | grep process
processor : 0
processor : 1
processor : 2
processor : 3
#导入镜像
[root@node-1 ~]# docker load -i k8s.gcr.io.pause.3.1.tar.gz
#创建yaml
[root@master-1 nginx]# cat nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: cpu-manager-demo
labels:
app: cpu-manager-demo
spec:
replicas: 2
selector:
matchLabels:
app: cpu-manager-demo
template:
metadata:
labels:
app: cpu-manager-demo
spec:
containers:
- name: cpu-manager-demo
image: nginx
resources:
requests:
cpu: 2
memory: "256M"
limits:
cpu: 2
memory: "256M"
ports:
- containerPort: 80
#创建deployment
[root@master-1 nginx]# kubectl apply -f nginx-deployment.yaml
deployment.apps/cpu-manager-demo created
#在节点获取容器
[root@node-1 ~]# docker ps | grep cpu-manager-demo
e5efcefacc84 nginx "/docker-entrypoint.…" 2 minutes ago
Up 2 minutes
k8s_cpu-manager-demo_cpu-manager-demo-67bbfc5d96-bvp5w_default_271fa62c-089f-4677-9c2b-778dfb898411_0
#获取容器pid
[root@node-1 ~]# docker inspect e5efcefacc84 | grep Pid
"Pid": 20114,
"PidMode": "",
"PidsLimit": null,
#查询 PID= 20114 的线程可用的CPU核心
[root@node-1 ~]# taskset -c -p 20114
pid 20114's current affinity list: 0,1
#如果没有设置CPU绑定,则是每个核心都可以运行
[root@node-3 ~]# taskset -c -p 5634
pid 5634's current affinity list: 0-3