携手创作,共同成长!这是我参与「掘金日新计划 · 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就会驱逐 podnodefs.available:文件系统信号。默认情况下,如果小于10%,就开始回收节点资源nodefs.inodesFree:描述 nodefs 索引节点内存状态的信号。默认情况下,如果小于5%,会驱逐 podimagefs.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。
如果节点有imagefs和nodefs文件系统,kubelet会通过不同的方式回收资源。
- 如果
nodefs达到阈值,kubelet垃圾回收死亡的 pod 和容器 - 如果
imagefs达到阈值,kubelet会删除未使用的镜像
如果没有使用imagefs,kubelet首先会删除所有终止运行的 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
- 首先驱逐的是资源使用超过请求的
BestEffort或Burstable的 pod。这些 pod 会根据优先级和资源使用级别排序。 - 资源使用少于请求的
Guaranteed和Burstablepod。
最小驱逐回收
如果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。如果使用较长的宽限期的软驱逐,节点状态会在true和false之间震荡,这可能会导致错误的驱逐决策。
为避免这种情况,可以使用eviction-pressure-transition-period标志,控制kubelet将节点状态转换之前必须等待的时间,默认为5m。
小结
本文讨论了一些有用的 kubernetes 管理实践,允许管理员设置自定义驱逐阈值和驱逐宽限期,能决定哪些条件对节点稳定性有影响。