2. Kubernetes 调度基础:调度器工作原理、调度队列、调度周期、调度框架概览
2.1 调度器核心职责与工作模型
Kubernetes 调度器(kube-scheduler)是控制平面的核心组件之一,负责将待调度的 Pod 绑定到最合适的 Node 上。其本质是一个资源匹配与约束满足问题求解器,遵循“谓词(Predicates)→ 优先级(Priorities)→ 绑定(Bind)”的经典流水线模型。
关键设计原则:调度器不直接管理 Pod 生命周期,仅负责“调度决策”;Pod 的创建、运行、终止由 kubelet 和控制器管理器负责。调度器保证全局最优近似解,而非最优解。
2.2 调度器工作原理与架构组件
kube-scheduler 以插件化调度框架(Scheduling Framework)为核心,通过注册一系列扩展点(Extension Points)实现可扩展的调度逻辑。其内部工作流程可抽象为以下组件:
| 组件/模块 | 职责 | 关键特性 |
|---|---|---|
| 调度队列(Scheduling Queue) | 管理待调度的 Pod,按优先级、创建时间、重试次数排序 | 支持 Backoff 机制、抢占式调度、Pod 去重 |
| 调度周期(Scheduling Cycle) | 为单个 Pod 执行一次完整的调度决策(Filter → Score → Normalize → Select) | 每个 Pod 独立执行,可并行调度多个 Pod |
| 绑定周期(Binding Cycle) | 将调度结果写入 API Server,触发 kubelet 创建 Pod | 异步执行,支持 Reserve、PreBind、Bind、PostBind 扩展点 |
| 调度框架(Scheduling Framework) | 定义扩展点接口,允许用户注入自定义调度逻辑 | 插件化架构,支持 QueueSort、PreFilter、Filter、PostFilter、PreScore、Score、NormalizeScore、Reserve、Permit、PreBind、Bind、PostBind |
调度队列 vs 调度周期:调度队列是“待办事项列表”,调度周期是“处理单个事项的流程”。队列负责排序和重试,周期负责具体的节点筛选和打分。
2.3 调度队列:Pod 排队与优先级管理
调度队列是调度器的“输入缓冲区”,负责管理所有待调度的 Pod。其核心设计包含三个子队列:
- ActiveQ(活跃队列):存放当前可被调度的 Pod,按优先级(PriorityClass)和创建时间排序。调度器每次从 ActiveQ 头部取出一个 Pod 进行调度。
- BackoffQ(退避队列):存放调度失败后需要等待一段时间再重试的 Pod。退避时间指数增长(如 1s → 2s → 4s → 8s),防止频繁重试导致系统抖动。
- UnschedulableQ(不可调度队列):存放因资源不足、节点不可用等原因无法调度的 Pod。当集群资源发生变化(如新节点加入、资源释放)时,这些 Pod 会被重新移回 ActiveQ。
调度队列性能风险:当集群规模较大(>5000 Pod)时,调度队列的排序和去重操作可能成为性能瓶颈。建议启用 Pod 优先级抢占 和 调度队列 Backoff 限流,避免低优先级 Pod 阻塞高优先级 Pod。
2.4 调度周期:从 Filter 到 Select 的完整决策链
调度周期是调度器为单个 Pod 执行一次完整调度决策的过程,包含以下核心阶段:
| 阶段 | 扩展点 | 输入 | 输出 | 典型插件 |
|---|---|---|---|---|
| 预处理 | PreFilter | Pod + Node 列表 | 预处理状态(如计算资源请求) | NodeResourcesFit |
| 过滤 | Filter | Pod + 单个 Node | 通过/不通过 | NodeUnschedulable, NodePorts, PodTopologySpread |
| 后过滤 | PostFilter | 过滤结果 | 抢占决策或修正 | Preemption |
| 预打分 | PreScore | Pod + 通过过滤的 Node | 打分上下文 | InterPodAffinity |
| 打分 | Score | Pod + 单个 Node | 分数(0-100) | NodeResourcesBalancedAllocation, ImageLocality |
| 归一化 | NormalizeScore | 所有 Node 分数 | 归一化后的分数 | DefaultPodTopologySpread |
| 选择 | Select(内置) | 归一化分数 | 最优 Node | 最高分节点(随机打破平局) |
调度周期性能优化:Filter 阶段是性能关键路径,建议将计算量大的插件(如 PodTopologySpread)放在 Score 阶段,而非 Filter 阶段。Filter 阶段应只做“硬约束”检查,Score 阶段做“软偏好”评估。
2.5 调度框架概览:插件化扩展点体系
Kubernetes 1.19+ 引入的调度框架(Scheduling Framework)彻底重构了调度器架构,将调度逻辑拆分为多个可插拔的扩展点。调度框架的核心设计理念:
- 扩展点(Extension Points):在调度周期的关键位置定义接口,允许用户注册自定义插件。
- 插件(Plugin):实现一个或多个扩展点接口的代码单元,可启用/禁用/配置。
- MultiPoint 扩展点:允许一个插件同时注册到多个扩展点,简化插件开发。
- 调度上下文(CycleState):在调度周期内传递状态信息,插件之间通过 CycleState 共享数据。
调度框架优势:相比旧版调度器(硬编码 Predicates + Priorities),调度框架支持动态加载插件、自定义调度策略、多调度器共存,极大提升了调度器的可扩展性和可维护性。
2.6 调度器工作流程总结
调度器的完整工作流程可归纳为以下步骤:
- 监听 Pod 事件:kube-scheduler 通过 Informer 监听 API Server 中未调度(
spec.nodeName为空)的 Pod。 - 入队排序:将待调度 Pod 加入调度队列,按优先级和创建时间排序。
- 出队调度:从 ActiveQ 头部取出一个 Pod,开始调度周期。
- 过滤节点:执行 Filter 插件,筛选出满足硬约束的 Node 列表。
- 打分排序:执行 Score 插件,对通过过滤的 Node 进行打分和归一化。
- 选择节点:选择分数最高的 Node(平局时随机选择)。
- 绑定节点:执行绑定周期,将 Pod 与 Node 的绑定关系写入 API Server。
- 异步处理:kubelet 监听到绑定事件后,在目标 Node 上创建并运行 Pod。
调度器故障风险:如果 kube-scheduler 发生故障(如崩溃、网络分区),所有待调度 Pod 将停留在 Pending 状态。建议部署多副本 kube-scheduler(leader election 模式),并配置调度器健康检查和Pod 调度超时告警。
2.7 调度器性能关键指标
| 指标 | 说明 | 推荐阈值 | 监控方式 |
|---|---|---|---|
| 调度延迟 | Pod 从入队到绑定完成的时间 | < 100ms(P99) | scheduler_e2e_scheduling_duration_seconds |
| 调度队列深度 | ActiveQ + BackoffQ + UnschedulableQ 中的 Pod 数量 | < 100 | scheduler_queue_incoming_pods_total |
| 调度失败率 | 调度失败的 Pod 占总调度 Pod 的比例 | < 1% | scheduler_pod_scheduling_attempts |
| Filter 耗时 | Filter 阶段的总执行时间 | < 50ms | scheduler_framework_extension_point_duration_seconds |
| Score 耗时 | Score 阶段的总执行时间 | < 30ms | scheduler_framework_extension_point_duration_seconds |
性能调优建议:当集群规模超过 1000 Node 时,建议启用 调度器性能分析(pprof),定位 Filter 和 Score 阶段的瓶颈插件。对于大规模集群,可考虑使用 Descheduler 进行二次调度优化。