Gitから消したものと実際に消えたもの
一言でいうと
Gitから消したものは削除の意図であり、実際に削除されるかどうかは、自動pruneのポリシーとオブジェクトごとの保護ルール、承認によって決まります。
なぜ必要なのか
デプロイ用のリポジトリで、使っていない設定ファイルを整理しました。レビューには、ファイル1つの削除と表示されます。 ところが、そのファイルがNamespaceや永続データとの接続を定義していたなら、レビュー上の小さな差が、運用では大きな削除になります。 GitOpsの長所である継続的な調整は、作成と変更にだけ適用されるわけではありません。削除も、望ましい状態に合わせる動作です。 逆に、Gitから消えたすべてのオブジェクトを永遠に残すと、使われないリソースがたまり、責任者が誰なのか分かりにくくなります。 必要なのは、削除をすべて切ることではなく、何を自動で削除し、何をレビューのあとで削除するかを決める基準です。
このラボは実際のデータを使いません。disposable-exerciseという短い値を入れたConfigMapで、ライフサイクルを再現します。 運用と同じ判断の構造を学びつつ、データ損失という代償は作らないための選択です。実際のPVCの保存や復元まで テストしたと解釈してはいけません。同じ名前のYAMLをもう一度適用できることと、データを復旧できることは別です。
どう動くのか
まず、3つの対象を切り分けます。Gitのディレクトリは望ましい状態を保持し、Applicationはどのディレクトリをどのクラスターに 適用するかを指定し、ConfigMapはその結果として作られた実際のオブジェクトです。Gitのパスからオブジェクトをなくすpruneと、 Application自体を削除するときに伴うリソースの整理は、別の出来事です。
自動同期を有効にしたからといって、自動削除まで有効になるわけではありません。Applicationのautomated.pruneが、削除の自動化を 決めます。このラボでは、その値をtrueにして、オブジェクトごとのオプションを比較します。次の表の核心は、異なる状態の列を 成功という1つの言葉に圧縮しないことです。
| Gitから削除したオブジェクト | 実際のオブジェクト | sync.status | operationState.phase |
|---|---|---|---|
| 特別な保護がないnormal | 削除される | Synced | Succeeded |
| Prune=falseのretained | 残る | OutOfSync | Succeededになることがある |
| Prune=confirmのconfirmed、承認前 | 残る | OutOfSync | Running |
| confirmed、承認後 | 削除される | Synced | Succeeded |
Prune=falseは、削除の操作をスキップさせます。Argo CDがもともと行おうとした削除は残っているので、望ましい状態と実際の状態は 異なります。かといって、調整器が故障したわけではありません。このとき、syncResultの該当のオブジェクトにはPruneSkippedが残ります。 保護されたオブジェクトが残る理由を把握したうえで、Gitに定義を戻せば、同じUIDのまま再びSyncedになることがあります。 OutOfSyncをなくそうとして実際のオブジェクトを手動で削除すると、保護ルールの目的そのものを壊してしまいます。 この復元は、すでに残っていた実際のオブジェクトとGitを再び一致させるので、新しい同期の操作が必要ないこともあります。 そのため、現在のsync.revisionとSynced、同じUIDを確認し、新しいoperationが作られること自体は、成功の条件として求めません。
Prune=confirmは、レビューが必要な削除を保留します。このときのRunningは、無限の障害という意味ではなく、承認待ちであることが あります。待っている原因は、operationState.messageと、削除予定のリソースの一覧で確認します。 承認は、Applicationのargocd.argoproj.io/deletion-approvedアノテーションに時刻を記録する方法でも行えます。 重要なのは、承認の印がConfigMap1つではなくApplicationに付くことです。レビューしたもの以外に、 別の削除対象が一緒にできた場合、以前の判断をそのまま適用することはできません。
Delete=falseは、名前が似ていますが、Applicationを削除するときの整理に関するオプションです。Gitからリソースを削除する pruneの別名ではありません。運用ドキュメントを書くときは、削除という言葉のあとに主語を付けてください。 Gitから何を削除したのか、Applicationを削除するのか、実際のオブジェクトを直接削除するのかを区別して初めて、オプションも正しく選べます。
現場での姿
チームが設定の所有権を別のリポジトリに移すとき、以前のApplicationのGit定義を先に削除すると、自動pruneが先に オブジェクトを削除することがあります。保護オプションを1つコピーするだけで、移行の設計が完成するわけではありません。 移行前と新しい所有者の範囲、同じオブジェクトを2つの調整器が同時に管理する期間、失敗したらどの原本に戻るかまで 決める必要があります。このユニットの2つのApplicationは、互いに異なるConfigMapを管理するので、そのような二重の所有は作りません。
証拠を読むときは、名前とUIDを一緒に見てください。Kubernetesでは同じ名前で新しいオブジェクトを作れるので、名前が 同じだという理由で保存されたと判定することはできません。逆に、Gitのコミットが変わったからといって、オブジェクトも新しく作られたわけではありません。 次のように、実際の状態と望ましい状態の座標を並べて残す習慣が役に立ちます。
git -C /srv/cgoa-prune-safety rev-parse HEAD
kubectl -n argocd get application cgoa-prune-safety -o json
kubectl -n cgoa-prune-safety get configmaps -o json
ここで読むのは、コミットSHA、source.path、destination.namespace、sync.revision、削除予定の一覧とUIDです。 それぞれの意味を説明できないまま、出力の全体をレポートに貼り付けることは、検証の代わりにはなりません。
次のラボですること
通常の削除、削除の保持、Gitによる復元、承認待ちを自分で作って確認します。承認のステップでは、前の観測のApplicationのUIDと 対象のConfigMapのUIDを、答案に書きます。ヘルパーは、現在の対象と違うと停止します。この制限は、誤った範囲に対する 学習中のミスを防ぐ仕組みであり、管理者のrootによるあらゆる操作を遮断するというセキュリティ上の保証ではありません。
公式ドキュメント
- Argo CDの同期オプション: PruneとDeleteが適用される場面を比較してください。
- Kubernetesのオブジェクト名とUID: 名前の再利用とオブジェクトのアイデンティティを区別してください。