系统设计面试题:Kubernetes PodGroup 如何实现 gang scheduling?
题干
Kubernetes v1.35 引入了 alpha 的 Scheduling Group 能力。请设计一个批处理平台:一组相互依赖的 worker 只有在至少 minCount 个 Pod 都能同时放置时才启动。说明 PodGroup、调度器、控制器、自动扩缩容与故障处理如何协作,并解释如何避免部分启动造成死锁。回答时要标明 alpha 能力的版本与 feature gate 前提。
面试官在考察什么
重点是把“单 Pod 可调度”提升为“组级可行性”,并保持 API、调度和运行时状态的一致。面试官会观察你是否区分 basic 与 gang、是否处理 PodGroup 尚未创建、资源不足、成员失败、抢占和观测闭环。只复述字段名称而没有状态机、超时和降级策略,无法证明系统设计能力。
先澄清这几个问题
- worker 必须全部同时启动,还是满足一个可用下限即可?这决定选择
gang以及minCount。 - 成员是一次性 Job 还是长时间运行的服务?两者的重试、回收和优先级不同。
- 组内 Pod 是否跨命名空间、跨集群或需要 GPU、拓扑约束?官方 Scheduling Group 引用同命名空间的 PodGroup。
- 资源等待多久算失败?是否允许排队、借用低优先级资源或转为非 gang 模式?
30 秒框架
先给边界:v1.35 的 schedulingGroup 和 PodGroup policy 为 alpha,默认关闭,需要 GenericWorkload feature gate,不能直接当作稳定生产 API。然后分四层回答:API 契约(Workload、PodGroup、Pod 引用)、组级调度(basic/gang 与 minCount)、生命周期(提交、等待、绑定、失败、重试)、运营护栏(容量、优先级、指标、审计和回滚)。
逐步拆解方案
1. 建模与不变量
Workload 控制器为一次运行创建唯一 PodGroup,并记录期望成员数、策略、版本和租户。每个 Pod 在创建时通过 spec.schedulingGroup.podGroupName 指向同命名空间的 PodGroup;该字段不可变,因此变更组要新建一组对象。核心不变量是:gang 组未达到 minCount 前,成员不能绑定到节点。
2. 选择策略
basic 适合只想聚合观测、成员可独立运行的工作;Pod 仍按普通规则分别调度。gang 适合紧耦合训练或批处理,调度器只在至少 minCount 个成员同时可行时接受这一组。把 minCount 设为小于实际成员数,可以允许部分弹性;把它设为成员总数,则实现全员同时放置。
3. 提交与等待状态机
控制器先写 PodGroup,再写 Pod,避免 Pod 先出现而长期找不到引用。若 PodGroup 尚不存在,Pod 会保持 Pending;调度器在对象创建后重新考虑。状态至少包括 PendingGroup、WaitingCapacity、Feasible、Bound、Running、Failed 和 Cancelled,每次转移都带 generation、原因和时间戳。
4. 调度与资源协调
调度器先按过滤、拓扑、设备和优先级计算成员的候选节点,再执行组级可行性判断。只有候选数量达到 minCount 才允许绑定;绑定应可重试且具幂等性。容量不足时,自动扩缩容器读取带组标识的 Pending 原因,扩容满足整组的资源画像,而不是只为第一个 Pod 加一个节点。
5. 抢占、超时与公平
为组设置统一 priority 与 queue weight,防止单个成员抢占后留下不可运行的半组。若等待超过 deadline,控制器取消整组并释放已绑定资源;重试生成新 generation,避免旧成员误加入。跨租户配额、最大组大小和队列老化策略要限制 gang 组长期占满集群。
6. 成员失败与回滚
运行中成员崩溃时,不应把“曾经达到门槛”误当成当前可用。根据作业语义选择重启单成员或终止整组;训练作业通常由 checkpoint 恢复并重建新组。删除 Workload 时按 owner 引用清理 PodGroup 与 Pod,保留终态事件用于审计。
7. 可观测性与安全边界
暴露组级队列等待时长、可行成员数、minCount、扩容次数、抢占次数和失败原因;日志包含 group UID 与 generation。Admission webhook 校验命名空间、配额、最小/最大成员数和 feature gate 状态。alpha API 必须有显式开关、兼容性测试和快速回滚路径。
一份合格回答示例
“我会用 Workload 控制器创建同命名空间 PodGroup,策略设为 gang,minCount 取可并行运行所需的最小 worker 数。Pod 通过不可变的 schedulingGroup 引用它。控制器先创建组再创建 Pod;缺少组时成员保持 Pending。调度器为所有成员计算候选节点,只有同时满足资源、拓扑和优先级且可行数达到 minCount 才绑定。自动扩缩容按整组资源画像扩容,超时则取消整组并释放资源。成员失败时按作业语义重建 generation,训练作业从 checkpoint 恢复。我们记录组级等待、可行数和失败原因,并把 v1.35 alpha 与 GenericWorkload feature gate 写入发布清单,生产默认关闭,先在隔离集群验证。”
常见失分点
- 把
basic当作 all-or-nothing,忽略它允许成员独立调度。 - 只设置 Pod 标签,没有说明 PodGroup 引用、同命名空间和不可变字段。
- 只讨论首次调度,不讨论 PodGroup 缺失、扩容、超时、抢占和成员重试。
- 把 alpha 能力描述成所有版本可用,遗漏
GenericWorkloadfeature gate。 - 用“绑定成功”代替“整组可运行”,没有组级指标和取消语义。
追问方向
如果 PodGroup 创建晚于 Pod 呢?
成员保持 Pending,调度器会在 PodGroup 出现后重新考虑;控制器仍应先组后 Pod 以减少等待窗口。
minCount 应该怎么定?
依据应用能前进所需的并发下限、单 Pod 资源和可接受的排队时间,设置上限并配合租户配额;不要盲目等于成员总数。
如何避免 gang 饥饿?
使用队列公平、老化、组大小上限和租户配额;监控组等待时间,必要时取消超时组释放容量。
与 schedulingGates 有何区别?
Gate 控制单个 Pod 何时进入可调度队列;Scheduling Group 让调度器按 PodGroup 评估一组成员。两者可以组合,但语义和故障指标要分别记录。
何时暂缓上线?
当集群版本、feature gate、调度插件或扩缩容器尚未兼容,或无法验证 alpha API 升级与回滚时,应先采用显式队列控制器并保留迁移方案。
参考资料
- Kubernetes 文档《Scheduling Group》。
- Kubernetes 文档《PodGroup Scheduling Policies》。
- Kubernetes 文档《Scheduling API Reference》。