第1章:Kubernetes调度器原理

调度器这东西,说白了就是Kubernetes集群里的「包工头」。

你提交一个Pod,它得决定把这活儿派给哪台机器干。我刚开始接触K8s时,总觉得调度就是个简单的资源匹配——哪个节点空闲就扔过去呗。后来线上一次Pod调度失败,排查了半天才发现是调度队列的优先级搞反了。嗯,从那以后,我老老实实把调度器原理啃了一遍。

1.1 默认调度器:kube-scheduler

Kubernetes默认的调度器叫kube-scheduler,它是个独立运行的组件。

我个人习惯把它理解成一个「过滤器+打分器」的组合体。先过滤掉不满足条件的节点,再给剩下的节点打分,最后选个分数最高的。

核心职责:

  • 监听新创建的Pod(未被调度到节点的)
  • 为Pod选择合适的Node
  • 将调度结果写入etcd

你想想看,如果集群里有1000个节点,每个节点都要跑一遍过滤和打分逻辑,性能怎么办?

默认调度器用了缓存机制,把节点信息缓存在本地。我在项目中遇到过,节点状态更新不及时导致调度到已满的节点,后来加了informer的重新同步周期才解决。

1.2 调度队列:Pod的候车室

调度队列,就是Pod等待被调度的「候车室」。

K8s把Pod分成三个队列:

队列名称 作用 优先级
activeQ 活跃队列,存放待调度的Pod 高
backoffQ 退避队列,调度失败的Pod先放这里 中
unschedulableQ 不可调度队列,资源不足的Pod放这里 低

为什么会设计三个队列?

我记得有一次线上Pod调度失败,直接丢回activeQ重试,结果频繁重试把API Server打爆了。后来K8s社区引入了backoff机制,失败后先退避一段时间再重试,这才稳定下来。

避坑指南:

我曾经遇到过Pod一直卡在unschedulableQ里出不来。原因是节点资源释放后,没有触发重新入队。后来加了定时器,每隔一段时间强制把unschedulableQ的Pod挪回activeQ重新调度。

1.3 调度周期:过滤与打分

调度周期分为两个阶段:过滤阶段和打分阶段。

过滤阶段(Predicates):

  • 检查节点资源是否满足Pod需求(CPU、内存、GPU等)
  • 检查节点端口是否冲突
  • 检查节点标签是否匹配Pod的nodeSelector
  • 检查Pod的亲和性/反亲和性规则

打分阶段(Priorities):

  • 资源利用率均衡(LeastRequestedPriority)
  • 节点亲和性匹配(NodeAffinityPriority)
  • Pod间亲和性(InterPodAffinityPriority)

我习惯把过滤阶段叫「一票否决制」——只要有一个条件不满足,这个节点就直接出局。打分阶段则是「优中选优」,每个节点拿个分数,最高分中标。

注意:

过滤阶段的顺序很重要。默认调度器会把计算量小的过滤器放在前面,比如检查节点端口冲突比检查Pod亲和性快得多。我曾经优化过调度性能,把过滤器的执行顺序调整了一下,调度吞吐量提升了15%。

1.4 绑定过程:从决策到落地

调度器选好节点后,需要把结果写回集群。这个过程叫绑定。

绑定分三步:

  1. 预绑定:调度器在本地缓存中标记Pod已被调度
  2. 绑定:调度器调用API Server,将Pod的NodeName字段设置为选中的节点
  3. 后绑定:触发一些扩展逻辑,比如存储卷的挂载

你想想看,如果绑定过程中API Server挂了怎么办?

调度器会重试绑定操作。我遇到过绑定超时的情况,调度器重试了3次才成功。如果一直失败,Pod会重新进入调度队列,等待下一次调度机会。

核心流程总结:

Pod创建 → 进入activeQ → 出队 → 过滤节点 → 打分排序 → 绑定节点 → 完成调度

1.5 调度器架构图

下面这张图展示了调度器的核心工作流程,我画了张SVG方便你理解:

Pod创建 调度队列 activeQ / backoffQ / unschedulableQ 过滤阶段 资源检查 端口冲突检查 亲和性检查 打分阶段 资源均衡打分 亲和性打分 综合评分 绑定节点 目标节点 失败重试 Kubernetes调度器核心流程

这张图把调度器的核心流程串起来了。从Pod创建开始,经过队列排队、过滤、打分,最后绑定到节点。如果绑定失败,Pod会重新进入队列等待下一次调度。

个人经验:

我建议你在排查调度问题时,先看Pod在哪个队列里。如果在unschedulableQ,多半是资源不足;如果在backoffQ,可能是调度失败后的退避;如果在activeQ但一直没调度,那可能是调度器本身出了问题。

调度器原理这部分,说白了就是理解「怎么选、选谁、怎么绑」这三个问题。搞清楚了,后面自定义调度器、配置调度策略就顺理成章了。

想要更多资料,联系可可