Kubernetes 调度器(kube-scheduler)是控制面中负责把未调度的 Pod 放到合适节点上的核心组件。集群规模一大,调度器的压力就会明显体现出来:批量提交几百上千个 Pod 时,调度延迟从毫秒级飙升到几十秒,甚至出现 Pod 一直处于 Pending 状态的情况。要解决这类问题,不能只靠加资源,需要先弄清楚调度器的内部工作流程,找到真正的瓶颈点,再针对性地优化。

一、调度器的工作流程与性能开销在哪里
kube-scheduler 的工作是一个不断循环的过程:从调度队列中取出一个 Pod,通过预选(Filter)阶段筛掉不满足条件的节点,再通过优选(Score)阶段给剩余节点打分,最后选出分数最高的节点执行绑定。整个过程的耗时可以简单拆解为:队列等待时间 + 预选耗时 + 优选耗时 + 绑定耗时。
队列等待时间经常被忽视。调度器内部维护了三个队列:activeQueue、unschedulableQueue 和 backoffQueue。当一个 Pod 调度失败后被放入 unschedulableQueue,只有集群状态发生变化(比如有节点新增、Pod 被删除)时才会被重新激活。如果集群事件频繁但 Pod 本身依赖的资源一直没出现,就会出现反复入队、反复失败的情况,白白消耗调度周期。
预选和优选的耗时与节点数量直接相关。假设集群有 5000 个节点,每调度一个 Pod 都要对全部节点跑一遍过滤和打分插件,哪怕单节点只花几十微秒,累计起来也是非常可观的计算量。更糟糕的是,某些插件在失败时没有快速短路,导致已经明显不匹配的节点仍然被完整评估。
二、如何定位调度器的性能瓶颈
定位瓶颈的第一步是看指标。kube-scheduler 默认暴露了 Prometheus 指标,其中几个关键指标需要重点关注:scheduler_schedule_attempts_total记录调度尝试次数和结果分布,scheduler_framework_extension_point_duration_seconds按插件统计各扩展点的耗时,scheduler_e2e_scheduling_duration_seconds反映端到端调度延迟。
# 查看调度延迟分布(直方图) kubectl get --raw /metrics | grep e2e_scheduling_duration_seconds # 观察各插件的耗时排名 kubectl get --raw /metrics | grep framework_extension_point_duration_seconds
如果发现 scheduler_schedule_attempts_total 中 failure 占比很高,说明大量时间浪费在注定失败的调度尝试上,问题可能出在资源碎片化或者调度队列的激活策略上。如果 extension point 耗时集中在某个插件,比如 InterPodAffinity 或 TaintToleration,就可以针对性地调整。
另一个实用手段是提升调度器日志级别。将 kube-scheduler 的日志参数设置为 --v=4 以上,可以看到每个 Pod 被哪些插件在哪些节点上拒绝,快速判断是否存在异常的拒绝模式,例如某个 Pod 的亲和性配置导致它几乎不可能找到满足条件的节点。
三、具体的优化手段
1. 启用百分比预选
从较新版本开始,调度器支持通过配置 percentageOfNodesToScore 来限制预选阶段评估的节点比例。例如集群有 10000 个节点,设置只评估 30%,调度器找到足够多的可行节点后就提前结束预选。对于大集群来说,这个参数对降低调度延迟的效果非常直接,代价是可能选不到理论上的最优节点。
apiVersion: kubescheduler.config.k8s.io/v1 kind: KubeSchedulerConfiguration profiles: - schedulerName: default-scheduler percentageOfNodesToScore: 30
2. 精简调度插件
默认的调度框架启用了一整套插件,但并不是每个集群都需要全部能力。如果业务上从不使用 Pod 亲和性,可以在配置中禁用 InterPodAffinity;不使用拓扑打散也可以关闭相应的插件。每禁用一个插件,就少了一轮全节点扫描的计算。禁用方式是通过 plugins 字段将对应插件的 Enable 改为 Disable。
3. 调整并行度与绑定吞吐
预选和优选阶段的并行度由参数 parallelism 控制,默认值通常等于节点数的平方根的十分之一(最小为1)。在 CPU 资源充足的控制面上,适当调高这个值可以让多节点的评估并行执行。另外绑定阶段依赖与 API Server 的交互,批量绑定的 QPS 和 Burst 限制过低时,绑定会变成新瓶颈,需要同步调整 clientConnection 相关的限流参数。
apiVersion: kubescheduler.config.k8s.io/v1 kind: KubeSchedulerConfiguration parallelism: 32 clientConnection: kubeconfig: /etc/kubernetes/scheduler.conf leaderElection: leaderElect: true
4. 消除调度失败的根源
与其让调度器反复尝试注定失败的 Pod,不如从源头减少失败。常见做法包括:为 Pod 设置合理的 requests,避免碎片化资源导致永远凑不齐;使用优先级和抢占让关键任务优先得到资源;对批量任务使用 Job 的并发控制,避免一次性压入过多 Pod。还可以通过 podInitialBackoffSeconds 和 podMaxBackoffSeconds 调整失败 Pod 的重试退避时间,降低无效重试频率。
四、优化效果验证与注意事项
任何优化都应该以指标为验证依据。建议在调整前后分别记录端到端调度延迟的分位数(尤其是 P99)、每秒成功调度的 Pod 数量,以及调度失败率。一个健康的集群,P99 调度延迟通常应该控制在几百毫秒以内,批量提交时吞吐应该平稳上升而不是出现断崖。
需要注意,百分比预选虽然能大幅提速,但会牺牲一定的调度质量,节点分布可能不如全量评估均匀;禁用插件前务必确认业务确实没有使用对应能力,否则会出现调度行为不符合预期的问题。此外,如果集群规模已经达到数千节点,还应该考虑控制面整体容量,包括 etcd 的写入性能和 API Server 的 watch 推送压力,调度器瓶颈有时只是控制面问题的外在表现。
总的来说,调度器优化是一个先测量、再动手的过程。弄清楚延迟到底花在队列、预选、优选还是绑定,比盲目调参重要得多。结合百分比预选、插件精简、并行度调整这几个手段,绝大多数大规模集群的调度吞吐都能获得明显改善。
Kubernetes调度器调度性能优化调度队列修改时间:2026-09-09 12:40:51