LabHub
学习 学习路径 课程

CNPE — 云原生平台工程师

制造 Synced 状态的故障,并通过 Git 恢复

在 LabHub 中继续学习

目标

在真实 k3s 与 Argo CD 中执行正常部署 → readiness 故障 → Git revert 恢复。 随后把批准新部署前必须检查的条件写成代码。

为什么重要

GitOps 也会忠实应用错误声明。如果不区分 Synced 与服务可用性,就会把故障批准为成功。 本实验会观测真实进程、EndpointSlice 和 Service HTTP。Recreate 与单副本是为了让故障清晰可见而故意设置的实验条件,并非生产可用性推荐配置。 这是无状态 Web 配置恢复,不是数据库恢复或无中断金丝雀验证。不要对该 VM 外的集群或 Git 仓库执行命令。

已准备内容

首次准备可能需要数分钟。预计学习时间为 55 分钟;若需要更多时间,请在到期前延长。 会话结束后 VM 与文件都会回收,因此请提前下载所需记录。

步骤

  1. /srv/gitops/app/release.json 中以 v1 List 编写 cnpe-shop/web Deployment 与 Service。使用 1 个副本、Recreate、20 秒进度期限、名为 web 的容器、镜像 docker.io/library/nginx:1.27-alpine、标签与选择器 app=web,以及 Service 80→80。容器启动时,把 labhub-cnpe-v1 不带换行写入 nginx index.html,再运行 nginx。readiness 使用 / 与 80 端口,周期 2 秒、失败阈值 1;request 为 25m/32Mi,limit 为 200m/128Mi。提交并推送,把完整 SHA 保存到 /root/cnpe/baseline.sha
  2. /root/cnpe/project.json 中编写 argocd 命名空间的 AppProject cnpe-delivery,在 /root/cnpe/application.json 中编写 Application cnpe-shop,然后应用。项目只允许准备好的一个 Git URL、cnpe-shop 目标以及 Deployment/Service,并把集群范围允许列表留空。Application 使用该项目、Git 的 app 路径、最初完整 SHA、in-cluster 目标,以及自动同步、prune 与 selfHeal。
  3. 使用观测工具确认最初 SHA 已达到 Synced、Healthy,副本与端点均为 1,HTTP 为 200 且正文精确匹配,并保存到 /root/cnpe/baseline.json。后续步骤中仍应保留该文件,作为首次成功记录。
  4. 只把 Git 清单中的 readiness 路径改为 /not-ready,推送新提交,并把完整 SHA 保存到 /root/cnpe/bad.sha。同时把 Application targetRevision 更新为该 SHA,并 refresh 以读取新 Git。不要直接 patch Deployment。
  5. 观测状态变为 Synced 但 Degraded,出现 ProgressDeadlineExceeded,ready、available 与端点均为 0,HTTP 失败,并保存到 /root/cnpe/failed.json。不要猜测内容后手写,应收集真实 API 与请求结果。
  6. 对故障提交执行 git revert,创建内容与最初清单相同的新恢复提交。推送并把完整 SHA 保存到 /root/cnpe/recovered.sha,再把 Application 更新到这个新 SHA。不要删除历史,也不要强制倒退到最初 SHA。
  7. 在新恢复 SHA 上再次确认 Synced、Healthy,副本与端点均为 1,HTTP 响应精确匹配,并保存到 /root/cnpe/recovered.json。评分会同时检查保存文件与当前服务。
  8. 编写 /root/cnpe/release-gate.py。参数依次为状态 JSON 路径、期望完整 SHA、期望 HTTP 正文。只有下方批准契约全部满足时退出码为 0,否则必须非零退出。不要修改状态文件。应测试当前正常状态,以及逐字段错误与缺失反例。

第 8 步批准契约

参考

一次观测使用 .../evidence.py observe;等待条件使用 .../evidence.py wait healthy 전체SHA.../evidence.py wait failed 전체SHA。使用 > 保存到对应步骤的 JSON 文件。 如果 45 秒内条件仍不匹配,工具会显示错误。请检查 API、probe 与事件后重试。 等待命令不会替代部署,也不会修正状态。

第 1、3、4、5、6 步会检查 Git 历史与保留的观测记录。恢复后不要删除过去的故障记录。 第 2 步还会检查当前接线与权限,第 7、8 步还会重新检查当前服务。因此,完整评分在恢复后仍能通过。 记录 JSON 是学习记录,不是防伪证明。第 8 步评分会在临时副本中加入反例,不会修改学生文件。

在 Git 中留下正常发布

/srv/gitops/app/release.json 中以 v1 List 编写 cnpe-shop/web Deployment 与 Service。使用 1 个副本、Recreate、20 秒进度期限、名为 web 的容器、镜像 docker.io/library/nginx:1.27-alpine、标签与选择器 app=web,以及 Service 80→80。容器启动时,把 labhub-cnpe-v1 不带换行写入 nginx index.html,再运行 nginx。readiness 使用 / 与 80 端口,周期 2 秒、失败阈值 1;request 为 25m/32Mi,limit 为 200m/128Mi。提交并推送,把完整 SHA 保存到 /root/cnpe/baseline.sha

仅创建文件,repo-server 无法看到。请推送到准备好的 bare 仓库,并记录完整 SHA。

缩小允许范围并连接 Application

/root/cnpe/project.json 中编写 argocd 命名空间的 AppProject cnpe-delivery,在 /root/cnpe/application.json 中编写 Application cnpe-shop,然后应用。项目只允许准备好的一个 Git URL、cnpe-shop 目标以及 Deployment/Service,并把集群范围允许列表留空。Application 使用该项目、Git 的 app 路径、最初完整 SHA、in-cluster 目标,以及自动同步、prune 与 selfHeal。

AppProject 并非只需使用不同于默认值的名称。请检查真实 sourceRepos、destinations 与资源类型允许列表。

收集首次成功证据

使用观测工具确认最初 SHA 已达到 Synced、Healthy,副本与端点均为 1,HTTP 为 200 且正文精确匹配,并保存到 /root/cnpe/baseline.json。后续步骤中仍应保留该文件,作为首次成功记录。

observe 只读取一次;wait healthy 完整SHA 最多等待条件 45 秒。请区分 stderr 与 stdout。

创建有效但错误的部署

只把 Git 清单中的 readiness 路径改为 /not-ready,推送新提交,并把完整 SHA 保存到 /root/cnpe/bad.sha。同时把 Application targetRevision 更新为该 SHA,并 refresh 以读取新 Git。不要直接 patch Deployment。

固定完整 SHA 的 Application 不会自动跟踪 main 的新提交。还必须修改待部署 SHA。

观测处于 Synced 的故障

观测状态变为 Synced 但 Degraded,出现 ProgressDeadlineExceeded,ready、available 与端点均为 0,HTTP 失败,并保存到 /root/cnpe/failed.json。不要猜测内容后手写,应收集真实 API 与请求结果。

进程运行与 readiness 不同。在超过进度期限前,状态可能仍为 Progressing。

保留 Git 历史并恢复

对故障提交执行 git revert,创建内容与最初清单相同的新恢复提交。推送并把完整 SHA 保存到 /root/cnpe/recovered.sha,再把 Application 更新到这个新 SHA。不要删除历史,也不要强制倒退到最初 SHA。

revert 会创建包含相反变更的新提交。请同时恢复 Git 内容与 targetRevision。

对照新提交与真实响应

在新恢复 SHA 上再次确认 Synced、Healthy,副本与端点均为 1,HTTP 响应精确匹配,并保存到 /root/cnpe/recovered.json。评分会同时检查保存文件与当前服务。

不能仅凭保存的正常 JSON 判断当前服务正常。当前 targetRevision、端点与 HTTP 也必须匹配。

不批准空证据的 gate

编写 /root/cnpe/release-gate.py。参数依次为状态 JSON 路径、期望完整 SHA、期望 HTTP 正文。只有下方批准契约全部满足时退出码为 0,否则必须非零退出。不要修改状态文件。应测试当前正常状态,以及逐字段错误与缺失反例。

True 在 Python 中等于 1,但不是副本数量的正确类型。请分别检查缺失、类型、generation 与正文。