题干与适用场景
Kubernetes v1.35 在启用 RestartAllContainers 动作后,为容器提供 restartPolicyRules。规则可以把退出码映射到重启动作,但 Pod 仍然有生命周期和就绪契约。应把它当作失败分类机制,而不是探针或告警的替代品。
假设工作 Pod 有三个不同故障域的容器。抓取器可能因临时凭据刷新失败而恢复;代理配置错误应让运维看到并告警;上报器的本地状态损坏时,可能需要重启整个 Pod。
面试官考察点
面试官关注明确的失败分类、版本和特性门槛意识,以及防止重启循环掩盖事故的方案。强回答会把退出码连接到责任人、就绪状态、退避、指标和灰度安全。
普通回答给每个容器都加规则。强回答会说明哪些退出码属于稳定应用语义,哪些只是偶然的进程细节,以及如何证明每个容器的状态适合单独恢复。
回答前需要澄清的问题
- 所有集群保证哪些 Kubernetes 版本和特性门?
- 退出码由应用契约控制,还是由运行时和 shell 包装器产生?
- 容器状态可丢弃、有检查点,还是与 Pod 其他容器耦合?
- 同一退出码重复出现时,应退避、替换 Pod,还是升级告警?
- 一个容器重启期间,哪些信号定义用户可用性?
如果退出码没有经过测试的应用契约,应先使用统一重启策略并完善进程契约。如果状态耦合,单独重启可能让 Pod 内部出现不一致。
30 秒回答框架
“我会先确认 Kubernetes 版本和特性门,再为每个容器定义退出码语义。只重启无状态的临时失败;让永久配置错误保持可见;共享状态损坏时替换 Pod。我会记录规则命中、重启次数、退避、就绪状态和重复退出码告警,先灰度一个工作负载,若错误率或重启循环上升就回滚。”
分步骤深入解答
- 确认前提。 核对 v1.35 行为、
RestartAllContainers、准入策略,以及控制器和观测系统是否理解新字段。 - 定义退出码责任。 保留少量有文档的类别,例如临时刷新、永久配置和不可恢复状态。测试包装器,避免信号被意外改写。
- 选择最小安全动作。 抓取器的临时码可重启;代理配置错误保持 NotReady 并告警;共享状态无效时替换 Pod。
- 保护依赖关系。 以依赖契约控制就绪,协调终止钩子,容器状态未预热前不要接收流量。
- 控制重复。 结合重启次数、指数退避和重复码告警。持续重启最终必须变成运维可见的失败。
- 渐进发布。 先灰度一个工作负载,对比重启循环率、恢复时间、错误率和 Pod churn,护栏稳定后再扩大。
替代方案包括单容器内 supervisor、把独立故障域拆成不同 Deployment,或使用替换 Pod 的控制器。选择能保留状态并让故障可见的最简单边界。
高质量示范回答
“对抓取器,退出码 42 表示短暂凭据刷新失败;它没有持久本地状态,可以安全重启。配置错误保持 NotReady 并通知负责人,重启只会重复同一失败。上报器发现本地检查点损坏时,我会终止 Pod,让干净卷或新 Pod 一致恢复。规则先在特性门后的单个 canary 工作负载启用,告警关注重复命中和重启循环;如果恢复时间或错误率退化就移除策略。”
常见错误
- 错误表现: 把所有非零退出都当作临时失败 → 失败原因: 永久故障变成静默重启循环 → 修正方法: 定义并测试退出码语义。
- 错误表现: 忽略特性门和集群版本差异 → 失败原因: 同一清单在环境中行为不同 → 修正方法: 加入准入和发布检查。
- 错误表现: 单独重启耦合状态的容器 → 失败原因: 其他容器保留不兼容状态 → 修正方法: 替换 Pod 或协调恢复。
- 错误表现: 只监控重启次数 → 失败原因: 用户仍报错但指标看似健康 → 修正方法: 结合就绪与服务 SLO。
追问及应对
如果退出码 42 来自 shell 包装器,镜像更新后改变了怎么办?
把退出码当作 API。固定并测试包装器,记录责任边界,契约变化时阻断发布,不能默默继承运行时特定码。
如何避免重启循环掩盖事故?
告警关注重复命中、重启速率、退避饱和和就绪丢失。达到有限尝试次数后升级为 Pod 替换或运维可见失败。
什么时候整 Pod 重启更安全?
状态共享、初始化顺序重要,或一个容器损坏会使同伴失效时,替换 Pod 更安全。可接受更大范围重启以避免部分恢复不一致。
如何回滚这个特性?
在工作负载模板禁用策略,恢复旧的重启行为并确认旧副本收敛。保留退出码契约和仪表盘,确保回滚仍可观测。