题干与适用场景
一个批处理平台会同时创建数千个 Pod,但镜像、配额、拓扑或外部资源尚未准备好。请设计一种机制,让 Pod 创建后暂不进入 Kubernetes scheduler,条件满足时再放行;同时说明如何避免调度器和 Cluster Autoscaler 被大量无效 Pending Pod 消耗,如何处理闸门超时、控制器故障和多租户隔离。
面试官考察点
- 能否把“已创建”与“可调度”拆成独立状态。
- 是否理解
spec.schedulingGates的创建、移除和不可追加约束。 - 能否设计幂等解闸、超时、权限和恢复流程。
- 能否区分 SchedulingGated、Unschedulable 与运行失败。
- 能否用指标、事件和审计记录证明系统没有静默卡死。
回答前需要澄清的问题
- 闸门由谁添加,哪些条件由谁负责确认?
- 条件是 Pod 级、批次级还是租户级?是否要求 gang scheduling?
- 放行延迟、过期策略、最大并发和成本目标是多少?
- 控制器重启、API 重试、节点扩缩容和权限撤销如何处理?
30 秒回答框架
我会在 Pod 创建时写入命名空间限定的 schedulingGates,把镜像预热、配额和外部资源准备做成可观测条件。控制器只负责幂等移除已有 gate,不在创建后追加新 gate;放行前再次检查租户配额和批次策略。指标区分 gated 与真正不可调度,超时进入明确的失败或人工处理状态,所有变更带条件版本和审计记录。
分步骤深入解答
1. 定义状态机
建议区分 Created、SchedulingGated、ReadyToSchedule、Unschedulable、Running 和 Expired。Pod 仍可被 API 读取,但 scheduler 不会尝试处理非空 gate 的 Pod。
2. 选择 gate 命名
每个 gate 是字符串条件名,例如 batch.example.com/image-ready。命名空间、批次和控制器版本写入 labels 或 annotations,gate 本身只表达未满足的条件,避免把动态数据塞进 gate 名称。
3. 在创建时写入 gate
gate 只能在 Pod 创建时由客户端或准入变更器初始化。创建后可以按任意顺序移除已有 gate,但不能追加新 gate;因此所有可能的阻塞条件必须在创建阶段完成枚举。
4. 设计解闸控制器
控制器监听 Pod、配额、镜像预热和外部资源事件,计算条件集合后执行带资源版本的 patch。重复事件应得到同一结果;只移除自己拥有的 gate,避免与其他控制器互相覆盖。
5. 处理批次与并发
批次级资源可由独立对象记录,Pod gate 只等待批次控制器的结论。放行时按租户配额、优先级和最大并发分批删除 gate,避免瞬间把调度压力转移到 scheduler 和 autoscaler。
6. 设计超时与人工介入
创建时间、最后条件更新时间和截止时间都应持久化。超时后不要偷偷移除 gate;应写入原因、发出事件并选择取消、重试或转人工队列。重试必须有退避和最大次数。
7. 观测真实队列
Kubernetes 提供 schedulerpendingpods 的 gated 标签,用于区分明确未准备好调度与已尝试但不可调度。配合 Pod condition、事件、控制器队列长度、gate 年龄分位数和 autoscaler 活动,才能定位瓶颈。
8. 约束权限与恢复
准入策略限制谁能创建 gate,控制器只允许移除指定命名空间和前缀的 gate。控制器重启后从 API 重建状态;patch 冲突重新读取并比较资源版本。若控制器长期不可用,值班流程应能按审计记录安全取消或放行。
设计取舍与边界
Scheduling gates 只控制 Pod 是否进入调度,不替代节点亲和性、资源请求、拓扑约束或运行时 readiness。gate 过多会把真实容量问题隐藏在应用层;gate 过少则会让无准备的 Pod 进入 scheduler。控制器必须把“条件未满足”和“集群没有容量”保持为不同信号,也不能把 gate 当作锁来实现任意跨对象事务。
落地计划与证据
- 记录每类 gate 的所有者、条件来源、超时和删除权限。
- 在准入层验证 gate 前缀、租户配额和创建时的完整条件集合。
- 先用小批次压测 scheduler、autoscaler、API Server 和控制器 patch 冲突。
- 监控
schedulerpendingpods{queue="gated"}、gate 年龄、超时率、放行吞吐和每租户并发。 - 演练控制器重启、网络分区、权限撤销、批次取消和重复 patch,并核对审计日志。
常见误区与追问
误区一:创建后再追加 gate
API 约束是 gate 只能创建时设置,之后只能移除。动态条件应由控制器在创建前汇总,或使用独立对象等待后再创建 Pod。
误区二:把 SchedulingGated 当成调度失败
非空 gate 的 Pod 尚未被 scheduler 尝试。回答必须区分 gated、Unschedulable、ImagePullBackOff 和应用 readiness。
误区三:用删除 gate 代替配额控制
移除 gate 只表示允许尝试调度,不能保证资源存在。放行前仍要检查配额、优先级和批次并发。
误区四:没有 gate 年龄和超时告警
没有年龄分位数就无法发现静默卡死。应记录条件、责任控制器、最后进展和明确的取消路径。
误区五:忽略 autoscaler 成本
大量未准备 Pod 会触发无意义的扩容评估。使用 gated 队列指标和放行节流验证成本是否真正下降。