最近发现测试环境的k8s集群,总有node利用不上,pod漂移过去之后,启动不了,故仔细排查了一下缘由!
问题现象
1 | [root@master35 scripts]# ./list_pod.sh | grep imis |
原因分析
1 | [root@node149 ~]# df -h |
1 | 由于这是测试环境,所以docker的目录,默认在/var/lib/docker,没有单独挂载别的目录,这样的话,也没加定时任务清理磁盘,/ 磁盘就会越来越满,现在看是用了86% |
由于某些原因,我们的那个portal pod必须运行于该node上(通过nodeSelector选定node的方式)。在无法扩充根分区size的情况下,为了临时恢复pod运行,我们只能进一步“压榨”node了。于是我们的思路是:通过调整node的eviction threshold值来让node恢复healthy。
解决方案
每个node上的kubelet都负责定期采集资源占用数据,并与预设的 threshold值进行比对,如果超过 threshold值,kubelet就会尝试杀掉一些Pod以回收相关资源,对Node进行保护。kubelet关注的资源指标threshold大约有如下几种:
1 | - memory.available |
每种threshold又分为eviction-soft和eviction-hard两组值。soft和hard的区别在于前者在到达threshold值时会给pod一段时间优雅退出,而后者则崇尚“暴力”,直接杀掉pod,没有任何优雅退出的机会。这里还要提一下nodefs和imagefs的区别:
1 | nodefs: 指node自身的存储,存储daemon的运行日志等,一般指root分区/; |
解决步骤
我们需要为kubelet重新设定nodefs.available的threshold值。怎么做呢?
kubelet是运行于每个kubernetes node上的daemon,它在system boot时由systemd拉起:
1 | root@master35 ~# ps -ef|grep kubelet |
查看一下kubelet service的状态:
1 | [root@master35 scripts]# systemctl status kubelet |
我们定义一个新的Environment var,比如就叫:KUBELET_EVICTION_POLICY_ARGS 在/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
1 | Environment="KUBELET_EVICTION_POLICY_ARGS=--eviction-hard=nodefs.available<5%" |
这样控制,node的磁盘策略为<5%的硬盘就可以用,不像之前默认的15%就用不了了!