Linux Descheduler 的 Pod 驱逐策略与低利用率节点优化

5次阅读

descheduler 默认策略不驱逐低利用率节点上的 pod,因其不感知实时资源使用率,且lownodeutilization默认禁用、依赖metrics server采样、基于requests而非usage判断。

Linux Descheduler 的 Pod 驱逐策略与低利用率节点优化

Descheduler 默认策略为什么不会驱逐低利用率节点上的 Pod

Descheduler 不是资源调度器,它只做“重新平衡”或“清理”,不感知节点 CPU/MEM 实时使用率。默认策略如 RemoveDuplicatesLowNodeUtilization 中的 LowNodeUtilization 确实面向低利用率场景,但它依赖的是 Descheduler 自己采样的指标(通过 Metrics Server),且必须显式启用——它不会自动开火。

  • LowNodeUtilization 默认是禁用的,配置里不写就等于没开
  • 它不读取 topnode_exporter 数据,只认 Metrics Server 的 /apis/metrics.k8s.io/v1beta1/nodes 返回值
  • 采样有延迟(默认 60s 间隔),若节点刚变空闲,Descheduler 可能还没拿到新数据
  • 阈值判断基于“请求量(requests)占比”,不是实际用量(usage);哪怕 Pod 只用了 5% CPU,只要它 request 了 4 核,该节点就算“高负载”

如何正确配置 LowNodeUtilization 触发驱逐

关键在三处:启用策略、配准阈值、确保 Metrics Server 可达。缺一不可。

  • 在 Descheduler 配置中显式声明 strategies,不能只靠注释或默认值
  • thresholds 必须同时设 cpumemory,即使只关心 CPU;未设置的资源会被跳过判断
  • targetThresholds 要比 thresholds 更宽松(例如 thresholds 是 20%,targetThresholds 至少设 40%),否则找不到“可迁入”的目标节点,驱逐会失败
  • 确认 Metrics Server 正常运行:kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" | jq '.items[].usage'
strategies:   "LowNodeUtilization":     enabled: true     params:       thresholds:         cpu: 20         memory: 20       targetThresholds:         cpu: 50         memory: 50       evictableNamespaces:         exclude:         - kube-system         - descheduler

驱逐后 Pod 为什么卡在 Pending 状态

这不是 Descheduler 的问题,而是调度器找不到合适节点——常见于资源 request/limit 设得过高,或节点 taint 未兼容。

  • 被驱逐的 Pod 带着原 resources.requests 重新进调度队列,若集群没有单节点能容纳这个 request,就会 Pending
  • 检查是否误加了 nodeSelectoraffinity,导致只剩 1–2 个节点可选
  • 确认目标节点没有 NoSchedule taint,或 Pod 没带对应 tolerations
  • Descheduler 不修改 Pod,也不触发 Horizontal Pod Autoscaler(HPA);如果想缩容,得另配 HPA 或手动调低 replicas

和 Cluster Autoscaler 配合时要注意什么

Descheduler 和 Cluster Autoscaler 是上下游关系,但节奏不同步容易引发“驱逐-扩容-再驱逐”循环

  • Descheduler 默认每 5 分钟跑一次,Cluster Autoscaler 扩容通常需 1–3 分钟;若 Descheduler 在 CA 扩容完成前反复驱逐,可能把 Pod 全赶到新节点上,又立刻因低利用率再驱离
  • 建议给 CA 设置 --scale-down-delay-after-add=10m,让新节点有足够时间“接活”
  • Descheduler 的 PodLifeTime 策略可配合使用:避免刚调度上去的 Pod 立刻被踢,加个 maxPodLifeTimeSeconds: 300
  • 不要在同一个命名空间里混用 LowNodeUtilizationRemovePodsViolatingInterPodAntiAffinity 等激进策略,容易叠加放大震荡

低利用率判断本身依赖采样精度和阈值粒度,而真实业务负载常有脉冲特征。哪怕配置全对,也可能出现“刚驱完,监控曲线就跳起来”的情况——这时候与其调低阈值,不如先看 Pod request 是否合理。

text=ZqhQzanResources