3、Pod调度基础:调度器工作原理、调度队列、调度周期、过滤与打分阶段
Pod 调度是 Kubernetes 集群的核心控制面行为之一。调度器(kube-scheduler)负责为新创建的、尚未绑定到节点的 Pod 选择一个最合适的节点。理解调度器的工作原理、调度队列、调度周期以及过滤与打分阶段,是进行集群资源预留和升级窗口管理的基础。
3.1 调度器工作原理概述
kube-scheduler 以独立组件或静态 Pod 形式运行,通过 Kubernetes API Server 监听未调度的 Pod(spec.nodeName 为空)。调度器为每个待调度 Pod 执行一个完整的调度周期,最终将 Pod 绑定到目标节点。其核心工作流程可概括为:
- 监听与入队:通过 Informer 机制监听 Pod 变化,将未调度的 Pod 加入调度队列。
- 调度周期:从队列中取出 Pod,依次执行过滤(Predicates)和打分(Priorities)阶段。
- 绑定周期:将调度结果(Pod 与 Node 的绑定关系)异步写入 API Server。
3.2 调度队列
调度队列是调度器的输入缓冲,负责管理待调度的 Pod。Kubernetes 默认使用三种队列结构,确保调度公平性与优先级处理:
| 队列类型 | 作用 | 调度顺序 |
|---|---|---|
| ActiveQ(活跃队列) | 存放所有等待调度的 Pod,按优先级排序 | 高优先级 Pod 优先出队 |
| BackoffQ(退避队列) | 存放调度失败的 Pod,等待重试 | 退避时间到期后移回 ActiveQ |
| UnschedulableQ(不可调度队列) | 存放因资源不足、节点不可用等原因无法调度的 Pod | 集群拓扑变化(如新增节点)时重新评估 |
3.3 调度周期
调度周期是调度器为单个 Pod 执行的核心决策过程,包含两个主要阶段:过滤(Filtering)和打分(Scoring)。整个周期是同步执行的,确保调度决策的原子性。
3.4 过滤阶段
过滤阶段(又称 Predicates 阶段)的目标是筛选出满足 Pod 运行基本条件的节点。调度器按顺序执行一组内置的过滤插件,任何一个插件返回失败,该节点即被排除。
常用的过滤插件包括:
- PodFitsResources:检查节点剩余 CPU、内存、GPU 等资源是否满足 Pod 的 requests。
- PodFitsHostPorts:检查 Pod 请求的端口是否已被占用。
- MatchNodeSelector:检查 Pod 的
nodeSelector是否匹配节点标签。 - PodToleratesNodeTaints:检查 Pod 的 tolerations 是否能容忍节点的 taints。
- CheckNodeUnschedulable:检查节点是否被标记为不可调度(
.spec.unschedulable: true)。 - NodeAffinity:检查节点亲和性规则。
kubectl cordon 标记为不可调度后,CheckNodeUnschedulable 插件会直接过滤掉该节点。这是实现“节点优雅下线”的关键机制。
3.5 打分阶段
打分阶段(又称 Priorities 阶段)对通过过滤的节点进行评分,选出最优节点。每个打分插件返回 0-100 的分数,调度器按权重加权求和,最终选择总分最高的节点。
| 打分插件 | 评分逻辑 | 适用场景 |
|---|---|---|
| LeastRequestedPriority | 优先选择资源使用率最低的节点(CPU+内存) | 负载均衡,避免热点 |
| BalancedResourceAllocation | 优先选择 CPU 和内存使用率最均衡的节点 | 资源碎片最小化 |
| MostRequestedPriority | 优先选择资源使用率最高的节点 | 集群利用率最大化 |
| NodeAffinityPriority | 根据节点亲和性权重打分 | 拓扑感知调度 |
| TaintTolerationPriority | 根据 Pod 容忍的污点数量打分 | 容忍度高的 Pod 优先调度 |
3.6 调度器扩展机制
Kubernetes 调度器支持通过 Scheduler Framework 进行扩展,允许用户自定义调度逻辑。框架定义了多个扩展点(Extension Points),分布在调度周期的不同阶段:
- QueueSort:自定义调度队列排序逻辑。
- PreFilter / Filter / PostFilter:过滤阶段的前、中、后处理。
- PreScore / Score / NormalizeScore:打分阶段的前、中、分数归一化。
- Reserve / Permit / PreBind / Bind / PostBind:绑定周期的扩展点。
3.7 调度器配置与性能
调度器的性能直接影响集群的 Pod 启动速度。以下参数对调度吞吐量有显著影响:
| 参数 | 默认值 | 说明 |
|---|---|---|
--kube-api-qps |
50 | 调度器与 API Server 的 QPS 限制 |
--kube-api-burst |
100 | 突发请求数 |
--parallelism |
16 | 并行调度 Pod 的数量 |
--percentage-of-nodes-to-score |
50 | 打分阶段评估的节点比例(0-100) |
percentage-of-nodes-to-score 可减少调度延迟,但可能降低调度质量。升级窗口期间建议保持默认值,确保调度公平性。
3.8 调度器与资源预留的关系
资源预留(Resource Reservation)直接影响调度器的过滤阶段。调度器在计算节点可用资源时,会考虑以下因素:
- 节点容量:
status.capacity中的 CPU、内存等总量。 - 已分配资源:所有已绑定 Pod 的
requests总和。 - 系统预留:kubelet 的
--system-reserved和--kube-reserved参数预留的资源。 - 节点可分配资源:
status.allocatable= 容量 - 系统预留 - kubelet 预留。
调度器使用 status.allocatable 作为节点可用资源的基准,而非 status.capacity。因此,合理的资源预留配置可以防止调度器将 Pod 分配到资源已被系统进程占用的节点。
kubectl describe node 检查节点的 Allocatable 值,确保预留资源充足。如果发现 Allocatable 远低于 Capacity,说明系统预留过高,可能导致 Pod 调度失败。