K8s 自定义调度器导致 Pod 调度失效排查
2026-08-11 00:53:03
# Kubernetes
业务 Pod 指定了自研调度器后,在高峰期扩容时必现 Pending,提示资源不足,但监控显示资源充裕;一旦切回默认调度器立刻恢复正常。这种”只有特定 Pod 出问题、且换调度器就好”的现象,指向自定义调度器自身的逻辑缺陷。
问题现象与背景原因
典型现象:指定了自定义调度器的业务 Pod 卡在 Pending。
1 | kubectl get pod biz-app |
核心原因:自定义调度器存在缓存与 etcd 数据不一致的 BUG。
- 业务 Pod 通过
spec.schedulerName指定了自研调度器。 - 自研调度器的评分插件(如
NodeAffinityPriority)读取了过期缓存,认为节点不满足亲和性,直接打 0 分,于是所有节点”都不合格” → Pending。 - 因为事件去重机制,这种”打分逻辑错误”不会在 Events 里留下明显异常日志,只表现为 Pending,极难发现。
提示:只有”指定了自定义调度器”的 Pod 出问题、且切换回默认调度器立刻正常——这是自定义调度器故障的强特征。
排查过程(思路与定位方法)
第一步:确认 Pod 用的是哪个调度器。
1 | kubectl get pod biz-app -o jsonpath='{.spec.schedulerName}' |
第二步:启用调度器详细追踪,看它到底怎么给节点打分。
1 | # 修改自定义调度器部署,提高日志级别 |
关注日志里对每个节点的 score、feasible 判断,看是否出现”本应合格却被打 0 分”。
第三步:对比 etcd 真实状态与调度器缓存。
1 | # 看节点真实标签 / 资源 |
第四步:验证”切换回默认调度器能否立刻调度”。(运行中 Pod 的 schedulerName 不可变,需用新 Pod 或改模板后重建来验证。)
最终的解决方法
- 修复逻辑漏洞:检查评分插件读取缓存的刷新机制,确保节点状态变更(标签 / 污点 / 资源)及时失效缓存。
- 增加兜底策略:当自定义调度器打分全为 0 时,fallback 到默认调度逻辑,避免整批 Pending。
- 开启调度失败可观测性:关闭事件去重或单独打点,让”所有节点 0 分”这种异常能被告警捕获。
- 关键教训:性能优化(用缓存提速)不能牺牲逻辑严谨性;缓存一致性必须兜底。
长期:为自定义调度器补单元测试 + 集成测试,覆盖”节点状态变更后缓存刷新”场景;并为调度失败配置监控(如 Pending 队列长度、调度时延)。
操作命令(可直接复制执行)
1 | # 1. 看 Pod 用的调度器 |