基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

kube-scheduler 的调度流程是怎样的

知识点图片

Kubernetes 的 kube-scheduler 是集群的默认调度器,它的核心职责是:为一个新创建的 Pod(尚未分配节点)在集群中寻找一个最合适的 Node。

整个调度流程可以概括为三个核心步骤:过滤 (Filtering) -> 打分 (Scoring) -> 绑定 (Binding)

以下是详细的调度流程解析:


1. 整体架构概览

现代的 kube-scheduler 基于 Scheduling Framework(调度框架) 构建。调度过程分为两个大的周期:

  1. 调度周期 (Scheduling Cycle):在内存中进行,为 Pod 选择节点。这是同步过程,一次只能处理一个 Pod。
  2. 绑定周期 (Binding Cycle):将 Pod 与节点绑定。这是异步过程。

2. 详细调度步骤

第一步:监听与入队 (Watch & Queue)

  • 监听 (Informer):Scheduler 通过 API Server 的 Watch 机制,持续监听 spec.nodeName 为空的 Pod。
  • 优先级队列 (Scheduling Queue)
    • 新发现的 Pod 会被放入内部的调度队列。
    • 队列会根据 Pod 的 PriorityClass(优先级)进行排序,高优先级的 Pod 先出队。
    • 队列分为:活动队列 (ActiveQ)、回退队列 (BackoffQ) 和不可调度队列 (UnschedulableQ)。

第二步:过滤阶段 (Filtering / Predicates) —— "哪些节点能用?"

Scheduler 从队列中取出一个 Pod,遍历集群中所有的 Node,排除掉不满足硬性条件的节点。如果某个节点不满足任何一个过滤条件,它就会被淘汰。

常见的过滤策略包括:

  • PodFitsResources:节点剩余的 CPU/内存是否满足 Pod 的 Request?
  • PodFitsHostPorts:Pod 请求的 HostPort 是否已被占用?
  • MatchNodeSelector:节点的标签是否匹配 Pod 的 nodeSelector
  • NoDiskConflict:Pod 请求的 Volume 是否与节点上已有的冲突?
  • TaintToleration:Pod 是否容忍(Tolerate)了节点上的污点(Taint)?
  • PodAffinity/AntiAffinity:是否满足 Pod 的亲和性/反亲和性规则?

结果:如果过滤后没有节点剩余,Pod 会进入 Pending 状态,并触发抢占 (Preemption) 逻辑(如果配置了高优先级)。如果有剩余节点,进入下一阶段。

第三步:打分阶段 (Scoring / Priorities) —— "哪个节点最好?"

Scheduler 对通过过滤的节点进行打分(通常是 0-100 分)。分数越高,表示该节点越适合放置该 Pod。

常见的打分策略包括:

  • ImageLocality:节点上是否已经存在 Pod 需要的镜像?(有镜像的节点分更高,因为启动快)。
  • LeastRequested:选择资源空闲率最高的节点(负载均衡)。
  • BalancedResourceAllocation:选择 CPU 和内存使用率最均衡的节点。
  • NodeAffinity:根据 NodeAffinity 的偏好(Preferred)规则打分。
  • TaintToleration:根据容忍度的匹配程度打分。

结果:计算出每个候选节点的总分。

第四步:选择 (Select)

  • Scheduler 选择得分最高的节点。
  • 如果最高分有多个节点,则从中随机选择一个(通常是 Round-Robin)。

第五步:绑定阶段 (Binding) —— "落实分配"

一旦选定节点,Scheduler 不会直接写数据库(etcd),而是分两步走:

  1. Assume (乐观绑定):Scheduler 先在自己的本地缓存中将 Pod 标记为“已绑定到该节点”。这样做是为了立刻开始调度队列中的下一个 Pod,提高吞吐量,而不需要等待 API Server 的慢速响应。
  2. Bind (实际绑定):Scheduler 异步向 API Server 发送绑定请求,更新 Pod 的 spec.nodeName 字段。
    • API Server 收到请求后,将结果写入 etcd。
    • 目标节点上的 Kubelet 监听到 Pod 被分配给自己,开始拉取镜像、启动容器。

3. 调度框架的扩展点 (Extension Points)

为了让用户能自定义调度逻辑,Kubernetes 将上述流程细化为多个扩展点(插件机制)。开发者可以编写插件挂载到这些点上:

  1. QueueSort:决定队列中 Pod 的排序方式。
  2. PreFilter:在过滤前预处理(如检查集群整体资源)。
  3. Filter:对应上述的过滤阶段。
  4. PostFilter核心用于抢占 (Preemption)。如果 Filter 阶段没找到节点,这里决定是否要驱逐低优先级的 Pod 来腾位置。
  5. PreScore:打分前的预处理。
  6. Score:对应上述的打分阶段。
  7. NormalizeScore:调整分数范围。
  8. Reserve:在内存中预留资源(对应 Assume)。
  9. Permit:允许、拒绝或等待(用于像 Gang Scheduling 这种需要一组 Pod 同时就绪的场景)。
  10. PreBind:绑定前的操作(如挂载网络卷)。
  11. Bind:执行绑定操作。
  12. PostBind:绑定后的通知。

总结

简单来说,kube-scheduler 的工作流就是:
排队 (Queue) -> 硬性筛选 (Filter) -> 软性打分 (Score) -> 乐观绑定 (Assume) -> 写入 API (Bind)

00:00
00:00