15 庖丁解牛:kube-scheduler

最近更新:2026-06-21
来源:技术书栈原文。本页按授权迁移至 GoClub。

整体概览

在第 3 节《宏观认识:整体架构》 中,我们也认识到了 Scheduler 的存在,知道了 Master 是 K8S 是集群的大脑,Controller Manager 负责将集群调整至预期的状态,而 Scheduler 则是集群调度器,将预期的 Pod 资源调度到正确的 Node 节点上,进而令该 Pod 可完成启动。本节我们一同来看看它如何发挥如此大的作用。

下文统一使用 kube-scheduler 进行表述

kube-scheduler 是什么

引用官方文档一句话:

kube-scheduler 是一个策略丰富,拓扑感知的调度程序,会显著影响可用性,性能和容量。

我们知道资源调度本就是 K8S 这类系统中的一个很复杂的事情,既要能满足系统对资源利用率的需要,同样还需要避免资源竞争,比如说端口冲突之类的。

为了能完成这样的需求,kube-scheduler 便在不断的迭代和发展,通过支持多种策略满足各类需求,通过感知拓扑避免资源竞争和保障系统的可用性及容量等。

我们在第 5 节下载服务端二进制文件解压后,便可看到 kube-scheduler 的可执行文件。当给它传递 –help 查看其支持参数的时候,便可以看到它支持使用 –address 或者 –bind-address 等参数指定所启动的 HTTP server 所绑定的地址之类的。

它和 kube-controller-manager 有点类似,同样是通过定时的向 kube-apiserver 请求获取信息,并进行处理。而他们所起到的作用并不相同。

kube-scheduler 有什么作用

从上层的角度来看,kube-scheduler 的作用就是将待调度的 Pod 调度至最佳的 Node 上,而这个过程中则需要根据不同的策略,考虑到 Node 的资源使用情况,比如端口,内存,存储等。

kube-scheduler 是如何工作的

整体的过程可通过 pkg/scheduler/core/generic_scheduler.go 的代码来看

它的输入有两个:

  • pod:待调度的 Pod 对象;
  • nodeLister:所有可用的 Node 列表

备注:nodeLister 的实现稍微用了点技巧,返回的是 []*v1.Node 而不是 v1.NodeList 可避免拷贝带来的性能损失。

处理阶段

kube-scheduler 将处理阶段主要分为三个阶段 Computing predicates,Prioritizing和 Selecting host:

  • Computing predicates:主要解决的问题是 Pod 能否调度到集群的 Node 上;

主要是通过一个名为 podFitsOnNode 的函数进行实现,在检查的过程中也会先去检查下是否已经有已缓存的判断结果, 当然也会检查 Pod 是否是可调度的,以防有 Pod Affinity (亲合性) 之类的存在。

  • Prioritizing:主要解决的问题是在上个阶段通过 findNodesThatFit 得到了 filteredNodes 的基础之上解决哪些 Node 是最优的,得到一个优先级列表 priorityList;

至于优先级的部分,主要是通过下面的代码:

给每个经过第一步筛选出来的 Node 一个 Score,再按照各种条件进行打分,最终得到一个优先级列表。

  • Selecting host:则是最终选择 Node 调度到哪台机器上。

最后,则是通过 selectHost 选择出最终要调度到哪台机器上。

总结

在本节中,我们介绍了 kube-scheduler 以及它在调度 Pod 的过程中的大致步骤。

不过它实际使用的各种策略及判断条件很多,无法在一节中完全都详细介绍,感兴趣的朋友可以按照本节中提供的思路大致去看看它的实现。

我们通过前面几节的介绍,已经知道了当实际进行部署操作的时候,首先会通过 kubectl 之类的客户端工具与 kube-apiserver 进行交互,在经过一系列的处理后,数据将持久化到 etcd 中;

此时,kube-controller-manager 通过持续的观察,开始按照我们的配置,将集群的状态调整至预期状态;

而 kube-scheduler 也在发挥作用,决定 Pod 应该调度至哪个或者哪些 Node 上;之后则通过其他组件的协作,最总将该 Pod 在相应的 Node 上部署启动。

我们在下节将要介绍的 kubelet 便是后面这部分“实际部署动作”相关的组件中尤为重要的一个,下节我们再详细介绍它是如何完成这些功能的。