1. Kubernetes 调度基础:调度器架构、调度流程、调度器组件详解
Kubernetes 调度器(kube-scheduler)是控制平面中负责将 Pod 绑定到合适 Node 的核心组件。它不负责创建 Pod,也不负责运行容器,而是通过一系列算法和策略,为每个待调度的 Pod 选择最匹配的工作节点。理解调度器的内部架构和完整流程,是后续学习资源模型驱动调度优化的前提。
1.1 调度器整体架构
Kubernetes 默认调度器采用插件化架构设计,核心调度框架(Scheduling Framework)定义了一组扩展点(Extension Points),调度插件可以注册到这些扩展点上,实现自定义的调度逻辑。调度器内部主要分为三个逻辑层:
- 调度队列层:管理待调度的 Pod,支持优先级排序、重试、回退等机制。
- 调度框架层:执行调度周期(Scheduling Cycle)和绑定周期(Binding Cycle),通过扩展点调用插件。
- 缓存与存储层:维护集群节点和 Pod 的快照信息,减少对 API Server 的直接访问。
关键设计原则:调度器通过 informer 机制监听 Pod 和 Node 的变化,将待调度 Pod 放入队列,然后循环从队列中取出 Pod 执行调度决策。调度结果通过 API Server 写入 Pod 的
spec.nodeName 字段。
1.2 调度流程详解
调度器处理一个 Pod 的完整生命周期分为两个主要阶段:调度周期和绑定周期。调度周期为 Pod 选择一个合适的节点;绑定周期将调度结果持久化到 API Server,并触发 kubelet 执行容器创建。
1.2.1 调度周期(Scheduling Cycle)
调度周期是同步执行的,包含以下步骤:
| 步骤 | 扩展点 | 说明 |
|---|---|---|
| 1. 排序 | QueueSort | 对调度队列中的 Pod 按优先级排序,高优先级 Pod 优先出队 |
| 2. 预过滤 | PreFilter | 预处理 Pod 信息,例如检查 Pod 的拓扑分布约束、卷挂载需求 |
| 3. 过滤 | Filter | 遍历所有节点,剔除不满足 Pod 调度条件的节点(如资源不足、端口冲突、污点容忍) |
| 4. 后过滤 | PostFilter | 当过滤后无可用节点时,执行抢占逻辑或返回失败 |
| 5. 预评分 | PreScore | 生成评分所需的上下文信息,例如节点亲和性评分数据 |
| 6. 评分 | Score | 对过滤后的节点进行打分,分数越高表示越适合运行该 Pod |
| 7. 归一化 | NormalizeScore | 将各插件的评分结果归一化到统一范围(默认 0-100) |
| 8. 保留 | Reserve | 在缓存中预留 Pod 在选定节点上的资源,防止并发调度冲突 |
性能提示:过滤阶段是调度性能的关键瓶颈。当集群规模较大时(数千节点),过滤插件的执行效率直接影响调度吞吐量。生产环境中建议启用
NodeResourcesFit、NodeName、NodeUnschedulable 等轻量级过滤插件,避免使用过于复杂的自定义过滤逻辑。
1.2.2 绑定周期(Binding Cycle)
绑定周期是异步执行的,包含以下步骤:
| 步骤 | 扩展点 | 说明 |
|---|---|---|
| 1. 许可 | Permit | 允许或拒绝绑定操作,支持等待/超时机制(常用于多调度器协调) |
| 2. 预绑定 | PreBind | 执行绑定前的准备工作,例如动态创建存储卷、配置网络策略 |
| 3. 绑定 | Bind | 将 Pod 的 spec.nodeName 更新为选定节点名称,持久化到 API Server |
| 4. 后绑定 | PostBind | 绑定成功后的清理或通知操作(如更新调度指标、释放临时资源) |
1.3 调度器核心组件详解
调度器的实现由多个内部组件协作完成,每个组件承担特定的职责:
| 组件名称 | 职责 | 关键数据结构/行为 |
|---|---|---|
| Scheduler | 调度器主入口,协调调度循环 | 维护 schedulingQueue、schedulerCache、framework 引用 |
| SchedulingQueue | 管理待调度 Pod 的优先级队列 | 支持 Add、Pop、AddUnschedulableIfNotPresent 操作 |
| SchedulerCache | 缓存集群节点和 Pod 的快照 | 使用 NodeInfo 存储节点资源、Pod 列表、卷信息 |
| Framework | 调度框架,管理插件注册与调用 | 维护 FilterPlugins、ScorePlugins、BindPlugins 等插件列表 |
| Plugin | 实现具体调度策略的插件单元 | 每个插件实现一个或多个扩展点接口(如 FilterPlugin、ScorePlugin) |
| Extender | 外部调度扩展器(已逐步被插件取代) | 通过 HTTP/gRPC 调用外部服务进行过滤或评分 |
1.4 调度器工作流程总结
调度器的工作可以概括为以下循环:
- 监听事件:通过 Informer 监听 Pod 和 Node 的创建、更新、删除事件。
- 入队:将新创建的、未指定
nodeName的 Pod 加入调度队列。 - 出队:从队列中取出优先级最高的 Pod,开始调度周期。
- 过滤:调用所有 Filter 插件,筛选出满足条件的节点列表。
- 评分:调用所有 Score 插件,对过滤后的节点进行打分排序。
- 选择:选择得分最高的节点作为目标节点(若多个节点同分,随机选择)。
- 预留:在缓存中为该 Pod 预留资源,防止并发冲突。
- 绑定:异步执行绑定周期,将 Pod 绑定到目标节点。
- 反馈:绑定成功则更新缓存;失败则回滚预留,将 Pod 重新入队等待下次调度。
常见陷阱:调度器默认使用 先到先服务 策略,但结合优先级(PriorityClass)可以实现抢占式调度。如果集群中大量 Pod 处于
Pending 状态,首先检查调度器日志和 kubectl describe pod 中的 Events 字段,定位是过滤失败还是评分异常。不要盲目增加节点资源,优先分析调度策略是否合理。
1.5 调度器配置与扩展
Kubernetes 调度器支持通过 KubeSchedulerConfiguration 进行配置,用户可以:
- 启用/禁用默认插件:例如禁用
NodeResourcesFit或启用NodeResourcesBalancedAllocation。 - 配置插件权重:调整 Score 插件的评分权重,影响最终节点选择。
- 注册自定义插件:通过
multiPoint或指定扩展点注入自定义调度逻辑。 - 设置调度策略:使用
Policy模式(已弃用)或Profile模式(推荐)定义多套调度配置。
以下是一个简单的调度器配置示例,展示如何调整默认插件的权重:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
plugins:
score:
disabled:
- name: NodeResourcesFit
enabled:
- name: NodeResourcesBalancedAllocation
weight: 2
- name: ImageLocality
weight: 1
pluginConfig:
- name: NodeResourcesBalancedAllocation
args:
resources:
- name: cpu
weight: 1
- name: memory
weight: 1
最佳实践:在生产环境中,建议保留默认的
NodeResourcesFit 和 NodeName 过滤插件,确保基本的资源匹配和节点选择正确性。评分插件可以根据业务场景调整:CPU 密集型应用提高 NodeResourcesBalancedAllocation 权重;IO 密集型应用启用 ImageLocality 减少镜像拉取时间。
通过本章的学习,你已经掌握了 Kubernetes 调度器的核心架构、完整调度流程以及各组件的职责。这些基础知识是后续深入理解资源模型、拓扑感知调度和性能优化的基石。