ぽよメモ

レガシーシステム考古学専攻

ArgoCDでリソースを消さずにrequire pruning状態を解消する

背景

ArgoCDでGitOpsしているとします。ここで誤ってkube-system namespaceリソースを一度管理下に入れてpushし、revertしたとしましょう。このようにArgoCDが同期しているリソースが同期元から消えたとき、設定によって以下の2パターンのどちらかの挙動となります。

  • prune: true のとき
    • 同期していたリソースの削除を自動的に試みる。リソースの削除が完了するとSyncedステータスになる。
  • prune: false のとき
    • 同期していたリソースは削除されず、該当リソースの削除待ち状態となりApplicationリソースは OutOfSyncステータスになる。
    • 手動で該当リソースを削除するとSyncedステータスになる。

まず前者の状態になるといきなり詰む可能性があります。基本的に使わない方がよいでしょう*1

後者の場合、kube-system namespaceは消したくありませんがOutOfSyncは解消したいところです。手動syncをしても(設定を変えなければ)以下の様にfailせずにずっとOutOfSyncなままの状態になります。今回はこれをどうにかする方法を紹介します。

kube-systemがrequire pruningになりOutOfSyncになっている

今回検証したのはArgoCD v2.14.11とv3.0.1の2つのバージョンです。

効果が無い方法

ignoreDifferenceに追加する

ArgoCDで差分を無視する有名な方法としてはArgoCDのsyncOptionで差分を無視するリソースを記述する方法です。GitHub Copilot Chatで聞いたところこれをおすすめされました。

argo-cd.readthedocs.io

しかし一度OutOfSyncとして認識されてしまうとこの方法は効果がありませんでした。

ArgoCDの機能でロールバックする

今回は一度変更をpush→revertしてなかったことにしたリソースでOutOfSyncにしてしまったため、過去のpush前の状態に戻すことは比較的安全であると考えられます。このとき上手くリセットされて管理下から外れないだろうかと考えたのですが効果はありませんでした。

argo-cd.readthedocs.io

正しい(?)方法

ArgoCDがリソーストラッキングに使っている情報を当該リソースから消すと、ArgoCDの管理下から外れます。そのリソースは既にArgoCDの同期対象ではないため、再度トラッキング情報が付与されることもありません。

ArgoCDがリソーストラッキングする方法が3つあり、自分のクラスタでどれを使っているかによって対処法が異なります。必ず設定を確認するようにしてください。

argo-cd.readthedocs.io

label の場合

v3.0.0以前のデフォルトのトラッキング手法です。ArgoCDは app.kubernetes.io/instance ラベルを使ってリソースを識別します

今回リソースを同期しているApplicationの名前を foo とすると、同期されているリソースには app.kubernetes.io/name: foo のようなラベルが付与されます。このラベルを削除すると管理かから外れたと認識され、OutOfSync状態からSyncedになります。

ドキュメントには書かれていませんが、自分の環境ではapp.kubernetes.io/part-of ラベルも付与されていたのでこれも消した方が良いでしょう。

# ラベル名の末尾に - を付けると削除するという意味になる
kubectl label ns kube-system app.kubernetes.io/instance-
kubectl label ns kube-system app.kubernetes.io/part-of-

annotation の場合

v3.0.0以降のデフォルトのトラッキング手法です。ArgoCDは対象リソースに argocd.argoproj.io/tracking-id アノテーションを付与します。 今回の場合以下のようなアノテーションが付与されていました。

❯ kubectl get ns kube-system -o yaml
apiVersion: v1
kind: Namespace
metadata:
  annotations:
    argocd.argoproj.io/tracking-id: require-pruning:/Namespace:require-pruning/kube-system
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Namespace","metadata":{"annotations":{"argocd.argoproj.io/tracking-id":"require-pruning:/Namespace:require-pruning/kube-system"},"name":"kube-system"}}
  creationTimestamp: "2025-05-18T02:15:00Z"
  labels:
    kubernetes.io/metadata.name: kube-system
  name: kube-system
  resourceVersion: "2095"
  uid: b4ed1a04-d5f3-4a15-bb19-bf2675660439
spec:
  finalizers:
  - kubernetes
status:
  phase: Active

このアノテーションを削除します。

# アノテーションも末尾に - を付けると削除するという意味になる
kubectl annotate ns kube-system argocd.argoproj.io/tracking-id-

annotation + label の場合

二つの方法の対応をどちらもやりましょう。

結果

Revertコミットに対してsyncedな状態になります。

syncedになった

手動syncするとどうなる?

設定を変更せずsyncするだけなら問題は生じません。 prune: false なApplicationではリソースは削除されないためです。

しかし、よくわからずオプションを有効にして手動syncすると問題が生じる可能性があります。仮にApplicationの設定で prune: false にしていても以下のように PRUNE を有効にしてsyncすると当該リソースを削除しようとします。

PRUNEにチェックを入れてsyncすると削除が走る

既に述べたようにkube-systemは保護されているため単にこの操作は失敗するのですが、何も保護が働いていないリソースに対して行うと削除は成功してしまいます。

手動syncするとkube-systemは削除出来ずsyncはfailする

forbiddenと言われている

まとめ

消したくないのに一度管理下に入れてしまったリソースを安全にArgoCDから見えないようにするには、付与されているリソーストラッキング情報を削除してやれば良いです(たぶん)。

またこのような事態が起き得ることを想定し、 prune: true な設定はできるだけ避けるべきでしょう。開発用で毎日のように消したり作ったりするリソースが含まれる様な環境以外では無効にしたいところです。

慌てて手動syncするのも危険です。仮にApplicationの設定で prune: false になっていても、手動syncでは無理矢理pruneできてしまうためです。


*1:kube-systemは保護されているため削除できませんが、同様に重要なNamespaceの削除はできないように保護を検討した方が良いでしょう。