Kubernetes v1.19 [稳定]调度框架(Scheduling Framework)是 Kubernetes 调度器的一种插件化架构。它由一组直接编译到调度器中的“插件”API 组成。这些 API 允许将大多数调度功能实现为插件,同时保持调度“核心”的轻量化和可维护性。有关框架设计的更多技术信息,请参阅调度框架设计提案。
调度框架定义了几个扩展点。调度器插件会注册并在一个或多个扩展点被调用。其中一些插件可以改变调度决策,而另一些则仅供参考。
调度 Pod 的每个尝试都分为两个阶段:调度周期(Scheduling Cycle)和绑定周期(Binding Cycle)。
调度周期为 Pod 选择一个节点,而绑定周期将该决策应用于集群。调度周期和绑定周期统称为“调度上下文(Scheduling Context)”。
调度周期串行运行,而绑定周期可以并行运行。
如果确定 Pod 无法调度或发生内部错误,调度或绑定周期可能会中止。此时 Pod 将被放回队列并重试。
下图显示了 Pod 的调度上下文以及调度框架暴露的接口。
一个插件可以实现多个接口,以执行更复杂或有状态的任务。
一些接口对应于调度器扩展点,这些扩展点可以通过调度器配置进行设置。

这些插件在将 Pod 添加到内部活动队列(Pod 被标记为准备好调度的地方)之前被调用。
只有当所有 PreEnqueue 插件都返回 Success 时,Pod 才能进入活动队列。否则,它会被放入内部的不可调度 Pod 列表,且不会获得 Unschedulable 条件。
有关内部调度器队列工作原理的更多详情,请阅读 kube-scheduler 中的调度队列。
EnqueueExtension 是一个插件接口,它允许插件根据集群中的变化,控制是否重试调度被该插件拒绝的 Pod。实现 PreEnqueue、PreFilter、Filter、Reserve 或 Permit 的插件应实现此接口。
Kubernetes v1.34 [稳定](默认开启)QueueingHint 是一个回调函数,用于决定是否可以将 Pod 重新排队到活动队列或退避队列。每当集群中发生某种类型的事件或变化时,它就会执行。当 QueueingHint 发现事件可能使 Pod 变得可调度时,Pod 会被放入活动队列或退避队列,以便调度器重试调度该 Pod。
这些插件用于对调度队列中的 Pod 进行排序。队列排序插件本质上提供了一个 Less(Pod1, Pod2) 函数。一次只能启用一个队列排序插件。
这些插件用于预处理有关 Pod 的信息,或检查集群或 Pod 必须满足的特定条件。如果 PreFilter 插件返回错误,则调度周期将中止。
这些插件用于过滤掉无法运行 Pod 的节点。对于每个节点,调度器将按配置顺序调用过滤插件。如果任何过滤插件将节点标记为不可行,则不会为该节点调用剩余的插件。节点可以并发评估。
这些插件在 Filter 阶段之后调用,但仅当未找到可行节点时。插件按配置顺序调用。如果任何 PostFilter 插件将节点标记为 Schedulable,则不会调用剩余的插件。PostFilter 的典型实现是抢占(Preemption),即通过抢占其他 Pod 来尝试使当前 Pod 可调度。
这些插件用于执行“预评分(Pre-score)”工作,为 Score 插件生成可共享的状态。如果 PreScore 插件返回错误,调度周期将中止。
这些插件用于对已通过过滤阶段的节点进行排名。调度器将为每个节点调用每个评分插件。将存在一个定义明确的整数范围,代表最低分和最高分。在 NormalizeScore 阶段之后,调度器将根据配置的插件权重合并来自所有插件的节点分数。
Kubernetes v1.33 [alpha](默认禁用)特性门控 VolumeCapacityPriority 在 v1.32 中用于支持静态配置的存储。从 v1.33 开始,新的特性门控 StorageCapacityScoring 替换了旧的 VolumeCapacityPriority,并增加了对动态配置存储的支持。启用 StorageCapacityScoring 后,kube-scheduler 中的 VolumeBinding 插件将扩展,根据每个节点的存储容量对节点进行评分。此特性适用于支持存储容量的 CSI 卷,包括由 CSI 驱动程序支持的本地存储。
这些插件用于在调度器计算节点的最终排名之前修改分数。注册此扩展点的插件将使用同一插件的 Score 结果进行调用。每个调度周期中每个插件调用一次。
例如,假设一个插件 BlinkingLightScorer 根据节点拥有多少闪烁灯来对它们进行排名。
func ScoreNode(_ *v1.pod, n *v1.Node) (int, error) {
return getBlinkingLightCount(n)
}
然而,闪烁灯的最大数量可能远小于 NodeScoreMax。为了解决这个问题,BlinkingLightScorer 还应该注册到此扩展点。
func NormalizeScores(scores map[string]int) {
highest := 0
for _, score := range scores {
highest = max(highest, score)
}
for node, score := range scores {
scores[node] = score*NodeScoreMax/highest
}
}
如果任何 NormalizeScore 插件返回错误,调度周期将中止。
实现 Reserve 接口的插件有两个方法,即 Reserve 和 Unreserve,它们分别支持称为 Reserve 和 Unreserve 的两个信息性调度阶段。维护运行时状态(也称为“有状态插件”)的插件应使用这些阶段,以便在调度器为给定 Pod 预留或取消预留节点资源时收到通知。
Reserve 阶段发生在调度器实际将 Pod 绑定到其指定节点之前。它旨在防止在调度器等待绑定成功时发生竞态条件。每个 Reserve 插件的 Reserve 方法可能会成功或失败;如果某个 Reserve 方法调用失败,则不会执行后续插件,并且 Reserve 阶段被视为失败。如果所有插件的 Reserve 方法都成功,则 Reserve 阶段被视为成功,并执行调度周期和绑定周期的剩余部分。
如果 Reserve 阶段或后续阶段失败,则会触发 Unreserve 阶段。发生这种情况时,所有 Reserve 插件的 Unreserve 方法将按 Reserve 方法调用的相反顺序执行。此阶段旨在清理与预留的 Pod 关联的状态。
Unreserve 方法的实现必须是幂等的,且不得失败。Permit 插件在每个 Pod 的调度周期结束时被调用,以阻止或延迟绑定到候选节点。Permit 插件可以执行以下三项操作之一:
批准
一旦所有 Permit 插件批准了一个 Pod,该 Pod 就会被发送进行绑定。
拒绝 (deny)
如果任何 Permit 插件拒绝 Pod,则将其返回到调度队列。这将触发 Reserve 插件中的 Unreserve 阶段。
等待 (wait)(带有超时)
如果 Permit 插件返回“wait”,则 Pod 将保留在内部的“等待”Pod 列表中,该 Pod 的绑定周期开始但会直接阻塞,直到获得批准。如果发生超时,wait 将变为 deny,并且 Pod 将被返回到调度队列,触发 Reserve 插件中的 Unreserve 阶段。
FrameworkHandle),但我们期望仅由 permit 插件批准处于“等待”状态的已预留 Pod 的绑定。一旦 Pod 获得批准,它就会进入 PreBind 阶段。这些插件用于执行在 Pod 绑定之前所需的任何工作。例如,PreBind 插件可以在允许 Pod 在目标节点上运行之前配置网络卷并将其挂载到目标节点上。
如果任何 PreBind 插件返回错误,Pod 将被拒绝并返回到调度队列。
这些插件用于将 Pod 绑定到节点。在所有 PreBind 插件完成之前,不会调用 Bind 插件。每个 bind 插件按配置顺序调用。绑定插件可以选择是否处理给定的 Pod。如果绑定插件选择处理 Pod,则跳过剩余的绑定插件。
这是一个信息性接口。Post-bind 插件在 Pod 成功绑定后被调用。这是绑定周期的结束,可用于清理关联的资源。
插件 API 分为两个步骤。首先,插件必须注册并进行配置,然后使用扩展点接口。扩展点接口具有以下形式。
type Plugin interface {
Name() string
}
type QueueSortPlugin interface {
Plugin
Less(*v1.pod, *v1.pod) bool
}
type PreFilterPlugin interface {
Plugin
PreFilter(context.Context, *framework.CycleState, *v1.pod) error
}
// ...
您可以在调度器配置中启用或禁用插件。如果您使用的是 Kubernetes v1.18 或更高版本,大多数调度插件都在使用中并默认启用。
除了默认插件之外,您还可以实现自己的调度插件,并将它们与默认插件一起配置。您可以访问 scheduler-plugins 了解更多详情。
如果您使用的是 Kubernetes v1.18 或更高版本,则可以将一组插件配置为调度器配置文件(Profile),并定义多个配置文件以适应各种类型的工作负载。在多个配置文件中了解更多信息。