2. K8s 调度基础:调度器架构、调度流程、节点选择与绑定机制
Kubernetes 调度器(kube-scheduler)是控制平面中负责将 Pod 分配到合适 Node 的核心组件。理解其架构、流程与绑定机制,是后续进行调度策略调优与配置漂移审计的基础。本章从调度器内部架构出发,逐步拆解调度全生命周期。
2.1 调度器架构:组件与职责
kube-scheduler 采用插件化架构,通过一系列可配置的调度队列、调度框架(Scheduling Framework)与绑定回路完成 Pod 的调度决策。其核心组件如下:
| 组件 | 职责 | 关键特性 |
|---|---|---|
| 调度队列 | 管理待调度的 Pod,支持优先级排序与重试 | ActiveQ / BackoffQ / UnschedulableQ |
| 调度框架 | 定义扩展点(Extension Points),允许插件注入过滤、评分、绑定等逻辑 | PreFilter / Filter / PostFilter / Score / Reserve / Permit / PreBind / Bind / PostBind |
| 调度器缓存 | 维护集群 Node 与 Pod 的实时快照,减少 API Server 请求 | 增量更新、过期清理 |
| 绑定回路 | 将选定 Node 与 Pod 的绑定关系写入 API Server | 异步绑定、幂等性保证 |
架构要点: 调度框架的插件化设计使得调度策略可动态组合,Prometheus 可通过监控每个扩展点的执行耗时与错误率,精准定位调度性能瓶颈。
2.2 调度流程:从入队到绑定
一个 Pod 从创建到完成调度,经历以下核心阶段:
- 入队(Queue):Pod 进入 ActiveQ,按优先级排序;若调度失败则进入 BackoffQ 或 UnschedulableQ。
- PreFilter:执行 Pod 级别的预处理检查(如 Pod 拓扑分布约束、卷冲突检测)。
- Filter:遍历所有 Node,执行过滤插件(如节点资源不足、端口冲突、污点容忍)。
- PostFilter:若无可调度 Node,执行抢占逻辑或标记为不可调度。
- Score:对通过过滤的 Node 进行评分,选择最高分 Node。
- Reserve:在缓存中预留资源,防止并发调度冲突。
- Permit:等待外部准入许可(如动态资源调度)。
- PreBind / Bind:执行绑定前预处理(如 CSI 卷挂载),然后写入绑定关系。
- PostBind:绑定完成后的清理与通知。
审计关注点: 每个扩展点均可通过 Prometheus Histogram 指标(如
scheduler_framework_extension_point_duration_seconds)监控耗时分布。若 Filter 阶段耗时异常,通常意味着节点资源检查插件存在性能瓶颈。
2.3 节点选择与绑定机制
节点选择是调度流程的核心输出,绑定机制则确保选择结果持久化。两者协同工作,形成调度决策的闭环。
2.3.1 节点选择:过滤 + 评分
节点选择分为两个阶段:
- 过滤阶段(Filter):硬性约束检查,不满足条件的 Node 被直接排除。常见过滤插件包括:
NodeResourcesFit:检查 CPU、内存是否满足 Pod 请求。NodePorts:检查端口是否冲突。NodeAffinity:检查节点亲和性规则。TaintToleration:检查污点容忍。
- 评分阶段(Score):对通过过滤的 Node 进行打分,选择最高分节点。常见评分插件包括:
NodeResourcesBalancedAllocation:优先选择资源分配均衡的节点。ImageLocality:优先选择已缓存所需镜像的节点。InterPodAffinity:优先满足 Pod 间亲和/反亲和规则。
漂移风险: 若集群中多个调度器实例使用不同的评分权重配置,同一 Pod 可能被分配到不同 Node,导致调度结果不一致。Prometheus 可通过
scheduler_pod_scheduling_attempts 和 scheduler_pod_scheduling_duration_seconds 监控调度一致性。
2.3.2 绑定机制:从选择到持久化
绑定机制确保调度决策被可靠写入 API Server,并触发 kubelet 执行 Pod 启动。其核心流程如下:
| 步骤 | 操作 | 失败处理 |
|---|---|---|
| PreBind | 执行绑定前预处理(如 CSI 卷挂载、网络配置) | 回滚 Reserve 状态,重新入队 |
| Bind | 通过 API Server 创建 Pod 与 Node 的绑定关系(Binding 对象) |
重试或回滚 |
| PostBind | 清理临时资源,通知其他组件 | 仅记录日志,不阻塞 |
绑定操作的伪代码如下:
// 绑定流程简化示例
func (s *Scheduler) bind(ctx context.Context, pod *v1.Pod, node string) error {
// 1. PreBind 扩展点
if err := s.runPreBindPlugins(ctx, pod, node); err != nil {
s.runReservePluginsUnreserve(ctx, pod, node)
return err
}
// 2. 执行绑定
binding := &v1.Binding{
ObjectMeta: metav1.ObjectMeta{Name: pod.Name, Namespace: pod.Namespace},
Target: v1.ObjectReference{Kind: "Node", Name: node},
}
if err := s.client.CoreV1().Pods(pod.Namespace).Bind(ctx, binding, metav1.CreateOptions{}); err != nil {
s.runPreBindPluginsUnreserve(ctx, pod, node)
return err
}
// 3. PostBind 扩展点
s.runPostBindPlugins(ctx, pod, node)
return nil
}
审计指标: 绑定阶段耗时可通过
scheduler_binding_duration_seconds 监控。若绑定耗时突增,通常与 API Server 负载或 PreBind 插件(如 CSI 卷挂载)延迟相关。
2.4 调度器配置与可观测性
调度器配置通过 KubeSchedulerConfiguration 对象管理,支持动态调整插件启用/禁用、评分权重、队列策略等。Prometheus 提供的调度相关指标包括:
| 指标名称 | 类型 | 说明 |
|---|---|---|
scheduler_queue_incoming_pods_total |
Counter | 入队 Pod 总数 |
scheduler_pod_scheduling_attempts |
Histogram | Pod 调度尝试次数分布 |
scheduler_framework_extension_point_duration_seconds |
Histogram | 各扩展点耗时分布 |
scheduler_binding_duration_seconds |
Histogram | 绑定阶段耗时分布 |
scheduler_volume_scheduling_duration_seconds |
Histogram | 卷调度耗时分布 |
调优建议: 通过 Prometheus 监控
scheduler_framework_extension_point_duration_seconds 的 P99 值,若 Filter 阶段超过 100ms,建议检查节点资源检查插件是否过多或节点数量过大。可考虑启用 NodeResourcesFit 的 LeastAllocated 策略以平衡负载。