Kubernetes v1.35:引入工作负载感知调度
调度大型工作负载比调度单个 Pod 更复杂、也更脆弱, 因为它通常需要把所有 Pod 作为整体来考虑,而不是逐个独立调度。 例如,在调度一个机器学习批处理任务时, 你往往需要有策略地放置每个 worker(例如放在同一个机架上), 才能让整体执行效率更高。 同时,这类工作负载中的 Pod 在调度视角下往往非常相似, 这从根本上改变了调度过程应有的形态。
虽然已经有很多定制调度器可以高效处理工作负载调度,
但考虑到工作负载调度对 Kubernetes 用户的普遍性和重要性,
尤其是在 AI 时代用例快速增长的背景下,
现在正是让工作负载成为 kube-scheduler 一等公民、并提供原生支持的时候。
工作负载感知调度
Kubernetes 1.35 最近发布了首批工作负载感知调度能力改进。 这些改进属于一个更广泛的长期计划,目标是提升工作负载的调度与管理能力。 该计划将跨越多个 SIG 和多个发布周期, 逐步扩展系统能力,向其“北极星目标”推进: 在 Kubernetes 中实现无缝的工作负载调度与管理, 包括但不限于抢占和自动伸缩。
Kubernetes v1.35 引入了 Workload API,
你可以用它描述工作负载的目标形态以及面向调度的要求。
它还带来了 编组调度(Gang Scheduling) 的初始实现,
可指示 kube-scheduler 以 全有或全无(all-or-nothing) 方式调度编组 Pod。
最后,我们通过 机会式批处理(Opportunistic batching) 特性提升了相同 Pod(通常构成一个编组)的调度效率,
从而加速整个调度过程。
Workload API
新的 Workload API 资源属于 scheduling.k8s.io/v1alpha1
API 组。
该资源以结构化、机器可读的形式定义多 Pod 应用的调度需求。
像 Job 这类面向用户的工作负载定义“运行什么”,
而 Workload 资源定义“一组 Pod 应如何被调度”,
以及它们在整个生命周期内的放置如何被管理。
Workload 允许你定义一组 Pod,并对其应用调度策略。
下面是一个编组调度配置示例:
你可以定义一个名为 workers 的 podGroup,并应用 gang 策略,minCount 设置为 4。
apiVersion: scheduling.k8s.io/v1alpha1
kind: Workload
metadata:
name: training-job-workload
namespace: some-ns
spec:
podGroups:
- name: workers
policy:
gang:
# 仅当 4 个 Pod 能同时运行时,该编组才可调度
minCount: 4
创建 Pod 时,你可以通过新的 workloadRef 字段把它们关联到这个 Workload:
apiVersion: v1
kind: Pod
metadata:
name: worker-0
namespace: some-ns
spec:
workloadRef:
name: training-job-workload
podGroup: workers
...
编组调度如何工作
gang 策略会强制执行全有或全无放置。
没有编组调度时,一个 Job 可能只被部分调度,
占用资源却无法真正运行,从而导致资源浪费甚至潜在死锁。
当你创建属于某个编组调度 Pod 组的 Pod 时,
调度器的 GangScheduling 插件会按每个 Pod 组(或副本键)独立管理其生命周期:
当你创建 Pod(或由控制器代你创建)时, 调度器会先阻止它们被调度,直到:
- 被引用的 Workload 对象已创建;
- 被引用的 Pod 组在某个 Workload 中存在;
- 该组中待调度 Pod 数量满足你的
minCount。
当到达足够数量的 Pod 后,调度器会尝试放置它们。 但这些 Pod 不会立即绑定到节点,而是先在
Permit门控处等待。调度器会检查是否已为整个组(至少达到
minCount)找到有效分配。- 如果组有足够空间,门控打开,所有 Pod 绑定到节点。
- 如果在超时(默认 5 分钟)内仅有子集 Pod 调度成功, 调度器会拒绝该组中的所有 Pod。 它们会返回队列,释放已保留资源给其他工作负载。
需要说明的是,虽然这只是第一版实现, Kubernetes 项目已经明确计划在后续版本持续改进并扩展编组调度算法。 我们希望带来的收益包括: 针对整个编组的单周期调度阶段、工作负载级抢占等, 并持续向北极星目标推进。
Opportunistic batching
除了显式的编组调度,v1.35 还引入了机会式批处理。 这是一个 Beta 特性,可降低相同 Pod 的调度延迟。
与编组调度不同,这个特性不要求启用 Workload API, 也不需要用户显式选择加入。 它在调度器内部以“机会式”方式工作:识别调度要求相同的 Pod (例如容器镜像、资源请求、亲和性等)。 当调度器处理一个 Pod 时, 可以复用该 Pod 的可行性计算结果给队列中后续相同 Pod, 从而显著加速调度。
只要 Pod 满足相应条件,多数用户无需额外操作就能自动受益于这项优化。
限制条件
机会式批处理仅在特定条件下生效。
kube-scheduler 用于寻找放置位置的相关字段,必须在 Pod 之间保持一致。
此外,某些特性的使用会为这些 Pod 禁用批处理机制,以确保正确性。
请注意,你可能需要检查 kube-scheduler 配置,
确保它没有在你不知情的情况下为工作负载隐式禁用批处理。
关于限制条件的更多细节,请参考文档。
北极星愿景
该项目有着广泛目标:实现工作负载感知调度。 这些新 API 与调度增强只是第一步。 在近期,工作将重点攻关:
- 引入工作负载调度阶段
- 增强多节点 DRA 与拓扑感知调度支持
- 工作负载级抢占
- 增强调度与自动伸缩的集成
- 增强与外部工作负载调度器的交互
- 覆盖工作负载全生命周期的放置管理
- 多工作负载调度模拟
以及更多方向。上述重点的优先级和实现顺序可能会调整,敬请关注后续更新。
快速开始
要体验工作负载感知调度改进:
- Workload API:在
kube-apiserver和kube-scheduler上启用GenericWorkload特性门控,并确保启用scheduling.k8s.io/v1alpha1API 组。 - 编组调度:在
kube-scheduler上启用GangScheduling特性门控(要求 Workload API 已启用)。 - 机会式批处理:该 Beta 特性在 v1.35 默认启用。
如有需要,可在
kube-scheduler上通过OpportunisticBatching特性门控将其关闭。
我们鼓励你在测试集群中试用工作负载感知调度,并分享使用体验, 帮助塑造 Kubernetes 调度的未来。 你可以通过以下方式反馈:
- 在 Slack (#sig-scheduling) 联系我们。
- 在工作负载感知调度跟踪 issue 下评论。
- 在 Kubernetes 仓库提交新的 Issue。
了解更多
- 阅读以下 KEP: Workload API 与编组调度 和机会式批处理。
- 关注工作负载感知调度 issue 获取最新进展。