批准空目标之前
一句话总结
空目标既可能表示有意废弃,也可能是错误的生成结果。解除保护前,必须确认当前 commit 与真实删除范围。
为什么需要它
整理各 environment directory 后,deployment 页面变为 OutOfSync,最后一次 operation 却显示 Succeeded。有人认为 reconciliation 较慢,应继续等待;另一个人则建议启用 allowEmpty,让状态变绿。但两人都尚未确认什么变空了,也没有确认是哪次 operation 成功。如果批准错误的生成结果,automation 可能执行原本无意进行的全量删除。
创建本单元前,我们在真实 Argo CD v3.5.2 上用一个小 ConfigMap 进行了实验。生成空目标后,object 仍然保留并出现 SyncError,但 operationState.phase 显示 Succeeded。检查后发现,这个成功记录并不属于当前空目标 commit,而是来自之前创建 object 的 commit。只检查成功字符串,不只是可能漏掉失败,还可能把 protection guard 正在阻止的删除报告为成功。
工作原理
自动 prune 在目标 resource 为零时提供阻止大规模删除的保护。将 allowEmpty 设为 true 可以解除该保护。这不是快速消除 error 的 repair button,而是允许 empty state 的运营决策。实验让第二个 Application 只管理一个 disposable ConfigMap。第一个 Application 的 retained 与 anchor 必须在实验结束前保持相同 UID 与 data。这样既能把批准 scope 保持得很小,也能验证 boundary。
第一项区分是 generation failure 与有效空结果。指定不存在的 source.path,可能在读取 manifest 的阶段就失败,不能用来证明 empty target protection。本 repository 会保留 empty directory,并把 resources.json 改为以下有效空 List。
{"apiVersion":"v1","kind":"List","items":[]}
第二项区分是比较的 commit 与执行的 operation。status.sync.revision 是当前正在比较的 desired state coordinate,status.operationState.syncResult.revision 则是该 operation result 所属 coordinate。两者不同时,不能把旧 operation 的 Succeeded 理解为当前 commit 执行成功,还必须同时检查 conditions。
本环境中的拒绝消息是 auto-sync will wipe out all resources,而最初编写的探针错误猜测 message 会含有 empty,因此漏掉了真实保护。该失败也保存在 validation record 中。message 可能随 version 改变,所以学员环境固定版本;除 message 外,还会同时确认 empty target、current revision、policy 和 retained UID。
| 观测阶段 | Git target | actual disposable | 策略与含义 |
|---|---|---|---|
| baseline | 一个 object | baseline UID | allowEmpty=false |
| empty target 观测 | 0 个 | 相同 UID | 自动全量删除被拒绝 |
| review 后允许 | 0 个,同一 commit | 不存在 | allowEmpty=true,实际删除 |
| 恢复 Git | 一个 object,新 commit | 新 UID | 恢复默认保护 false,重新创建 object |
注意,即使 Git commit 相同,只改变 policy 也可能让 actual object 消失。声称已 review Git diff,并不代表也 review 了 Application policy change。change approval record 不仅要保存 Git coordinate,还要记录查看了哪个 Application、什么 policy、哪份 resource list 后才做出决定。
现场会遇到的情况
在销毁 branch-specific test environment 等场景中,target 变空可能完全合理。即使如此,也必须确认:没有把 rendering failure 当作 empty result,目标 environment 确实需要废弃,并且没有应保留的数据。反过来,如果要维持 environment,却得到空结果,就应先恢复 filter condition 或 path selection。若只把获得绿灯当作完成条件,那么所有资源已经消失、因而不再有差异的状态,也会被视为成功。
编写报告时,请按顺序回答:当前 commit rendering 是否成功?结果为空是有意废弃吗?该 Application 精确拥有哪些 deletion target?批准后是否只删除了预期 target?如果需要恢复,object definition 与 data 分别能从哪里恢复?
最后一个问题在本实验中故意保持未完成。重新从 Git 创建 ConfigMap 可以写入相同 data,但 UID 会重新生成;database 或 volume 内容不会随之自动恢复。不要声称该实验已经验证 backup。真实数据的 recoverability 必须通过独立 backup 与 restore test 证明。
下一项实验要做什么
preview-empty 会先创建 empty target,并保存保护生效的观测。此时 disposable 必须仍然存在。随后从 guard-7.json 读取 current commit、previous operation commit 与 target UID,再显式允许删除。下一阶段恢复 Git definition 与默认保护,并确认新的 UID。已经完成的阶段即使重新运行,也不会重复删除;评分只读取 actual state。如果 change record 停在 pending,不能猜测已经完成,而应保留材料。此设计用于避免为了获得新观测而无条件重复同一次删除。
官方文档
- Argo CD 自动同步:确认自动 prune 与 allowEmpty 的关系。
- Kubernetes ConfigMap:确认实验 object 包含与不包含的内容。