引言

Kubernetes调度器(kube-scheduler)是集群的大脑,它决定了每个Pod应该运行在哪个节点上。尽管调度决策看起来只是"选一个节点",但其内部实现涉及队列管理、缓存机制、多阶段过滤和评分等多个精密的子系统。理解调度器源码,是掌握Kubernetes集群性能调优的关键一步。

1. 调度器整体架构

调度器的核心是一个无限循环,从scheduling queue中取出Pod,为每个Pod选择一个最佳节点:

  • Informer监听Pod/Node/Service等对象的创建与变化
  • Scheduling Queue维护待调度的Pod队列(activeQ/unschedulableQ/backoffQ)
  • Scheduling Framework提供插件化的调度管线
  • Scheduler Cache维护集群状态的快照,用于调度决策

2. 调度队列的三层结构

调度队列使用三种数据结构管理Pod:

  • activeQ:优先队列(基于Pod.Priority或进队时间),调度器优先从这里取Pod
  • unschedulableQ:无法被调度的Pod,定时会被重新检查(默认60s)
  • backoffQ:调度失败的Pod按退避时间排序,默认1s到60s的二次方等比退避

当一个Pod首次进入队列时,它被放入activeQ。如果调度失败,它先进入backoffQ,等待退避时间后移入activeQ。如果Pod长时间无法调度或Node资源变化,系统也会主动将unschedulableQ中的Pod重新激活。

3. Scheduling Framework的插件管线

Kubernetes 1.15引入Scheduling Framework后,调度过程被分解为多个可扩展的插件阶段:

PreEnqueue阶段:检查Pod是否有资格进入队列,返回Code Unschedulable/Pending会阻止入队。

QueueSort阶段:确定Pod在队列中的排序。默认Less函数基于Priority数值(FIFO for equal priority),可替换为自定义排序器。

PreFilter阶段:计算集群和Pod的元数据,存入CycleState以供后续插件使用。典型实现包括计算Node资源总数、Pod资源需求汇总等。

Filter阶段:以"一票否决"的方式排除不满足条件的节点。代表性插件有:NodeResourcesFit(检查CPU/内存/EphemeralStorage)、NodeInfo(节点状态)、TaintToleration(污点容忍)、NodeAffinity/ PodAffinity(亲和性规则)等。

PostFilter阶段:在Filter阶段之后触发,被Preemption插件用于启用抢占机制。Filter返回所有节点被拒绝后才执行PostFilter。

PreScore阶段:为Score阶段准备数据,类似PreFilter为Filter服务。

Score阶段:对所有通过Filter的节点打分(0-100分)。NodeResourcesFit计算资源余量百分比,ImageLocality偏好已有镜像的节点,PodAffinity应用亲和性规则。

NormalizeScore阶段(1.21+):将Score归一化,调整各插件分数的权重。

Reserve/Unreserve阶段:在Pod正式绑定到节点之前预留资源,支持乐观锁并发控制。

Permit阶段:对选定的节点做出最终决定:Allow(立即绑定)/Deny(拒绝该节点)/Wait(等待一段时间再决定,用于等待IngressBinding)。

PreBind/PostBind阶段:在绑定Pod到节点之前/之后执行附加操作,如PV绑定(CIDR allocate)。

4. 抢占机制(Preemption)

当一个高优先级Pod无法找到合适的节点时,调度器会尝试抢占(evict)低优先级Pod来腾出空间。抢占流程涉及:

  • 遍历所有节点,模拟释放低优先级Pod后的资源状态
  • 选择"抢占代价"(需删除的Pod数×Priority损失)最小的节点
  • 通过Eviction API优雅删除被抢占的Pod(可配置grace period)
  • 抢占可能导致Pod迁移和重新调度,因此应谨慎配置PodPriority和PriorityClass。

    5. Scheduler Cache与无锁快照

    Scheduler Cache维护了集群所有Node和Pod的最新快照。为了保证调度决策的一致性而不加全局锁,Scheduler Cache使用了"调度周期"(scheduling cycle)的概念:

    • 调度周期从快照片(snapshot)开始,期间所有检查都基于这个副本
    • Node/Pod更新暂存在incoming channel中
    • 如果Pod在绑定步骤失败,会回退到re-queue流程而不是破坏Cache完整性

    6. 多调度器与扩展机制

    Kubernetes 1.18后支持运行多个调度器:

    • kube-scheduler默认调度器,内置全面的通用调度逻辑
    • 自定义调度器(如Volcano,Yunikorn)通过多组件调度实现细粒度装箱
    • kubelet的StartupAllowedIndependentRestartPolicy可以协同调度器与Kubelet的重启行为

    7. 源码级调优实践

    实际部署中的关键调优参数:

    • percentageOfNodesToScore(默认50%) - 当节点数超过500时,只对其中50%的节点打分
    • parallelism(默认16) - 并行调度的协程数
    • nodeStatusUpdateFrequency - Informer同步Node状态的时间间隔
    • HardPodAffinitySymmetricWeight - NodeAffinity/PodAffinity的加权比

    总结

    Kubernetes调度器是一个经过多年进化的高度模块化的系统。从简单的Filtering到多段Framework管线,从评分到抢占再到覆盖式调度,调度器的演进反映了云原生环境对调度效率与公平性的持续追求。理解不仅停留在配置层面,深入到源码层面,才能在面对复杂业务场景时做出更合理的调度决策。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部