2. Kubernetes 调度器基础:kube-scheduler 工作原理、调度框架与调度周期

Kubernetes 调度器(kube-scheduler)是控制平面的核心组件之一,负责将待调度的 Pod 绑定到最合适的 Node 上。理解其工作原理、调度框架(Scheduling Framework)以及调度队列与调度周期,是掌握多集群调度策略的前提。

2.1 kube-scheduler 工作原理

kube-scheduler 通过监听 API Server 获取未调度的 Pod(spec.nodeName 为空),经过一系列过滤、评分、绑定步骤,最终将 Pod 与 Node 绑定。其核心工作流程如下:

  1. 监听与入队:通过 Informer 机制监听 Pod 和 Node 的变化,将待调度 Pod 加入调度队列。
  2. 调度周期:从队列中取出一个 Pod,依次执行过滤(Predicates)和评分(Priorities)算法。
  3. 绑定周期:将选中的 Node 信息写入 Pod 的 spec.nodeName,完成绑定。
  4. 异步绑定:绑定操作是异步的,调度器不会等待绑定结果即开始处理下一个 Pod。
关键指标:调度延迟(Scheduling Latency)是衡量调度器性能的核心指标,通常要求 P99 小于 100ms。

2.2 调度框架(Scheduling Framework)

Kubernetes 从 v1.19 开始引入调度框架,将调度周期和绑定周期拆分为多个可扩展的扩展点(Extension Points)。调度框架允许用户通过实现插件(Plugin)来定制调度行为,而无需修改核心代码。

调度框架的核心扩展点如下表所示:

扩展点 阶段 说明 常见插件示例
QueueSort 调度队列 对队列中的 Pod 进行排序 PrioritySort
PreFilter 调度周期 预处理 Pod 信息,检查是否满足调度前提 NodeResourcesFit
Filter 调度周期 过滤不满足条件的 Node NodeName, PodTopologySpread
PostFilter 调度周期 当所有 Node 都被过滤时,执行抢占或失败处理 DefaultPreemption
PreScore 调度周期 评分前的预处理 NodeResourcesBalancedAllocation
Score 调度周期 对通过过滤的 Node 进行评分 NodeResourcesLeastAllocated, ImageLocality
NormalizeScore 调度周期 对评分结果进行归一化 NodeResourcesMostAllocated
Reserve 绑定周期 预留资源,防止并发冲突 VolumeBinding
Permit 绑定周期 允许或拒绝绑定,支持等待/超时 NodeAffinity
PreBind 绑定周期 绑定前的准备工作 NodeVolumeLimits
Bind 绑定周期 执行绑定操作 DefaultBinder
PostBind 绑定周期 绑定后的清理或通知 NodeResourcesFit
实践建议:在多集群场景下,可以通过实现自定义的 Filter 和 Score 插件,将集群负载、网络延迟、成本等维度纳入调度决策。

下图展示了调度框架中扩展点与调度周期的关系:

调度框架扩展点与调度周期 调度队列 QueueSort 调度周期(Scheduling Cycle) PreFilter Filter PostFilter PreScore Score Normalize 绑定周期(Binding Cycle) Reserve Permit PreBind Bind PostBind Pod 绑定完成 说明: • 调度周期是同步的,绑定周期是异步的,两者通过 Permit 扩展点解耦。 • 每个扩展点可以注册多个插件,插件按配置顺序执行。 • 多集群调度器可以复用此框架,通过自定义 Filter/Score 插件实现集群维度的调度决策。

2.3 调度队列

调度队列负责管理待调度的 Pod,是调度器的入口。Kubernetes 使用优先级队列(Priority Queue)实现,支持三种子队列:

  • activeQ:存放等待调度的 Pod,按优先级排序。
  • backoffQ:存放调度失败的 Pod,经过退避时间后重新入队。
  • unschedulableQ:存放因资源不足等原因无法调度的 Pod,当集群资源变化时重新评估。
注意:调度队列的排序由 QueueSort 插件决定。默认按 Pod 优先级(PriorityClass)排序,优先级高的 Pod 先被调度。在多集群场景下,可以通过自定义 QueueSort 插件实现跨集群的优先级排序。

2.4 调度周期详解

调度周期是调度器的核心执行单元,分为过滤阶段和评分阶段。过滤阶段确保 Node 满足 Pod 的硬性约束,评分阶段则从满足条件的 Node 中选出最优解。

2.4.1 过滤阶段(Filtering)

过滤阶段依次执行多个 Filter 插件,任何一个插件返回失败,该 Node 即被排除。常见的过滤条件包括:

  • 节点资源是否满足 Pod 的 Request
  • 节点是否满足 NodeSelector 和 NodeAffinity
  • Pod 是否与节点上的 Pod 存在端口冲突
  • Pod 是否满足 PodTopologySpread 约束

2.4.2 评分阶段(Scoring)

评分阶段对通过过滤的 Node 进行打分,分数范围 0-100。调度器最终选择总分最高的 Node。如果多个 Node 分数相同,则随机选择。常见的评分策略包括:

  • LeastRequestedPriority:优先选择资源利用率低的节点,实现负载均衡。
  • MostRequestedPriority:优先选择资源利用率高的节点,实现资源集中。
  • BalancedResourceAllocation:优先选择 CPU 和内存使用率均衡的节点。

下图展示了调度周期中过滤与评分的详细流程:

调度周期:过滤与评分流程 Pod 入队 过滤阶段(Filter) 评分阶段(Score) 选择最优 Node 过滤插件示例 • NodeResourcesFit:检查资源是否充足 • NodeName:检查节点名称是否匹配 • NodeUnschedulable:排除不可调度节点 • PodTopologySpread:检查拓扑分布约束 评分插件示例 • NodeResourcesLeastAllocated:负载均衡 • NodeResourcesMostAllocated:资源集中 • ImageLocality:优先本地镜像 • TaintToleration:容忍度评分

2.5 绑定周期

绑定周期在调度周期之后执行,负责将 Pod 与选中的 Node 进行绑定。绑定周期包含 Reserve、Permit、PreBind、Bind、PostBind 五个扩展点。其中:

  • Reserve:在缓存中预留资源,防止并发调度冲突。
  • Permit:允许或拒绝绑定,支持等待(例如等待 CSI 卷挂载完成)。
  • Bind:实际执行绑定操作,默认通过 API Server 更新 Pod 的 spec.nodeName。
多集群场景:在多集群调度器中,绑定周期可以扩展为跨集群的绑定操作,例如在选定集群后,通过该集群的 API Server 完成绑定,或通过 Federation 控制面进行统一绑定。

2.6 调度器配置与扩展

Kube-scheduler 支持通过 KubeSchedulerConfiguration 配置文件进行灵活配置,包括:

apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
  - schedulerName: default-scheduler
    plugins:
      filter:
        enabled:
          - name: NodeResourcesFit
          - name: NodeName
        disabled:
          - name: "*"
      score:
        enabled:
          - name: NodeResourcesLeastAllocated
            weight: 2
          - name: ImageLocality
            weight: 1
    pluginConfig:
      - name: NodeResourcesLeastAllocated
        args:
          resources:
            - name: cpu
              weight: 1
            - name: memory
              weight: 1

通过配置多个 Profile,可以实现多调度器共存,每个 Profile 使用不同的插件组合,适用于不同的工作负载类型。

扩展建议:在多集群调度器中,可以创建自定义 Profile,启用跨集群的 Filter 插件(如集群资源过滤)和 Score 插件(如集群负载评分),实现集群维度的调度决策。