Descheduler

Descheduler for Kubernetes — README 总结 #

仓库地址: github.com/kubernetes-sigs/descheduler


一、什么是 Descheduler? #

Descheduler 是 Kubernetes 的反调度器,用于解决 kube-scheduler 无法处理的问题:当集群状态随时间变化后,已经运行的 Pod 可能不再处于最优节点上。Descheduler 根据策略找到并驱逐这些 Pod,让它们被重新调度到更合适的节点。

为什么需要 Descheduler? #

场景说明
节点负载不均部分节点过载或空闲
调度条件变化节点的 taint/label 变化,亲和性不再满足
节点故障恢复故障节点的 Pod 迁移到其他节点后造成聚集
新增节点新节点加入集群后需要重新平衡

注意:Descheduler 只负责驱逐 Pod,不负责调度。被驱逐的 Pod 由 kube-scheduler 重新调度。


二、部署方式 #

Descheduler 可以以 Job / CronJob / Deployment 三种方式运行在集群中(kube-system 命名空间,作为 Critical Pod 避免被驱逐):

方式说明
Job执行一次后退出
CronJob定时周期性执行
Deployment常驻运行,支持 HA(Leader Election)

安装方式支持:kubectl apply / Helm Chart(v0.18+)/ Kustomize


三、策略插件(Strategy Plugins) #

Descheduler 采用插件化架构,策略分为两大类:

Deschedule 插件(逐个处理 Pod) #

插件说明
RemovePodsViolatingInterPodAntiAffinity驱逐违反 Pod 间反亲和性的 Pod
RemovePodsViolatingNodeAffinity驱逐违反节点亲和性的 Pod
RemovePodsViolatingNodeTaints驱逐违反节点 Taint 的 Pod
RemovePodsHavingTooManyRestarts驱逐重启次数过多的 Pod
PodLifeTime基于 Pod 年龄/状态/退出码驱逐
RemoveFailedPods驱逐失败的 Pod

Balance 插件(批量处理 Pod 实现均衡) #

插件说明
RemoveDuplicates驱逐同一节点上的重复副本
LowNodeUtilization从过载节点驱逐 Pod,迁移到空闲节点
HighNodeUtilization从空闲节点驱逐 Pod,集中到更少节点(配合节点缩容)
RemovePodsViolatingTopologySpreadConstraint驱逐违反拓扑分散约束的 Pod

四、策略插件详解 #

1. RemoveDuplicates(去重) #

确保同一个节点上不会运行同一 ReplicaSet/StatefulSet/Job 的多个副本。适用于节点故障恢复后 Pod 聚集的场景。

2. LowNodeUtilization(低利用率均衡) #

                    thresholds          targetThresholds
                    ◄─────────►         ◄──────────────►
节点利用率:  [空闲]  [适中]          [过载]
             < 20%    20%-50%         > 50%

空闲节点 ← Pod 从过载节点迁移过来
过载节点 → 驱逐 Pod
  • thresholds:低于此值视为空闲节点(如 CPU < 20%)
  • targetThresholds:高于此值视为过载节点(如 CPU > 50%)
  • 支持 useDeviationThresholds 模式(基于平均值的偏差)

3. HighNodeUtilization(高利用率装箱) #

与 LowNodeUtilization 相反,驱逐空闲节点上的 Pod 使它们集中到更少节点。需配合 MostAllocated 调度策略使用,适用于触发节点缩容。

4. RemovePodsViolatingNodeAffinity #

实现 requiredDuringSchedulingRequiredDuringExecution 语义(kube-scheduler 只保证调度时满足亲和性,不保证运行时持续满足)。

5. RemovePodsViolatingNodeTaints #

当节点的 Taint 变化后,驱逐不再满足容忍条件的 Pod。支持 excludedTaintsincludedTaints 过滤。

6. PodLifeTime(Pod 生命周期) #

支持多种驱逐条件:

  • 年龄驱逐maxPodLifeTimeSeconds 驱逐超过指定时间的 Pod
  • 状态驱逐:基于 Pod Phase、Container State、退出码等条件
  • 条件驱逐:基于 status.conditions 的 type/reason/status

7. RemoveFailedPods #

驱逐处于 Failed 状态的 Pod,可按 reason、exitCodes、ownerKinds 过滤。


五、过滤机制(Filter) #

Descheduler 提供多层过滤来保护不应被驱逐的 Pod:

Pod 保护规则(Pod Protections) #

保护规则默认行为配置方式
系统关键 Pod保护(不驱逐)defaultDisabled: ["SystemCriticalPods"] 可解除
DaemonSet Pod保护defaultDisabled: ["DaemonSetPods"] 可解除
本地存储 Pod保护defaultDisabled: ["PodsWithLocalStorage"] 可解除
失败裸 Pod保护defaultDisabled: ["FailedBarePods"] 可解除
PVC Pod驱逐extraEnabled: ["PodsWithPVC"] 可保护
无 PDB Pod驱逐extraEnabled: ["PodsWithoutPDB"] 可保护
ResourceClaim Pod驱逐extraEnabled: ["PodsWithResourceClaims"] 可保护

其他过滤 #

过滤方式说明
Namespace 过滤namespaces.include / namespaces.exclude
Label 过滤labelSelector
Priority 过滤priorityThreshold.name / priorityThreshold.value(默认 system-cluster-critical)
NodeFit 过滤nodeFit: true 驱逐前检查 Pod 是否能调度到其他节点
MinReplicasminReplicas 当 ReplicaSet 副本数低于阈值时不驱逐
MinPodAgeminPodAge 不驱逐创建时间在此阈值内的 Pod

六、全局配置 #

参数说明默认值
nodeSelector限定处理的节点范围nil(全部)
maxNoOfPodsToEvictPerNode每个节点最多驱逐数nil(无限制)
maxNoOfPodsToEvictPerNamespace每个命名空间最多驱逐数nil(无限制)
maxNoOfPodsToEvictTotal每次调度周期总驱逐上限nil(无限制)
gracePeriodSeconds驱逐宽限期(秒)nil

七、驱逐决策机制 #

Descheduler 驱逐 Pod 时的优先级:
    ├─ 按 Priority 排序:低优先级先驱逐
    ├─ 同优先级下:BestEffort → Burstable → Guaranteed
    └─ 遵守 PDB(PodDisruptionBudget)

不会被驱逐的 Pod:
    ├─ system-cluster-critical / system-node-critical(除非显式配置)
    ├─ 裸 Pod(无 OwnerRef,除非 evictFailedBarePods: true)
    ├─ DaemonSet Pod(除非 evictDaemonSetPods: true)
    ├─ 本地存储 Pod(除非 evictLocalStoragePods: true)
    └─ DeletionTimestamp 非 nil 的 Pod

八、高可用(HA) #

以 Deployment 方式部署时,可通过 --leader-elect 开启 Leader Election,多副本部署但只有一个实例活跃。


九、Metrics #

指标类型说明
pods_evicted_totalCounter驱逐的 Pod 总数
loop_duration_secondsHistogram一次完整调度周期耗时
strategy_duration_secondsHistogram每个策略执行耗时

默认通过 https://localhost:10258/metrics 暴露。


十、版本兼容性 #

Descheduler支持的 Kubernetes 版本
v0.36v1.36
v0.35v1.35
v0.34v1.34
v0.33v1.33
v0.32v1.32
v0.31v1.31
v0.30v1.30
v0.29v1.29
v0.28v1.28
v0.27v1.27
v0.26v1.26
v0.25v1.25
v0.24v1.24
v0.23v1.23
v0.22v1.22
v0.21v1.21
v0.20v1.20
v0.19v1.19
v0.18v1.18

每个 Descheduler 版本经过其对应的最近 3 个 K8s minor 版本测试。

Reference #