2. Kubernetes 调度基础:调度器工作原理、调度队列、调度周期、Predicates 与 Priorities 算法

2.1 调度器核心工作原理

Kubernetes 调度器(kube-scheduler)是控制平面的核心组件之一,负责将待调度的 Pod 绑定到最合适的 Node 上。其本质是一个基于 事件驱动 和 周期循环 的决策引擎,通过监听 API Server 中未调度的 Pod(spec.nodeName 为空),执行一套可插拔的调度算法,最终将 Pod 与 Node 的绑定关系写回 etcd。

关键设计原则: 调度器不直接管理 Pod 的生命周期,只负责“分配”决策;每个 Pod 的调度是独立且串行的,保证同一时刻只有一个 Pod 进入调度周期。
kube-scheduler 核心工作流程 API Server 调度队列 调度周期 绑定周期 写回 API Server 说明: 调度器通过 Informer 机制监听 Pod 和 Node 的变化,将待调度 Pod 放入优先队列; 调度周期和绑定周期是串行执行的,绑定失败会重新入队等待下一次调度。

2.2 调度队列(Scheduling Queue)

调度队列是调度器的“待办事项列表”,负责管理所有等待调度的 Pod。Kubernetes 使用 优先级队列 实现,Pod 在队列中的顺序由其 优先级(Priority) 和 入队时间 共同决定。

队列类型 作用 数据来源
activeQ(活跃队列) 存放所有等待调度的 Pod,按优先级排序 API Server 中 spec.nodeName="" 的 Pod
backoffQ(回退队列) 存放调度失败、需要等待一段时间后重试的 Pod 调度周期或绑定周期失败的 Pod
unschedulableQ(不可调度队列) 存放因资源不足、节点不可用等原因暂时无法调度的 Pod Predicates 阶段失败的 Pod
性能调优要点: 当集群规模较大(>1000 Node)时,unschedulableQ 中的 Pod 可能因频繁的 Node 更新事件被反复唤醒,导致调度器 CPU 飙升。可通过调整 --permit-every-one-second 和 --unschedulableQ-burst 参数控制回填速率。

2.3 调度周期(Scheduling Cycle)

调度周期是调度器为单个 Pod 选择 Node 的完整过程,分为两个阶段:过滤(Filtering) 和 打分(Scoring)。调度周期是串行的,同一时间只有一个 Pod 在执行调度周期。

调度周期内部流程(Filtering → Scoring) 过滤阶段 候选节点集 打分阶段 Predicates 算法 节点预选(NodePreFilter) 节点过滤(NodeFilter) Priorities 算法 节点打分(Score) 归一化(NormalizeScore) 选择最优节点 调度周期结束后,调度器进入绑定周期,将 Pod 与最优 Node 的绑定关系写入 API Server。

2.4 Predicates 算法(过滤阶段)

Predicates 算法是一组 硬约束 检查,用于过滤掉不满足 Pod 运行条件的 Node。只有通过所有 Predicates 检查的 Node 才会进入打分阶段。常见的 Predicates 算法包括:

  • PodFitsResources: 检查 Node 剩余 CPU、内存是否满足 Pod 的 requests 需求。
  • PodFitsHostPorts: 检查 Node 上是否已有 Pod 占用了相同的 hostPort。
  • PodSelectorMatches: 检查 Node 的标签是否匹配 Pod 的 nodeSelector。
  • CheckNodeCondition: 检查 Node 是否处于 Ready、DiskPressure 等健康状态。
  • CheckVolumeBinding: 检查 Pod 使用的 PVC 是否能在该 Node 上挂载。
  • NoDiskConflict: 检查 Pod 使用的 Volume 是否与 Node 上已有 Pod 冲突。
  • MatchInterPodAffinity: 检查 Pod 间的亲和性和反亲和性规则。
性能陷阱: 在大型集群中,PodFitsResources 和 MatchInterPodAffinity 是最耗时的 Predicates 算法。如果集群中 Node 数量超过 5000,建议启用 NodeResourcesFit 的 LeastAllocated 或 MostAllocated 策略,并合理设置 --hard-pod-affinity-weight 参数。

2.5 Priorities 算法(打分阶段)

Priorities 算法对通过过滤的 Node 进行 软评分,每个算法返回一个 0-100 的分数,最终加权求和得到每个 Node 的总分。调度器选择总分最高的 Node 作为目标节点。常见的 Priorities 算法包括:

算法名称 评分逻辑 权重(默认) 适用场景
LeastRequestedPriority 优先选择资源使用率低的 Node(CPU + 内存) 1 负载均衡、资源碎片最小化
MostRequestedPriority 优先选择资源使用率高的 Node 1 资源密集型应用、减少空闲 Node
BalancedResourceAllocation 优先选择 CPU 和内存使用率最均衡的 Node 1 混合负载、避免单资源瓶颈
NodeAffinityPriority 根据 preferredDuringSchedulingIgnoredDuringExecution 规则打分 2 节点亲和性调度
InterPodAffinityPriority 根据 Pod 间的亲和性/反亲和性规则打分 2 Pod 亲和性调度
ImageLocalityPriority 优先选择已缓存 Pod 所需镜像的 Node 1 镜像拉取加速

2.6 调度周期与绑定周期的协作

调度器将 Pod 的调度过程拆分为 调度周期 和 绑定周期,两者通过 异步通道 解耦。调度周期是串行的,绑定周期可以并发执行。这种设计使得调度器在等待绑定结果时,可以继续处理下一个 Pod 的调度周期,提升整体吞吐量。

性能调优关键指标:
  • 调度延迟(Scheduling Latency): Pod 从创建到被调度器选中 Node 的时间,通常应 < 100ms。
  • 绑定延迟(Binding Latency): 调度器将绑定关系写入 API Server 的时间,受 etcd 写入性能影响。
  • 调度吞吐量(Scheduling Throughput): 每秒能调度的 Pod 数量,默认约 10-50 Pod/s,可通过 --kube-api-qps 和 --kube-api-burst 调整。

2.7 调度器扩展机制

Kubernetes 调度器支持 调度框架(Scheduling Framework),允许用户通过 调度插件(Scheduler Plugin) 扩展调度逻辑。调度框架定义了多个扩展点:

  • QueueSort: 自定义调度队列的排序逻辑。
  • PreFilter / Filter: 对应 Predicates 阶段,可添加自定义过滤逻辑。
  • PreScore / Score / NormalizeScore: 对应 Priorities 阶段,可添加自定义打分逻辑。
  • Reserve / Permit / PreBind / Bind: 绑定周期的扩展点,用于预留资源、权限检查、自定义绑定逻辑。
Helm 集成提示: 在 Helm Chart 中部署自定义调度器时,可以通过 values.yaml 配置调度器的 plugins 和 pluginConfig,实现调度策略的声明式管理。例如,使用 NodeResourcesFit 插件的 scoringStrategy 字段切换 LeastAllocated 和 MostAllocated 策略。