k8s 驱逐机制

通过 kubelet 实现 Pod 的驱逐过程,它有自己的 一套驱逐机制,每个节点上的 kubelet 都会通过 cAdvisor 提供的资源使用指标来监控自身 节点的资源使用量,并根据这些指标的变化做出相应的驱逐决定和操作 。 kubelet 待续监控 主机的资源使用情况,尽噩防止计算资源被耗尽,一旦出现资源紧缺的迹象,就会主动终 止 一 个或多个 Pod 的运行,以回收紧缺的资源 。 当一个 Pod 被终止时,其中的容器会被全 部停止, Pod 的状态会被设置为 Failed。

驱逐时机

磁盘不足

磁盘资源不足时会触发 Pod 的驱逐行为

Kubernetes包括两种 文件系统: nodefs 和 imagefs。

  • nodefs 是 kubelet 用于存储卷系统、服务程序日志等的文件系统
  • imagefs 是容 器运行时使用的可选文件系统,用千存储容器镜像和容器可写层数据 。

cAdvisor 提供了这 两种文件系统的相关统计指标,分别如下:

  • available: 表示该文件系统中可用的磁盘空间 。
  • inodesFree: 表示该文件系统中可用的 inode 数量(索引节点数量) 。

默认情况下, kubelet检测到下面的任意条件满足时,就会触发 Pod 的驱逐行为 。

  • nodefs.available<l0%
  • nodefs.inodesFree<5% 。
  • imagefs.available<l5% 。
  • irnagefs.available<l5% 。

如果 nodefs 达到驱逐阅值, kubelet 就会删除所有已失效的 Pod 及其容器实例对应的 磁盘文件。相应地 , 如果 imagefs 达到驱逐阔值,则 kubelet 会删除所有未使用的容器镜像。 kubelet 不关注其他文件系统,不支待所有其他类型的配置,例如保存在独立文件系统中的 卷和日志。

内存不足

memory.available 代表当前节 点的可用内存

默认情况下 , memory.available<100Mi 时会触发 Pod 的驱逐行为 。

驱逐 Pod 的过程:

  • kubelet 从 cAdvisor 中定期获取相关的资源使用拯指标数据 , 通过配置的阅值 筛选出满足驱逐条件的 Pod
  • kubelet 对这些 Pod 进行排序,每次都选择 一 个 Pod 进行驱 逐。

设置阈值

软阈值

驱逐软阙值由一个驱逐阔值和一个管理员设定的宽限期共同定义 。 当系统资源消耗达 到软阔值时,在这一状况的持续时间达到宽限期之前, kubelet 不会触发驱逐动作 。 如果没 有定义宽限期,则 kubelet会拒绝启动。

另外,可以定义终止 Pod 的宽限期。如果定义了这一宽限期,那么 kubelet 会使用pod.Spec.TerminationGracePeriodSeconds 和最大宽限期这两个值之间较小的数值进行宽限,如果没有指定,则 kubelet 会立即“杀掉 “Pod。

  • –eviction-soft: 描述驱逐阙值(例如 memory.available<l.5GiB ),如果满足这一条 件的持续时间超过宽限期,就会触发对 Pod 的驱逐动作 。
  • –eviction-soft-grace-period: 驱逐宽限期(例如 memory.available=]m30s),用于定 义达到软阅值之后持续时间超过多久才进行驱逐。
  • –eviction-max-pod-grace-period: 在达到软阔值后,终止 Pod 的最大 宽限时间(单 位为 s)。

硬阈值

硬阙值没有宽限期,如果达到了硬阅值,则 kubelet 会立即“杀掉 “Pod 并进行资源回收 。

硬阔值的定义包括参数 –eviction-bard: 驱逐硬阔值,一旦达到闽值,就会触发对 Pod 的驱逐操作。

kubelet 的默认硬阔值定义如下:

--eviction-hard=memory.available<l00Mi

kubelet 的–housekeeping-interval 参数用于定义了一个时间间隔, kubelet 每隔一 个这 样的时间间隔就会对驱逐阅值进行评估 。

节点状态

节点状态与驱逐信号 的对应关系

image-20221006173317947

如果一个节点状态在软闽值的上下振荡,但没有超过宽限期,则会导致该节点的相应

状态在 True 和 False 之间 不断变换 ,可能对调度的决策过程产生负面影响 。

要防止这种状态出现,可以使用参数--eviction-pressure-transition-period (在脱离压力 状态前 需要等待 的时间,默认值为 5m0s) 为 kubelet 设置脱离压力状态之前需要等待的时 间。

这样一来, kubelet在把压力状态设萱为 False之前, 会确认在检利周期之内该节点没 有达到驱逐闹值 。

回收 Node 级别的资源

kubelet 在驱逐用户 Pod 之前,会尝试回收 Node 级别的资源 。在观测到磁盘压力时 ,基千服务器是否为容器运行时定义了独立的 imagefs, 会有不同的资源回收过程 。

有imagefs

  • 如果 nodefs 文件系统达到了驱逐阙值, 则 kubelet会删掉已停掉的 Pod 和容器来 清理空间 。
  • 如果 imagefs 文件系统达到了驱逐阙值,则 kubelet会删掉所有无用的镜像来清理 空间。

无imagefs

如果 nodefs 文件系统达到了驱逐闹值,则 kubelet 会这样清理空间:

  • 首先删除已停掉的 Pod、 容器;
  • 然后删除所有无用的镜像 。

驱逐用户的Pod

kubelet如果无法在节点上回收足够的资源,就会开始驱逐用户的 Pod。

kubelet 会按照下面的标准对 Pod 的驱逐行为进行判断 。

  • Pod 要求 的服务质量Qos。
  • Pod 对紧缺 资源的消耗址(相对千资源诮求 Request )。

kubelet 会按照下面的顺序驱逐 Pod。

  • BestEffort: 紧缺资源消耗最多的 Pod 最先被驱逐。

  • Burstable: 根据相对请求来判断,紧缺资源消耗最多的 Pod 最先被驱逐,如果没 有 Pod 超出它们的请求,则策略会瞄准紧缺资源消耗址最大的 Pod。

  • Guaranteed: 根据相对请求来判断,紧缺资源消耗最多的 Pod 最先被驱逐,如果 没有 Pod 超出它们的请求,则策略会瞄准紧缺资源消耗盘最大的 Pod。

有lmagefs的情况

  • 如果 nodefs触发了驱逐,则 kubelet会根据 nodefs 的使用情况(以 Pod 中所有容器的本地卷和日志所占的空间进 行 计算)对 Pod 进行排序 。
  • 如果 imagefs触发了驱逐,则 kubelet会根据 Pod中所有容器消耗的可写入层的使用空间进 行 排序 。

没有lmagefs的情况

  • nodefs 触发了驱逐 , 则 kubelet 会对各个 Pod 中所有容器的总体磁盘消耗(以本 地卷+日志+所有容器的写入层 所 占的空间进行计算)进行排序 。

资源最少回收量

在某些场景下,驱逐 Pod 可能只回收了很少的资源 , 这就导致了 kubelet 反复触发驱逐阔值 。 另外 , 回 收 磁盘这样的资源是需要消耗时间 的 。

要缓和这种状况 , kubelet可以对每种资源都定义 minimum-reclaim。 kubelet一旦监测 到了资源压力 , 就会试着回收不少于 minimum-reclaim 的资源数黛 , 使得资源消耗益回到 期望的范围 。这样配置的效果如下 。

  • 当 memory.available 超过阔值并触发了驱逐操作时, kubelet 会启动资源回收,并 保证 memory.available至少有 500MiB。

  • 当 nodefs.available超过阙值并触发了驱逐操作时, kubelet会恢复 nodefs.available 到至少 l.5GiB。

  • 当 imagefs.available 超过阔 值 并触发了驱逐操作时, kubelet 会保证 imagefs. available恢复到至少 102GiB。

在默认情况下 ,所 有资源的 eviction-minimum-reclaim 都为 0。

节点资源紧缺情况下的系统行为

调度器

在节点资源紧缺的情况下,节点会向 Master 报告这一状况。在 Master 上运行的调度 器 (Scheduler) 以此为信号,不再继续向该节点调度新的 Pod。如表 10.7 所示为节点状况 与调度行为的对应关系。

image-20221006180912302

Node 的 OOM 行为

如果节点在 kubelet 能够回收内存之前遭遇了系统的 OOM (内存不足),节点则依赖oom_k让!er 的设置进行响应

kubelet 根据 Pod 的 QoS 为每个容器都设置了一个 oom_score_adj 值

image-20221006181053300

如果 kubelet 无法在系统 OOM 之前回收足够的内存,则 oom_伈lier 会根据内存使用比 率来计算 oom_score, 将得出的结果和 oom_score_adj 相加,得分最高的 Pod 首先被驱逐 。

这个策略的思路是, QoS 最低且相对于调度的 Request 来说消耗最多内存的 Pod 会首 先被驱逐,来保障内存的回收。

与 Pod 驱逐不同,如果一个 Pod 的容器被 OOM“ 杀掉”,则可能被 kubelet 根据 RestartPolicy 重启 。

可调度的资源和驱逐策略实践

一个集群的资源管理需求

  • 节点内存容量: 10GiB
  • 保留 10%的内存给系统守护进程(操作系统、 kubelet 等)
  • 在内存使用率达到 95%时驱逐 Pod, 以此降低系统压力并防止系统 OOM