2. Kubernetes 调度器基础:调度器架构、调度流程、默认调度策略

2.1 调度器架构概览

Kubernetes 调度器(kube-scheduler)是控制平面的核心组件之一,负责将待调度的 Pod 绑定到最合适的 Node 上。调度器以插件化架构设计,通过一系列可配置的调度阶段完成决策。

关键设计原则: 调度器不直接管理 Pod 生命周期,仅负责“调度决策”——将 Pod 与 Node 的绑定关系写入 API Server。Node 上的 kubelet 监听绑定后启动容器。
Kubernetes 调度器架构组件 API Server 调度器主循环 调度队列 过滤阶段(Predicates) 打分阶段(Priorities) 绑定阶段 扩展调度器(Extender) Node 缓存 / 调度缓存 说明: 调度器通过 Informer 机制监听 API Server 中的 Pod 和 Node 变化,维护本地缓存以减少 API Server 压力。

2.2 调度流程详解

Kubernetes 调度器采用“调度周期 + 绑定周期”两阶段模型。每个 Pod 的调度过程分为以下步骤:

  1. 调度队列入队: 新创建的 Pod 或因调度失败重新入队的 Pod 进入调度队列(Scheduling Queue)。队列支持优先级排序和重试机制。
  2. 过滤阶段(Filtering): 遍历所有 Node,应用一组过滤插件(Predicates),筛选出满足 Pod 资源需求、节点选择器、亲和性等约束的候选节点集合。
  3. 打分阶段(Scoring): 对过滤后的候选节点进行打分,每个打分插件(Priority)输出 0-100 的分数,最终加权求和得到每个节点的总分。
  4. 选择最优节点: 选择总分最高的节点作为调度目标。若存在多个同分节点,则随机选择一个。
  5. 绑定阶段(Binding): 调度器将 Pod 与选定 Node 的绑定关系写入 API Server。绑定成功后,kubelet 开始创建 Pod。
调度失败重试: 如果过滤阶段没有找到任何可用节点,Pod 会留在调度队列中等待重试。调度器会持续监听 Node 资源变化,一旦有节点满足条件则重新调度。

2.3 默认调度策略

Kubernetes 默认调度器内置了多组过滤和打分插件。以下表格列出了最常用的默认策略:

策略类型 插件名称 功能描述 权重(打分)
过滤(Predicates) NodeResourcesFit 检查 Node 剩余 CPU/内存是否满足 Pod 请求 —
NodeName 检查 Pod 是否指定了 nodeName —
PodTopologySpread 确保 Pod 在拓扑域(如区域、节点)中均匀分布 —
NodeAffinity 检查 Node 标签是否满足 Pod 的节点亲和性规则 —
TaintToleration 检查 Pod 是否容忍 Node 上的污点 —
打分(Priorities) NodeResourcesBalancedAllocation 优先选择 CPU 和内存使用率均衡的节点 1
ImageLocality 优先选择已缓存 Pod 所需镜像的节点 1
InterPodAffinity 根据 Pod 间亲和性/反亲和性打分 2
NodeAffinity 根据节点亲和性优先级规则打分 2

2.4 调度器扩展机制

默认调度策略无法满足所有场景,Kubernetes 提供了三种扩展方式:

  • Scheduler Extender: 通过 HTTP/HTTPS 调用外部服务,在过滤和打分阶段注入自定义逻辑。适用于与外部资源管理系统集成。
  • Scheduler Framework 插件: 从 Kubernetes 1.19 开始,调度器采用插件化框架(Scheduling Framework),允许用户编写 Go 插件注册到调度周期的任意扩展点(Filter、Score、PreBind、PostBind 等)。
  • 自定义调度器: 编写独立的调度器二进制,通过 schedulerName 字段让 Pod 选择使用自定义调度器。
注意: Scheduler Extender 在过滤阶段会显著增加调度延迟,因为每个 Node 都需要经过一次 HTTP 调用。生产环境推荐使用 Scheduling Framework 插件以获得更好的性能。

2.5 调度器参数配置

调度器通过 KubeSchedulerConfiguration 对象进行配置,支持 YAML 格式。以下是一个典型的配置片段:

apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
  - schedulerName: default-scheduler
    plugins:
      filter:
        enabled:
          - name: NodeResourcesFit
          - name: NodeName
          - name: PodTopologySpread
        disabled:
          - name: TaintToleration
      score:
        enabled:
          - name: NodeResourcesBalancedAllocation
            weight: 2
          - name: ImageLocality
            weight: 1
    pluginConfig:
      - name: NodeResourcesFit
        args:
          scoringStrategy:
            type: LeastAllocated

关键参数说明:

  • profiles: 支持多调度器配置,每个 profile 对应一个 schedulerName。
  • plugins: 控制每个扩展点(filter、score、preBind 等)启用或禁用的插件列表。
  • pluginConfig: 为特定插件提供自定义参数,如打分策略类型(LeastAllocated / MostAllocated / RequestedToCapacityRatio)。
  • weight: 打分插件的权重系数,影响最终总分。

2.6 调度流程可视化

以下 SVG 图展示了单个 Pod 从创建到绑定完成的完整调度流程:

Pod 调度完整流程 1. Pod 创建 API Server 写入 etcd 2. 入调度队列 优先级排序 + 重试 3. 过滤阶段 筛选候选 Node 4. 打分阶段 加权评分 5. 选择最优 Node 最高分 / 随机 6. 绑定阶段 写入绑定关系 7. kubelet 响应 拉取镜像启动容器 调度失败重试 关键时间点: • 过滤阶段:如果候选节点数为 0,Pod 进入重试队列,等待资源变化事件。 • 打分阶段:所有候选节点都会参与打分,即使分数相同也会随机选择一个。 • 绑定阶段:调度器使用乐观锁(resourceVersion)确保绑定操作的原子性。

2.7 调度器与 OPA Gatekeeper 的协同点

理解调度器基础后,可以明确 OPA Gatekeeper 在调度场景中的介入位置:

  • Pod 准入阶段: Gatekeeper 可以在 Pod 创建时拦截并验证调度相关字段(如 nodeSelector、affinity、tolerations),确保符合组织策略。
  • Node 标签管理: Gatekeeper 可以约束 Node 标签的创建和修改,间接影响调度器的节点选择结果。
  • 调度器参数合规: Gatekeeper 可以验证 KubeSchedulerConfiguration 中的插件启用/禁用是否符合安全基线。