kubernetes集群节点资源预留

概述

默认kubelet没配置资源预留应用没做应用资源限制情况下,那host上所有资源都是可以给pod调配使用的,这样很容易引起集群雪崩效应,比如集群内有一台上跑的pod没做resource limt导致占用资源过大导致将宿主机压死了,此时这个节点在kubernetes内就是一个no ready的状态了,kubernetes会将这台host上所有的pod在其他节点上重建,也就意味着那个有问题的pod重新跑在其他正常的节点上,将另外正常的节点压跨。循怀下去直到集群内所有主机都挂了,这就是集群雪崩效应。

如何避免?
在kubernetes中可以通过给kubelet配置参数预留资源给系统进程和kubernetes进程保证它们稳定运行。目前能实现到cpu、memory、ephemeral-storage层面的资源预留。
重点提两点
cpu:cpu是配置cpu shares实际上对应的是cpu的优先级,简单来说,这个在cpu繁忙时,它能有更高优先级获取更多cpu资源。

ephemeral-storage是kubernetes1.8开始引入的一个资源限制的对象,kubernetes 1.10版本中kubelet默认已经打开的了,到目前1.11还是beta阶段,主要是用于对本地临时存储使用空间大小的限制,如对pod的empty dir、/var/lib/kubelet、日志、容器可读写层的使用大小的限制。

配置
在讲配置之前我们先了解几个概念

Node capacity:节点总共的资源
kube-reserved:给kubernetes进程预留的资源
system-reserved:给操作系统预留的资源
eviction-threshold:kubelet eviction的阀值
allocatable:留给pod使用的资源

node_allocatable=Node_capacity-(kube-reserved+system-reserved+hard-eviction)

eviction-threshold
分两类:
1、kube-control-manager周期性的接收kubelet发送过来的心跳,检查所有节点的状态,当节点属于no ready时,驱逐重建上面的pod(默认超时5分钟)。
2、kubelet周期性的检查host上的资源,与配置项里面的配置进行比对,达到阀值后,按照优先级驱逐pod。

eviction-threshold实际上是对pod limit_resource的补充,因为limit_resource只能针对单个pod做资源限制,当这个pod达到限制的阀值后,kubelet便会oom_killer掉这个container,而eviction-threshold根据事先设定的Eviction Thresholds来触发Eviction,调用算法筛选出合适的几个pod,kill掉一个或多个pod回收资源,被eviction掉的pod会被kube-scheduler在其他节点重新调度起来。
eviction-threshold分两种类型
Soft Eviction Thresholds:达到触发值后,并不是马上去驱逐pod,而是等待一个缓冲时间,这个配置参考
https://kubernetes.io/docs/tasks/administer-cluster/out-of-resource/

Hard Eviction Thresholds:达到触发值后,直接筛选出对应的pod kill掉

两种配置方式
绝对值:memory.available<5Gi
百分比:memory.available<5%

配置kubelet资源预留

环境
kubernetes:v1.11
kubeadm:v1.11
os:ubuntu16.04

一台master+2台worker节点

机器配置
内存:8175176KB
CPU:2vcpu
磁盘:40G

resource-reserved依赖cgroup,所以需要提前将kubelet和docker的cgroup-driver对应好
在修改配置前,先查看node节点目前可用资源

1
kubectl describe node rke-node3

这里以cpu、ephemeral-storage、memory为参考,capacity为host本身资源,Allocatable为host实际可分配资源,这里可以看见在没配置资源预留的情况下,Allocatable基本上等于capacity,然后我们配置rke-node3的kubelet

1
vim /var/lib/kubelet/kubeadm-flags.env
1
2
3
4
5
6
7
--enforce-node-allocatable=pods,kube-reserved,system-reserved --kube-reserved-cgroup=/system.slice/kubelet.service --system-reserved-cgroup=/system.slice --kube-reserved=cpu=1,memory=2Gi, --system-reserved=cpu=500m,memory=1Gi

enforce-node-allocatable=pods,kube-reserved,system-reserved #默认为pod设置,但我们这里要给kube进程和system预留所以要加上。
kube-reserved-cgroup=/system.slice/kubelet.service #kube组件对应cgroup目录
system-reserved-cgroup=/system.slice #系统组件对应cgroup目录
kube-reserved=cpu=1,memory=2Gi #kube组件资源预留大小
system-reserved=cpu=500m,memory=1Gi #系统组件资源预留大小

cpuset和hugetlb subsystem是默认没有初始化system.slice手动创建

1
mkdir -p /sys/fs/cgroup/cpuset/system.slice/kubelet.service/
1
mkdir -p /sys/fs/cgroup/hugetlb/system.slice/kubelet.service/

配好后重启kubelet

1
systemctl restart kubelet

然后我们在通过kubectl describe node rke-node3查看信息。

kube-reserved=cpu=1,system-reserved=cpu=500m 所以cpu就1.5个了,总共就2个,那么Allocatable就为2000-1500=500m了
kube-reserved=memory=2Gi,system-reserved=memory=1Gi 所以你才为3Gi,8Gi-3GI=5Gi=5242990Ki

上面也论证了kubelet配置资源预留,实际上是kubelet上报资源时,把预留的值减去了,所以scheduler调度时得到的值就是减后的值。

配置eviction
生产环境尽量配置eviction-soft,少用eviction-hard,因为eviction-hard没有缓冲时间,马上去驱逐pod,而eviction-soft可以通过配置eviction-soft-grace-period(达到阀值后等待多久在进行eviction,默认是90s)
eviction-hard(默认就配置了eviction-hard=memory.available=100Mi,所以我们前面没做任何配置Allocatable看见的memory会少100M内存)

1
--enforce-node-allocatable=pods,kube-reserved,system-reserved --kube-reserved-cgroup=/system.slice/kubelet.service --system-reserved-cgroup=/system.slice --kube-reserved=cpu=1,memory=2Gi, --system-reserved=cpu=500m,memory=1Gi, --eviction-hard=memory.available<10%,nodefs.available<10%,imagefs.available<10%

配置了eviction-hard的话,

1
Allocatable=Node_capacity-(kube-reserved+system-reserved+eviction-threshold)
1
--enforce-node-allocatable=pods,kube-reserved,system-reserved --kube-reserved-cgroup=/system.slice/kubelet.service --system-reserved-cgroup=/system.slice --kube-reserved=cpu=1,memory=2Gi, --system-reserved=cpu=500m,memory=1Gi, --eviction-soft=memory.available<10%,nodefs.available<10%,imagefs.available<10% --eviction-soft-grace-period=memory.available=2m,nodefs.available=2m,imagefs.available=2m

配置了eviction-soft的话,

1
Allocatable=Node_capacity-(kube-reserved+system-reserved)

最佳实践
1、生产环境中,建议资源预留+应用资源限制结合使用,因为如果单纯只做资源预留的,没做应用资源限制或配置eviction,如果应用运行了一段时间的pod突然资源使用暴涨,就会触发host oomkill。
2、在kubernetes中资源分为可压缩资源和不可压缩资源 ,如我们常见的cpu是可压缩资源、内存、磁盘资源是不可压缩资源。建议只针对不可压缩资源进行资源预留。
3、建议给系统预留10%的内存,kubernetes组件预留3%~5%的内存,磁盘预留10%。

1
2
3
4
5
6
7
https://www.kubernetes.org.cn/1150.html
http://wsfdl.com/kubernetes/2017/12/18/k8s资源预留.html
https://my.oschina.net/jxcdwangtao/blog/1629059
http://www.sohu.com/a/231155920_268033
https://www.kubernetes.org.cn/4022.html
http://licyhust.com/容器技术/2017/10/24/eviction/