3. K8s调度器架构:Scheduler组件、调度队列、调度框架概览
Kubernetes 调度器(kube-scheduler)是控制平面中负责将 Pod 绑定到合适 Node 的核心组件。理解其内部架构——尤其是调度队列与调度框架——是诊断调度故障、优化调度性能以及实现 GitOps 回滚窗口内稳定调度的基础。
3.1 Scheduler 组件架构
kube-scheduler 以独立进程运行,通过 API Server 监听未调度的 Pod(spec.nodeName 为空),经过一系列筛选与打分后,将 Pod 绑定到最优 Node。其核心组件包括:
| 组件 | 职责 | 关键数据结构/行为 |
|---|---|---|
| 调度队列 | 管理待调度 Pod 的排队、优先级、重试与回退 | activeQ / backoffQ / unschedulableQ |
| 调度框架 | 定义调度周期与绑定周期的扩展点插件链 | QueueSort / PreFilter / Filter / Score / Reserve / Permit / PreBind / Bind |
| 调度缓存 | 维护集群 Node 与 Pod 的实时快照,避免重复 API 调用 | NodeInfo / PodInfo / assumed Pods |
| 调度器主循环 | 从队列取出 Pod,调用框架执行调度,处理绑定与缓存更新 | scheduleOne() 循环 |
关键点:调度队列与调度框架是调度器内部最核心的两个子系统。队列决定了 Pod 被调度的顺序与重试策略;框架决定了调度决策的扩展性与可定制性。
3.2 调度队列:三级队列模型
kube-scheduler 使用三级队列管理待调度 Pod,这是故障排查中必须理解的数据流:
- activeQ(活跃队列):存放所有等待调度的 Pod,按优先级排序(由 QueueSort 插件决定)。调度器主循环每次从此队列头部取出一个 Pod。
- backoffQ(回退队列):存放调度失败但尚未达到最大重试次数的 Pod。每个 Pod 有独立的回退时间(指数退避),到期后移回 activeQ。
- unschedulableQ(不可调度队列):存放因资源不足、节点选择器不匹配等不可调度错误的 Pod。当集群拓扑变化(如新增 Node、资源释放)时,触发重新入队。
故障排查提示:当 Pod 长时间处于 Pending 状态时,检查调度器日志中的队列状态。若 Pod 在 unschedulableQ 中,说明调度器认为当前无可用 Node;若在 backoffQ 中,说明调度失败正在退避重试。
3.3 调度框架:扩展点与插件链
调度框架(Scheduling Framework)是 Kubernetes 1.19+ 引入的可扩展调度架构。它将调度周期与绑定周期拆分为多个扩展点,每个扩展点可注册多个插件。调度器按顺序执行插件链,任何插件返回失败则终止当前调度周期。
3.3.1 调度周期扩展点
| 扩展点 | 执行时机 | 典型插件示例 | 失败影响 |
|---|---|---|---|
| QueueSort | Pod 入队时排序 | PrioritySort | 影响调度顺序 |
| PreFilter | 预处理 Pod 信息,校验前置条件 | NodeResourcesFit, PodTopologySpread | Pod 进入 backoffQ |
| Filter | 筛选满足条件的 Node | NodeUnschedulable, NodeAffinity, TaintToleration | Pod 进入 unschedulableQ |
| PostFilter | 所有 Node 均被过滤后执行 | DefaultPreemption | 触发抢占或标记不可调度 |
| PreScore | 打分前预处理 | NodeResourcesFit | 影响打分结果 |
| Score | 对通过 Filter 的 Node 打分 | NodeResourcesBalancedAllocation, ImageLocality | 选择最高分 Node |
| NormalizeScore | 对分数进行归一化 | NodeResourcesFit | 修正分数范围 |
| Reserve | 在缓存中预留资源 | VolumeBinding | 预留失败则回滚 |
| Permit | 批准或延迟绑定 | 自定义准入控制 | 等待批准或超时 |
3.3.2 绑定周期扩展点
| 扩展点 | 执行时机 | 典型插件示例 | 失败影响 |
|---|---|---|---|
| PreBind | 绑定前执行预处理 | VolumeBinding | 绑定失败,回滚 Reserve |
| Bind | 执行 Pod 与 Node 的绑定 | DefaultBinder | 绑定失败,回滚 Reserve |
| PostBind | 绑定成功后清理或通知 | VolumeBinding | 不影响调度结果 |
故障排查重点:调度框架的扩展点执行顺序是固定的。若 Pod 调度失败,应首先确定失败发生在哪个扩展点。例如:Filter 失败通常意味着资源不足或节点亲和性不满足;Permit 失败可能涉及自定义准入插件或超时配置。
3.4 调度器故障排查关键路径
基于上述架构,当 Pod 调度异常时,建议按以下路径排查:
- 检查 Pod 状态与事件:
kubectl describe pod <pod-name>查看 Events 字段,定位失败阶段。 - 检查调度器日志:
kubectl logs -n kube-system kube-scheduler-<node>搜索 Pod 名称,查看队列流转与扩展点执行结果。 - 检查调度队列状态:通过调度器 HTTP 端点
/metrics查看scheduler_queue_incoming_pods_total、scheduler_pending_pods等指标。 - 检查调度框架插件配置:确认
kube-scheduler-config中插件启用顺序与参数是否正确。 - 检查集群资源与拓扑:确认 Node 状态、资源容量、污点容忍、亲和性规则是否满足 Pod 需求。
GitOps 回滚窗口关联:在回滚窗口内,调度器可能因资源竞争、插件配置变更或队列积压导致 Pod 调度延迟。理解调度器架构有助于在回滚前预判调度风险,并在回滚后快速恢复调度稳定性。