节点资源不足,kubelet回收资源分成几步

425 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

kubelet 管理资源不足的节点

kubelet是 kubernetes 中重要的组件,关于节点控制,主要用于:

  • apiserver注册节点
  • 监控apiserver中已经调度的 pod,通知CRI在调度新 Pod 后重启容器
  • 监控正在运行的容器状态并报告给apiserver
  • 执行liveness探针并在健康检查失败后重新启动容器
  • 运行由kubelet管理的静态 pod
  • 收集节点资源使用量

当节点资源资源耗尽时,kubelet驱逐节点的能力。当磁盘、RAM、CPU 等计算资源不足时,kubelet可以极大维护节点的稳定性。

kubelet 确定资源使用量

kubelet可以从节点上驱逐工作负载,以释放资源,但kubelet如何知道节点资源不足的?

其实kubelet是通过eviction singal(驱逐信号)和eviction threshold(驱逐阈值)确定何时回收资源。

  • 驱逐信号是系统资源(如内存)的当前容量
  • 驱逐阈值是kubelet维护的资源最小值

换言之,每个驱逐信号都与某个驱逐阈值相关。

该驱逐阈值会告诉kubelet何时开始回收资源。

目前,kubelet支持以下驱逐信号

  • memory.available:内存状态信号。内存的默认驱逐阈值为 100Mi。也就是说当内存小于 100Mi 时,kubelet就会驱逐 pod
  • nodefs.available:文件系统信号。默认情况下,如果小于10%,就开始回收节点资源
  • nodefs.inodesFree:描述 nodefs 索引节点内存状态的信号。默认情况下,如果小于5%,会驱逐 pod
  • imagefs.available-imagefs:镜像存储信号。如果小于15%,会驱逐工作负载
  • image.inodesFree:索引 imagefs 节点内存的状态,没有默认驱逐阈值。

memory.available 的值来自 cgroupfs,而不是像 free -m 这样的工具。 这很重要,因为 free -m 在容器中不起作用

kubelet启动时会执行这些默认值,可以在启动时自定义驱逐阈值。

目前,kubernetes 支持硬驱逐和软驱逐。

如果达到硬驱逐,kubelet就会立即开始回收资源,没有任何延迟。软驱逐会在宽限期前,不会驱逐 pod。

可以使用eviction-soft驱逐条件和eviction-soft-grace-period组合使用。例如,kubelet --eviction-soft memory.available<1.5Gi -- eviction-soft-grace-period memory.available=1m30s来指定内存小于 1.5Gi 开始驱逐 pod,在驱逐 pod 之前有 1m30s 宽限期。

还有eviction-max-pod-grace-period在满足软驱逐条件而终止 Pod 时使用的最大允许宽限期(以秒为单位)。

硬驱逐没有宽限期,当到达硬驱逐条件时,kubelet会立即杀死 pod,而不会正常终止以回收紧缺的资源。

可以通过eviction-hard参数设置硬驱逐条件。例如kubelet --eviction-hard memory.available<100Mi表示节点内存小于 100Mi 会立即回收资源。

kubelet 如何回收资源

kubelet在驱逐用户 pod 之前会尝试先回收节点资源,例如未使用的容器镜像或已经停止运行的 pod。

如果节点有imagefsnodefs文件系统,kubelet会通过不同的方式回收资源。

  • 如果nodefs达到阈值,kubelet垃圾回收死亡的 pod 和容器
  • 如果imagefs达到阈值,kubelet会删除未使用的镜像

如果没有使用imagefskubelet首先会删除所有终止运行的 pod 和容器,然后删除未使用的镜像。

如果回收完节点资源没有解决掉问题,还是处于资源匮乏的阶段,kubelet会开始驱逐用户 pod。kubelet会根据 pod 的 Qos 类、pod 的优先级等回收 pod。

Qos 类

  • Guaranteed pod:所有容器的 cpu 和 memory 的资源限制(limit)和请求(request)相等的 pod
  • Burstable pod:其中一个或多个容器设置资源限制和请求的 pod
  • Best Effort pod:未设置资源请求和限制的 pod

通常,kubelet按如下顺序排列和驱逐 pod

  • pod 是否超过资源请求。
  • pod 优先级。检查 pod 的priority,尝试先驱逐优先级较低的 pod
  • pod 相对于请求的资源使用情况。

根据这些规则,kubelet按以下顺序驱逐 pod

  • 首先驱逐的是资源使用超过请求的BestEffortBurstable的 pod。这些 pod 会根据优先级和资源使用级别排序。
  • 资源使用少于请求的GuaranteedBurstable pod。

最小驱逐回收

如果kubelet回收资源量很少,可能会导致kubelet反复到达配置的驱逐条件并触发多次驱逐。为避免这种情况,可以使用--eviction-minimum-reclaim参数或配置文件为每个资源设置最小回收资源。

例如,设置最小回收量:

可以通过kubelet启动参数设置

--eviction-hard=memory.available<1Gi,nodefs.available<2Gi,imagefs.available<200Gi
--eviction-minimum-reclaim=memory.available=0Mi,nodefs.available=1Gi,imagefs.available=2Gi

可通过配置文件设置

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
evictionHard:
  memory.available: "1Gi"
  nodefs.available: "2Gi"
  imagefs.available: "200Gi"
evictionMinimumReclaim:
  memory.available: "0Mi"
  nodefs.available: "1Gi"
  imagefs.available: "2Gi"

在这个例子中,如果nodefs.available满足驱逐条件,kubelet会开始回收资源,直到满足 2Gi,然后继续回收至少 1Gi。这样就可以避免频繁回收。

资源不足可能还会遇到另一个问题,节点状态震荡。

kubelet收到驱逐信号时,例如,memory.available到达驱逐阈值时,kubelet会将MemoryPressure节点状态分配给节点,这个状态与污点Taint关联,可防止调度新的 pod。如果使用较长的宽限期的软驱逐,节点状态会在truefalse之间震荡,这可能会导致错误的驱逐决策。

为避免这种情况,可以使用eviction-pressure-transition-period标志,控制kubelet将节点状态转换之前必须等待的时间,默认为5m

小结

本文讨论了一些有用的 kubernetes 管理实践,允许管理员设置自定义驱逐阈值和驱逐宽限期,能决定哪些条件对节点稳定性有影响。