代表性面试主题

系统设计面试:如何设计 Kubernetes Pod 原地资源调整?

系统设计困难
Offer.cc 编辑团队发布 更新

题干

平台团队希望在不重建 Pod 的情况下调整 CPU 与内存。请设计 Kubernetes 原地 Pod 调整流程,说明何时容器必须重启、如何处理资源不足,以及怎样观测和回滚。

题干与适用场景

平台团队希望在不重建 Pod 的情况下调整 CPU 与内存。请设计 Kubernetes 原地 Pod 调整流程,说明何时容器必须重启、如何处理资源不足,以及怎样观测和回滚。

Kubernetes 1.33 将容器原地调整提升为 Beta;1.36 的 Pod 级资源调整也处于 Beta。请求修改运行中 Pod 的 CPU 和内存资源,kubelet 根据 resizePolicy、节点容量与 cgroup 状态执行或延迟处理,避免把“修改规格”误解为“永不重启”。

面试官考察点

重点包括:区分 Pod 级资源上限与容器资源、resizePolicy 的 CPU/内存语义、Pending/InProgress 状态、不可行与延迟重试、调度器与 kubelet 的职责、QoS 与优先级,以及灰度和回滚边界。

30 秒回答框架

“我会把原地调整设计成声明式请求加状态机。控制器更新资源规格,kubelet 检查节点可行性并更新 PodResizePendingPodResizeInProgress;CPU 通常可以不重启,内存是否重启由容器的 resizePolicy 决定。不可行请求要保留原因并按优先级重试,不能假装已经生效。平台需要观测 observedGeneration、实际 cgroup、重启次数和 QoS 变化,并以小批量灰度和反向 patch 回滚。”

分步骤深入解答

第一步:定义资源模型

容器资源决定单个容器的请求与限制;Pod 级资源在支持的版本中提供聚合边界。Pod 级限制是所有容器使用量的上界,但单个容器限制不能超过 Pod 级限制。API 设计必须明确修改的是 spec.containers[*].resources 还是 spec.resources

第二步:建立声明式调整流程

平台接收目标资源和原因,写入 Pod 的资源字段,保存原值、操作者和变更代次。API 层不直接操作节点 cgroup;kubelet 观察新的 generation,完成可行性检查和执行,并把结果写回状态。

第三步:处理重启策略

容器可按资源分别配置重启策略:

yaml
resizePolicy:
  - resourceName: cpu
    restartPolicy: NotRequired
  - resourceName: memory
    restartPolicy: RestartContainer

NotRequired 尝试在运行中应用;RestartContainer 允许通过重启使新值生效。对于 restartPolicy: Never 的 Pod,所有容器资源都必须使用 NotRequired,否则请求无效。

第四步:设计可行性与延迟状态

节点无法提供目标资源时,kubelet 设置 PodResizePending,原因可以是 InfeasibleDeferred;成功处理时进入 PodResizeInProgress。控制器应读取状态而不是只看 API spec,并通过 observedGeneration 确认状态对应的请求代次。

第五步:处理 CPU 与内存差异

CPU 调整通常可更新 cgroup 配额而不重启应用。内存缩容可能受到当前工作集限制,部分运行时需要重启才能安全应用;不能以 CPU 的无重启行为推断内存。控制器应按资源读取策略并为每种结果提供明确事件。

第六步:协调调度与 QoS

原地调整不等于节点重新调度。扩大请求可能需要节点容量,延迟请求应按 PriorityClass、QoS 类别和等待时长重试。调整后要重新计算 QoS、资源配额和监控告警,避免突破 namespace 配额或让 Guaranteed 工作负载被低估。

第七步:观测实际生效值

同时采集期望 spec、status 条件、observedGeneration、容器实际 cgroup 配额、重启次数、OOM、CPU throttling 与内存工作集。若状态显示完成但 cgroup 未变化,应把它视为失败并阻止下一次调整,而不是继续叠加 patch。

第八步:灰度、限速与回滚

按工作负载和节点池分批执行,限制并发调整数,设置 Pending 超时和最大重试次数。异常时恢复保存的旧资源;若内存策略导致重启,先摘除流量并验证就绪,再扩大灰度。所有请求都要支持幂等键,避免控制器重复提交。

设计取舍与边界

无重启连续性还是资源确定性

原地调整减少服务中断,但延迟和节点容量会让结果异步。对延迟敏感服务可保守使用小步调整;对批处理可接受重启以换取确定性。

Pod 级边界还是容器级精度

Pod 级资源适合表达共享上限,容器级资源适合保护关键容器。两者同时存在时,平台必须校验容器限制不超过 Pod 上限,并在 UI 和审计中显示有效边界。

自动重试还是人工批准

可行性暂时不足适合有限重试;涉及内存重启、QoS 变化或生产高峰时,应要求批准或维护窗口,不能无限自动重试。

失败演练与演进计划

节点资源不足

提交超过节点容量的扩容请求,确认状态为 InfeasibleDeferred,验证重试不会修改已生效的旧值。

内存调整触发重启

为内存设置 RestartContainer,观察流量摘除、容器重启、就绪恢复和事件顺序,确认控制器不会把重启误报为业务故障。

代次竞争

快速提交两个不同目标,确认旧 generation 的完成状态不会覆盖新目标,并且最终状态的 observedGeneration 与实际 cgroup 一致。

常见误区与追问

误区一:原地调整保证永不重启

追问:什么会触发重启?容器的 resizePolicy 可以要求重启,尤其是内存变化;Pod 级资源调整本身没有独立重启策略,但容器策略仍生效。

误区二:只更新 spec 就算完成

追问:如何确认成功?检查状态条件、observedGeneration、实际 cgroup、容器事件和重启次数,不能只读期望字段。

误区三:节点不足时持续 patch

追问:正确做法是什么?保留 Pending 原因,按优先级和等待时长有限重试,并提供迁移、缩小目标或人工批准路径。

延伸追问与参考答案

为什么 CPU 和内存要分开设计?

CPU 配额通常能在线改变;内存缩容受工作集和运行时约束,可能需要重启。统一接口仍应保留按资源的策略和状态。

如何防止重复调整覆盖新目标?

用资源版本或 generation 做条件更新,控制器只接受最新目标,状态通过 observedGeneration 与实际 cgroup 对账。

何时不应使用原地调整?

需要强隔离、节点无法稳定提供容量、应用不能承受重启或资源变化会破坏运行时假设时,应采用新 Pod 滚动替换并保留原地功能作为受控优化。

公开来源

同类题目

相关面试工具

用 Solve 整理系统设计回答

从澄清需求开始,展开规模、架构、组件选择和取舍。

查看工具