本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kubernetes 1.26:Pod 调度就绪性
Kubernetes 1.26 引入了一个新的 Pod 特性:调度门控(scheduling gates)。在 Kubernetes 中,调度门控是一些键(key),用来告诉调度器一个 Pod 何时准备好被调度。
它解决了什么问题?
当 Pod 被创建时,调度器将不断尝试为它寻找一个合适的节点。这个无限循环会一直持续,直到调度器为 Pod 找到一个节点,或者 Pod 被删除。
长时间处于不可调度状态的 Pod(例如,那些被某些外部事件阻塞的 Pod)会浪费调度周期。一个调度周期可能需要 ≅20 毫秒或更长时间,具体取决于 Pod 调度约束的复杂性。因此,在大规模场景下,这些被浪费的周期会显著影响调度器的性能。请参见下面“调度器”框中的箭头。
调度门控有助于解决这个问题。它允许声明新创建的 Pod 尚未准备好进行调度。当 Pod 上存在调度门控时,调度器会忽略该 Pod,从而节省不必要的调度尝试。如果你在集群中安装了 Cluster Autoscaler,这些 Pod 也会被其忽略。
清除门控是外部控制器的责任,这些控制器知道 Pod 何时应被考虑进行调度(例如,配额管理器)。
它是如何工作的?
调度门控的工作方式通常与 Finalizer 非常相似。spec.schedulingGates
字段非空的 Pod 将显示为 SchedulingGated
状态,并且其调度将被阻止。请注意,可以添加多个门控,但它们都应在 Pod 创建时添加(例如,你可以将它们作为规约的一部分或通过一个变更性质的 Webhook 来添加)。
NAME READY STATUS RESTARTS AGE
test-pod 0/1 SchedulingGated 0 10s
要清除门控,你需要更新 Pod,从其 schedulingGates
字段中移除所有项。门控不必一次性全部移除,但只有当所有门控都被移除后,调度器才会开始考虑调度该 Pod。
在底层,调度门控是作为 PreEnqueue 调度器插件实现的,这是一个新的调度器框架扩展点,在每个调度周期的开始时被调用。
使用场景
此功能实现的一个重要使用场景是动态配额管理。Kubernetes 支持ResourceQuota,但 API 服务器在你尝试创建 Pod 时强制执行配额。例如,如果一个新的 Pod 超过了 CPU 配额,它将被拒绝。API 服务器不会将 Pod 排队;因此,创建 Pod 的一方需要不断地尝试重新创建它。这要么意味着资源可用和 Pod 实际运行之间存在延迟,要么意味着由于不断的尝试而给 API 服务器和调度器带来负载。
调度门控允许外部配额管理器解决 ResourceQuota 的上述限制。具体来说,该管理器可以(使用一个变更性质的 Webhook)向集群中创建的所有 Pod 添加一个 example.com/quota-check
调度门控。当有配额启动 Pod 时,该管理器再移除该门控。
下一步是什么?
要使用此功能,必须在 API 服务器和调度器中启用 PodSchedulingReadiness
特性门控。我们非常欢迎你进行测试并告诉我们(SIG Scheduling)你的想法!
其他资源
- Kubernetes 文档中的Pod 调度就绪
- Kubernetes Enhancement Proposal