引发Pod驱逐的原因

语言: CN / TW / HK

最近在处理一个项目的k8s集群时,频繁遇到pod在不同节点驱逐的现象。

如此频繁的驱逐引发了"节点状态振荡",是某node节点或多个Node节点出发了"驱逐信号"造成的。

集群由1个master和4台node组成,经仔细检查发现存在如下问题:

  1. 其中master-node节点和另外3台node节点内核为3.10版本,只有一台node节点为5.4的新版内核
  2. 其中一台node节点文件句柄数没有修改为,1024
  3. 五台的磁盘空间均比较小,但是经查有3台可以通过逻辑卷扩容
  4. 磁盘占用率,已经发现有2台出现磁盘占用率超过80%的现象
    kubelet 有如下所示的默认硬驱逐阈值:
    memory.available<100Mi
    nodefs.available<10%
    nodefs.inodesFree<5%
    imagefs.available<15%

    由上可见,文件句柄数过小和磁盘空间使用过高都会触发阈值,内核版本过低可能造成资源分配不平衡及内存占用高(内存泄漏风险)也会引发驱逐。

    如上逐一解决后,观察一周时间,至今还没有发生驱逐现象

    总结:在集群规模较小的情况下,要充分保障各资源情况,否则发生驱逐后到其它节点仍然无法满足资源需求,会引起节点震荡。集群机器数量较多,被驱逐到其它节点上的pod,在多台机器上资源不满足的概率较小。

    以下是一些相关说明:

    驱逐信号

    什么是驱逐信号呢?简单理解就是,kubelet什么时候什么场景下开始驱逐pod呢?总的有几个参考值吧,这就是驱逐信号,k8s提供了以下几种驱逐信号

驱逐信号 描述

memory.available    node.status.capacity[memory] - node.stats.memory.workingSet
nodefs.available    node.stats.fs.available
nodefs.inodesFree   node.stats.fs.inodesFree
imagefs.available   node.stats.runtime.imagefs.available
imagefs.inodesFree  node.stats.runtime.imagefs.inodesFree
memory.available是针对内存资源,其余4个驱逐信号都是针对磁盘空间的。

上面的每个信号都支持字面值或百分比的值。基于百分比的值的计算与每个信号对应的总容量相关。

memory.available 的值从 cgroupfs 获取,而不是通过类似 free -m 的工具。 这很重要,因为 free -m 不能在容器中工作

kubelet 只支持两种文件系统分区。

nodefs 文件系统,kubelet 将其用于卷和守护程序日志等。

imagefs 文件系统,容器运行时用于保存镜像和容器可写层。

imagefs 可选。kubelet 使用 cAdvisor 自动发现这些文件系统。 kubelet 不关心其它文件系统。当前不支持配置任何其它类型。 例如,在专用 filesytem 中存储卷和日志是 不可以 的。

我们可以想想worker节点中什么最耗磁盘空间,无非也就下面几项

镜像文件:有的很大,几百M。每次更新deployment,都会拉取新的镜像,长此以往,不通版本的镜像肯定要消耗很大磁盘空间的。imagefs文件系统正是管理这些镜像的,如果我们配置的驱逐信号中有imagefs.available或者imagefs.inodesFree,且触发驱逐阀值后,k8s将会主动清理一些没有使用的版本镜像,以此来释放更多的磁盘空间。
日志:随着应用的长时间运行,日志会越来越庞大,volume不管你使用的是emptyDir,hostPath,还是nfs,clustersfs,都会将日志存储在节点上的,占用worker节点的磁盘空间也将会越来越大。docker中的日志分为俩种,docker主进程的标准输出日志和项目中用户产生的文件日志,正好对应nodefs文件系统中的卷和守护程序日志。如果我们配置的驱逐信号中有nodefs.available或者nodefs.inodesFree且触发驱逐阀值后,k8s将会清理这些日志,清理这些的日志的方式只能是驱逐pod了。

软驱逐阈值

使用一对由驱逐阈值和宽限期组成的配置对。在宽限期内持续超过阀值则进行驱逐。比如下面这俩行配置,表示的意义是当节点的memory.available小于500Mi,且在1分30内持续小于500Mi时,开启触发驱逐。下面这俩行是成对出现的。

软驱逐阈值使用关键字eviction-soft

--eviction-soft=memory.available<500Mi
--eviction-soft-grace-period=memory.available=1m30s

硬驱逐阈值

相对于软驱逐阈值,区别就是没有缓冲时间,只要触发驱逐信号,就立即开始驱逐而不是优雅的终止。

硬驱逐阈值使用关键字eviction-hard。比如下面例子

--eviction-hard=memory.available<500Mi,nodefs.available<20%