Argo CD显示绿色,订单页面却返回500
目标
区分 Git 同步与业务成功,确认配置真正被消费的时点,并通过 Git 完成恢复。
为什么这很重要
即使期望的配置已经部署,该配置本身也可能有误,或者运行中的进程尚未读取它。 本实验使用真实的 Argo CD、k3s 和 nginx,调查 readiness 返回 200、但业务路径返回 500 的合成故障。 不要调用或修改外部支付系统、用户数据或生产 LabHub。 仅使用个人 VM 中的 cgoa-business-health Namespace。不要更改全局控制器、安全或网络设置。 本实验时长为 55 分钟。如有需要,请在到期前延长时间,并另行保存所需文件。会话结束时,VM 和文件会被回收。
已准备的环境与辅助工具
Git 工作仓库位于 /srv/cgoa-business-health,bare 仓库位于 /srv/bare/cgoa-business-health.git。 Argo CD 从 VM 内部 gitd 服务读取 main 的 app 目录。不要使用外部 Gitea 或生产 Git。 实验服务器以 non-root 身份运行,capability drop ALL,根文件系统只读,使用 RuntimeDefault,且不挂载服务账户令牌。 nginx 镜像会在 VM 准备期间拉取,因此第一个学习步骤无需等待下载。 学生文件放在 /root/cgoa-health。题目中的 key=value 表示说明,文件请按格式示例写成 JSON。 python3 /opt/fixtures/cgoa_health_lab.py observe 会读取当前 Git、API、挂载文件和响应。 complete N 会验证所写的第 N 步答案,并保存实际观测结果。只有第 4、6 步会执行限定范围内的 Git 变更。 请使用 git show --stat 和 git show 直接检查变更内容。如果你直接修改了仓库,辅助工具不会覆盖,而是会停止。 solve N 与查看答案相同,会补充当前尚不存在的答案,不会修改已有的错误答案或部分答案。 prepare N 只准备尚未完成的前置步骤,不会创建当前第 N 步的答案。grade N 只读取文件、Git 和 Kubernetes。
步骤
- 在个人 VM 的 /srv/cgoa-business-health 中检查 git rev-parse HEAD。将实际 SHA 字符串写入 revision.json 的 revision,然后运行 complete 1。确认 observation-1.json 中的本地 Git、远程 main 与 Argo CD revision 一致,并且资源身份得到保留。
- 使用 observe 读取 /healthz 和业务路径 / 的响应。在 http.json 中写入数字 readiness=200、business=500,然后运行 complete 2。observation-2.json 中会保留三对实际 HTTP 状态码和正文样本。不要把 Healthy 理解为业务成功。
- 对照 git show HEAD:app/resources.json 中的 nginx.conf 与实际响应。在 diagnosis.json 中写入字符串 cause=application-config、probe_scope=process、fix_source=git,然后运行 complete 3。不要把外部 API 或 DNS 写成实际原因。
- 在 config.json 中写入数字 status=200 和字符串 body=checkout ready,然后运行 complete 4。辅助工具会创建一个只修改 ConfigMap 的 Git 提交并 push 到 main。在 observation-4.json 中调查:新的 revision 和新 ConfigMap 已经生效,但旧 Pod 和 500 响应是否仍然存在。还要通过 git show 确认 Deployment 未被更改。
- 比较 observation-4.json 中的 configmap.data.nginx.conf、mounted_config 和旧 Pod UID。在 consumption.json 中写入字符串 mode=subPath、布尔值 pod_replaced=false 和 restart_required=true,然后运行 complete 5。回答本实验使用的新 Pod 替换方式所需的操作。不要期望仅靠等待就能更新 subPath。
- 将 observation-4.json 中 configmap.data.nginx.conf 的字节编码为 UTF-8,并计算 SHA-256。在 rollout.json 的 checksum 中写入计算得到的 64 位字符串,然后运行 complete 6。第二个 Git 提交只会更改 spec.template.metadata.annotations 中的 checksum/config。将新 Pod、挂载文件以及业务 200 响应保存到 observation-6.json。
- 在 observation-6.json 中检查 git_revision 和 pod.metadata.uid。在 verification.json 中,将 revision 和 pod_uid 写为对应字符串,将 business=200 写为数字,将 deployment_replaced=false 写为布尔值,然后运行 complete 7。再次观测三对实际响应,并确认 Application 和 Deployment UID 是否得到保留。
- 根据此前的观测和 Git 谱系,在 decision.json 中写入布尔值 recovered=true、availability_guaranteed=false,以及字符串 config_strategy=versioned-rollout、next_check=external-path。使用 complete 8 保存最终观测结果。请区分内部样本成功与对外 DNS、TLS、身份验证及长期可用性保证。
参考
不要只看 Pod 名称,还要同时查看 UID、ConfigMap 数据与挂载文件,以及 HTTP 状态码与正文。 Git 配置提交和模板提交的父子关系会记录在观测结果的 git_parents 中。不要编辑成功的观测结果。 checksum/config 是触发模板变更的一种约定,并非 Kubernetes 内置的自动配置监控功能。 三次内部 HTTP 响应只是学习用样本,并未验证外部用户路径和长期可用性。 部分输入会被保留。如果存在错误答案,请自行对照题目修改后再次运行 complete。 如果在 Git 操作期间中断并留下 pending 记录,工具不会自动制造过去的成功结果。请保存资料,并在新的实验中重新开始。 哈希可以检测记录被意外覆盖,但无法作为安全保证来阻止同一 VM root 的所有伪造。 评分预算为 60 秒,准备前置步骤的预算为 90 秒。实际收敛等待由 complete 负责,而不是由评分过程负责。 ConfigMap 官方文档 · Argo CD health。
将 Git 与实际同步的提交关联起来
在个人 VM 的 /srv/cgoa-business-health 中检查 git rev-parse HEAD。将实际 SHA 字符串写入 revision.json 的 revision,然后运行 complete 1。确认 observation-1.json 中的本地 Git、远程 main 与 Argo CD revision 一致,并且资源身份得到保留。
不要比较会移动的 main 名称,而要比较固定不变的提交 SHA。
同时观测绿灯状态和业务 500
使用 observe 读取 /healthz 和业务路径 / 的响应。在 http.json 中写入数字 readiness=200、business=500,然后运行 complete 2。observation-2.json 中会保留三对实际 HTTP 状态码和正文样本。不要把 Healthy 理解为业务成功。
收到 HTTP 响应与业务成功是两件不同的事。
区分故障原因和需要修改的源头
对照 git show HEAD:app/resources.json 中的 nginx.conf 与实际响应。在 diagnosis.json 中写入字符串 cause=application-config、probe_scope=process、fix_source=git,然后运行 complete 3。不要把外部 API 或 DNS 写成实际原因。
请查找该服务器实际读取的 nginx 配置中的 return 值。
仅通过 Git 修复配置
在 config.json 中写入数字 status=200 和字符串 body=checkout ready,然后运行 complete 4。辅助工具会创建一个只修改 ConfigMap 的 Git 提交并 push 到 main。在 observation-4.json 中调查:新的 revision 和新 ConfigMap 已经生效,但旧 Pod 和 500 响应是否仍然存在。还要通过 git show 确认 Deployment 未被更改。
请通过 git show 和 Pod UID 区分配置变更与滚动更新。
证明 subPath 留下了旧文件
比较 observation-4.json 中的 configmap.data.nginx.conf、mounted_config 和旧 Pod UID。在 consumption.json 中写入字符串 mode=subPath、布尔值 pod_replaced=false 和 restart_required=true,然后运行 complete 5。回答本实验使用的新 Pod 替换方式所需的操作。不要期望仅靠等待就能更新 subPath。
请比较 API 中保存的配置与容器内文件是否具有相同值。
使用配置哈希更新 Pod 模板
将 observation-4.json 中 configmap.data.nginx.conf 的字节编码为 UTF-8,并计算 SHA-256。在 rollout.json 的 checksum 中写入计算得到的 64 位字符串,然后运行 complete 6。第二个 Git 提交只会更改 spec.template.metadata.annotations 中的 checksum/config。将新 Pod、挂载文件以及业务 200 响应保存到 observation-6.json。
请使用包含换行符的实际 nginx.conf 字符串计算哈希。
通过新进程的响应验证恢复
在 observation-6.json 中检查 git_revision 和 pod.metadata.uid。在 verification.json 中,将 revision 和 pod_uid 写为对应字符串,将 business=200 写为数字,将 deployment_replaced=false 写为布尔值,然后运行 complete 7。再次观测三对实际响应,并确认 Application 和 Deployment UID 是否得到保留。
请同时比较新的 Pod UID 和保持不变的 Deployment UID。
报告已验证的范围和剩余验证项
根据此前的观测和 Git 谱系,在 decision.json 中写入布尔值 recovered=true、availability_guaranteed=false,以及字符串 config_strategy=versioned-rollout、next_check=external-path。使用 complete 8 保存最终观测结果。请区分内部样本成功与对外 DNS、TLS、身份验证及长期可用性保证。
三次 ClusterIP 样本无法保证外部路径以及一个月的可用性。