空の目標を承認する前に
一言でいうと
空の目標は、意図した廃棄の場合もあれば、誤った生成結果の場合もあります。保護を解除する前に、現在のコミットと実際の削除の範囲を確認する必要があります。
なぜ必要なのか
環境別のディレクトリを整理したあと、デプロイ画面がOutOfSyncになりました。最後の操作にはSucceededと書かれています。 ある人は、調整が遅いだけだから待とうと言い、別の人は、allowEmptyを有効にすれば緑になるといって、設定を変えようとします。 どちらも、まだ何が空なのか、どの操作の成功なのかを確認していません。誤った生成結果を承認すると、 自動化が意図しない全体の削除を実行する可能性があります。
このユニットを作る前に、本物のArgo CD v3.5.2で小さなConfigMapを使って実験しました。空の目標を作るとオブジェクトは そのまま残り、SyncErrorが生じましたが、operationState.phaseはSucceededでした。確認してみると、その成功は 現在の空の目標のコミットではなく、以前にオブジェクトを作ったコミットの記録でした。成功という文字列だけを見る検証は、 失敗を見逃すにとどまらず、保護の仕組みが止めている削除を成功したと報告してしまう可能性がありました。
どう動くのか
自動pruneには、目標のリソースが1つもないときに、大規模な削除を防ぐ保護があります。allowEmptyをtrueにすると、 その保護を解除できます。これはエラーを素早く消すための修理ボタンではなく、空の状態を許容するという運用上の判断です。 このラボでは、2つ目のApplicationにdisposableというConfigMapを1つだけ任せます。1つ目のApplicationのretainedとanchorは、 実験が終わるまで同じUIDとデータを維持している必要があります。承認の対象の大きさを小さく保ちながら、境界を検証します。
1つ目の区別は、生成の失敗と有効な空の結果です。存在しないsource.pathを指定すると、マニフェストを読む 段階そのものが失敗することがあります。これを空の目標の保護の証拠として使ってはいけません。今回のリポジトリではemptyディレクトリを 維持して、resources.jsonを次のような有効な空のListに変えます。
{"apiVersion":"v1","kind":"List","items":[]}
2つ目の区別は、比較したコミットと実行した操作です。status.sync.revisionは、今比較した望ましい状態の座標であり、 status.operationState.syncResult.revisionは、その操作の結果が属する座標です。2つの値が異なると、古い操作の Succeededを、現在のコミットの実行の成功と読むことはできません。conditionsも一緒に見る必要があります。 この環境での拒否のメッセージはauto-sync will wipe out all resourcesで、最初に書いた検査は、メッセージにemptyが 含まれるだろうと推測して、実際の保護を見逃しました。その失敗も検証の記録に残しました。メッセージはバージョンによって変わる ことがあるので、受講生の環境ではバージョンを固定しており、メッセージ1つのほかに、空の目標・現在のrevision・ポリシー・保存するUIDを一緒に確認します。
| 観測 | Gitの目標 | 実際のdisposable | ポリシーと意味 |
|---|---|---|---|
| 基準線 | オブジェクト1つ | 基準のUID | allowEmpty=false |
| 空の目標の観測 | 0個 | 同じUID | 自動の全体削除が拒否される |
| レビュー後の許可 | 0個、同じコミット | なし | allowEmpty=trueで実際に削除 |
| Gitによる復元 | オブジェクト1つ、新しいコミット | 新しいUID | デフォルトの保護falseを復元、オブジェクトを再作成 |
同じコミットでポリシーだけが変わっても、実際のオブジェクトが消えることがあるという点を確認してください。Gitのdiffだけをレビューしたという主張だけでは、 Applicationのポリシーの変更までレビューしたことにはなりません。変更の承認の記録には、Gitの座標だけでなく、どのApplication、 どのポリシー、どのリソースの一覧を見て決めたのかも残す必要があります。
現場での姿
ブランチごとのテスト環境を廃棄する場合のように、目標が空になることが正当な場合もあります。それでも、レンダリングが失敗したことを 空の結果として扱っていないか、対象の環境が本当に廃棄の対象なのか、残すべきデータがないのかを確認する必要があります。 逆に、環境を維持したいのに結果が空なら、フィルターの条件やパスの選択から復元するほうが、意図に合います。 緑のランプを得ること自体を完了の条件にすると、リソースがすべて消えて、もう差がない状態も成功に見えます。
レポートを書くときは、次の問いに順番に答えてみてください。現在のコミットのレンダリングは成功したか。結果が空の理由は 意図した廃棄か。このApplicationが所有する削除の対象は、正確には何か。承認のあとに、予想した対象だけが消えたか。 復元が必要なら、オブジェクトの宣言とデータのそれぞれについて、何をどこから復旧できるか。
最後の問いは、このラボではあえて未完成のまま残します。ConfigMapをGitから再び作れば、同じデータを入れることは できますが、UIDは新しくなります。データベースやボリュームの中身が一緒に戻るわけではありません。この実験でバックアップが 検証されたと書かないでください。実際のデータの復旧可能性は、別のバックアップと復元のテストを通して証明する必要があります。
次のラボですること
preview-emptyは、空の目標を作って、保護が働いた観測を先に保存します。この時点では、disposableがまだ 残っている必要があります。guard-7.jsonから、現在のコミット、以前の操作のコミット、対象のUIDを読んだうえで、明示的に許可します。 次のステップでは、Gitの定義とデフォルトの保護を元に戻し、新しいUIDを確認します。すでに完了したステップは、再実行しても削除を 繰り返さず、採点は実際の状態を読み取るだけです。変更の記録がpendingで途切れていたら、完了を推測せずに 資料を保存します。新しい観測を得ようとして、同じ削除を無条件にもう一度実行する習慣を避けるための設計です。
公式ドキュメント
- Argo CDの自動同期: 自動pruneとallowEmptyの関係を確認してください。
- Kubernetes ConfigMap: 実験用のオブジェクトが保持するものと保持しないものを確認してください。