概述
默认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 | --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 |
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 | https://www.kubernetes.org.cn/1150.html |