介绍

从发起模块的角度,pod eviction 可以分为两类:

  • Kube-controller-manager: 周期性检查所有节点状态,当节点处于 NotReady 状态超过一段时间后,驱逐该节点上所有 pod。
  • Kubelet: 周期性检查本节点资源,当资源不足时,按照优先级驱逐部分 pod。

    Kube-controller-manger 发起的驱逐

    Kube-controller-manager 周期性检查节点状态,每当节点状态为 NotReady,并且超出 podEvictionTimeout 时间后,就把该节点上的 pod 全部驱逐到其它节点,其中具体驱逐速度还受驱逐速度参数,集群大小等的影响。最常用的 2 个参数如下:

  • –pod-eviction-timeout:NotReady 状态节点超过该时间后,执行驱逐,默认 5 min。

  • –node-eviction-rate:驱逐速度,默认为 0.1 pod/秒

当某个 zone 故障节点的数目超过一定阈值时,采用二级驱逐速度进行驱逐。

  • –large-cluster-size-threshold:判断集群是否为大集群,默认为 50,即 50 个节点以上的集群为大集群。
  • –unhealthy-zone-threshold:故障节点数比例,默认为 55%
  • –secondary-node-eviction-rate:当大集群的故障节点超过 55% 时,采用二级驱逐速率,默认为 0.01 pod/秒。当小集群故障节点超过 55% 时,驱逐速率为 0 pod/秒。

在目前的版本(v1.16)中,默认开启了TaintBasedEvictions, TaintNodesByCondition这两个feature gate,则所有node生命周期管理都是通过condition + taint的方式进行管理。其主要逻辑由三部分组成:

  1. 不断地检查所有node状态,设置对应的condition
  2. 不断地根据node condition 设置对应的taint
  3. 不断地根据taint驱逐node上面的pod

查看代码发现--pod-eviction-timeout并未起作用,原来在v1.13版本之前TaintBasedEvictions功能还未开启,此时node not-ready之后,controller直接判断not-ready时间是否超过了—pod-eviction-timeout,超过就进行删除。而v1.13,TaintBasedEvictions功能开启之后就不会使用了该参数,转而使用了上面描述的condition+taint方案。也就是说node NotReady之后,pod的驱逐时间完全由每个pod toleration中 tolerationSecond决定,而不是由controller-manager的参数—pod-eviction-timeout统一决定。这样想想也合情合理,每个pod对于故障的容忍时间不同,tolerationSecond可以更加灵活地为每个pod指定不同的驱逐时间。

Kubelet 发起的驱逐

Kubelet 周期性检查本节点的内存和磁盘资源,当可用资源低于阈值时,则按照优先级驱逐 pod,具体检查的资源如下:

  • memory.available
  • nodefs.available
  • nodefs.inodesFree
  • imagefs.available
  • imagefs.inodesFree

以内存资源为例,当内存资源低于阈值时,驱逐的优先级大体为 BestEffort > Burstable > Guaranteed,具体的顺序可能因实际使用量有所调整。当发生驱逐时,kubelet 支持 soft 和 hard 两种模式,soft 模式表示缓期一段时间后驱逐,hard 模式表示立刻驱逐。

MemoryPressure、DiskPressure的存储空间(EphemeralStorage)

kubelet 按以下顺序排列和驱逐 Pod:

  1. 首先考虑资源使用量超过其请求的 BestEffort 或 Burstable Pod。 这些 Pod 会根据它们的优先级以及它们的资源使用级别超过其请求的程度被逐出。
  2. 资源使用量少于请求量的 Guaranteed Pod 和 Burstable Pod 根据其优先级被最后驱逐。

DiskPressure下的inode、PIDPressure

当 kubelet 因 inode 或 PID 不足而驱逐 pod 时, 它使用优先级来确定驱逐顺序,因为 inode 和 PID 没有请求。