LabHub
学习 学习路径 课程

CNPA — 云原生平台工程助理

恢复必须在下一个 Pod 启动后仍然有效

在 LabHub 中继续学习

一句话总结

安全恢复不能由一次正常响应证明。控制器对当前声明的观测状态、由该声明生成的 Pod、真实响应,以及替代 Pod 的配置必须全部一致。

概念图: 一句话总结 · 为什么需要它 · 它如何工作 · 先确认控制器是否读取声明

为什么需要它

即使新 Pod readiness 检查失败,服务也可能正常,因为旧 Pod 仍在处理请求。这不一定是异常,而可能是为了避免坏部署一次性清除现有容量的设计结果。

问题在于看到正常 HTTP 就认定新版本成功。如果响应来自旧 Pod,它不是新版本成功的证据。反过来,也不能因一个新 Pod 未就绪就断定所有用户都遭遇故障。部署进度与用户影响彼此相关,但不是同一个值。

真实探针中,两个旧正常 Pod 与一个未就绪的新 Pod 同时存在,服务由旧 Pod 正常响应。第一次回滚虽然完成,但替换旧 Pod 后,部分容量再次未就绪。这正是恢复定义必须包含 Pod 替换验证的依据。

它如何工作

先确认控制器是否读取声明

保存变更的 API 响应,并不表示控制器已经处理。应同时读取 Deployment 的 metadata.generationstatus.observedGeneration,确认当前声明已被观测;再区分新模板的副本数、就绪数和可用数。Available 条件也可能仍来自以前的状态。

本例使用两个副本、maxSurge: 1maxUnavailable: 0,确保新 Pod 未就绪时不会先减少旧正常容量。终止中的 Pod 可能短暂额外出现,不要把列表长度与 Deployment 容量计算混为一谈。

还要准确描述观测命令没有在时限内结束:它只表示在该观测窗口中没有看到完成,与 Deployment 控制器报告的进度期限超时或应用真实 readiness 失败是不同证据。仅凭超时重新启动同一安装,可能会抹去原因或造成执行重叠。

关联实际响应的 Pod

示例应用会在响应中返回 Pod 名称、读取的配置版本与正常状态,但只相信这些值仍然不够。还要按 UID 对照所查 Pod 是否属于对应 ReplicaSet,以及 ReplicaSet 是否属于本次 Deployment,因为名称可能复用。

应同时查看各 Pod 的 /readyz 响应与 Kubernetes Ready 条件。进程仍存活的 liveness 与可以接收流量的 readiness 不同。本例在错误配置下进程仍存活,但 readiness 返回 503。还要关联服务成功响应来自哪个正常 Pod。

这并不意味着生产应用必须始终向外部用户暴露这些信息。这个小型教学响应用于展示观测对象之间的关系。生产环境应选择受访问控制的内部诊断路径、日志或部署元数据。

用下一个 Pod 验证恢复

回到旧版本后,替换一个正常 Pod。确认旧 UID 消失并产生新 UID,再检查新 Pod 是否真正读取旧配置并进入就绪。不能把旧正常 Pod 的响应复用为新 Pod 成功的证据。

这种替换只在个人 VM 内指定工作负载中进行,并不是在生产环境中为确认恢复而任意删除 Pod 的流程。生产环境必须先考虑容量、中断预算、流量和批准的测试范围。探针的删除请求也附带 UID 与 resourceVersion 条件,避免忽略其他对象或并发变更。

实际现场中的表现

平台团队在提供部署工具的同时,也应提供理解失败的线索。相比“部署失败”一句话,“一个新副本正以配置 v2 运行但 readiness 返回 503,两个旧 v1 副本仍在服务”更能帮助开发者决定下一步行动。

恢复记录不仅要说明改变了什么,也要说明保留了什么。本实验最后重新确认了其他团队的 Deployment UID 与正常响应。这不能证明所有租户隔离,但能排除通过删除其他应用来挽救自己应用的错误成功。

保存记录时,应把当前执行与目标 UID 关联,并避免后续步骤覆盖过去观测。不要把查询失败记录成空列表或正常状态。完成后再次评分同一步骤时,旧证据的意义仍应保持,学习者才能回顾自己学到了什么。

下一项实验将做什么

我们会使用可变配置执行部署与回滚,并观察 Pod 替换后故障复发;随后通过按版本划分的不可变配置引用恢复,并比较直到替代 Pod 也正常的结果。目标是把命令退出码、控制器状态、真实响应与配置来源视为不同证据。

官方文档