比較から何を外すか
一言でいうと
無視ルールは、同期の判定から特定のフィールドを除く仕組みです。広く使うと、ノイズと一緒に本物のドリフトも消えてしまうので、argocd admin settings resource-overrides ignore-differencesで消える行を目で確認してからコミットする必要があります。
なぜこの仕組みが必要なのか
GitOpsの理想は「リポジトリに書かれたものがそのままクラスター」です。現実はそうではありません。クラスターには、リポジトリに書けない値が次々に生まれます。HPAがspec.replicasを変え、サイドカー注入のWebhookがコンテナを1つ差し込み、コントローラーがdeployment.kubernetes.io/revisionのようなアノテーションを付けます。これらの値をリポジトリに書くことはできません。書いた瞬間にその値が固定され、そうするとHPAやWebhookが存在する理由がなくなるからです。
そこで無視ルールがあります。「このフィールドの差はOutOfSyncとして数えない」と宣言する場所です。問題は、この仕組みに一方にだけ傾く力があるという点です。広く無視すれば画面が静かになり、狭く無視すればずっと騒がしいままです。静かなほうの代償は、数か月後に来ます。
どう動くのか
ルールは2か所に書けます。グローバルはargocd-cmのresource.customizations.ignoreDifferences.<그룹>_<종류>で、アプリごとのものはApplicationのspec.ignoreDifferencesのリストです(プレースホルダーは、順にグループと種類です)。2つはマージされて適用されます。そのため、グローバルに広く掛けておいて、アプリで絞ることはできません。絞る方向のルールは、最初からアプリの側に置く必要があります。
ルールブロックの中には、3種類のリストを書けます。
resource.customizations.ignoreDifferences.apps_Deployment: |
jsonPointers:
- /spec/replicas
jqPathExpressions:
- .spec.template.spec.containers[] | select(.name == "sidecar").image
managedFieldsManagers:
- kubectl
jsonPointersは、スラッシュで降りていくパスです。単純ですが、配列は位置の番号でしか指せないので、コンテナの順序が変わると、見当違いの要素を無視してしまいます。jqPathExpressionsは、条件で選べます。上の例のように「名前がsidecarのコンテナのimage」を指名でき、これはポインターでは安定して書けません。managedFieldsManagersは種類が違います。フィールドのパスではなく、そのフィールドを最後に書いたマネージャーの名前で、無視する対象を選びます。サーバーサイド適用が残した所有の記録を根拠にする方式なので、リソースのYAMLだけを見ても、何が除かれるかを計算できません。プレビューのコマンドが、このリストだけでは何もレンダリングできない理由です。
名前が似ている別のノブがもう1つあります。ignoreResourceUpdatesは、調整ループを起こすかどうかを決めます。アノテーション1つが変わるたびに、コントローラーがアプリ全体を再計算するのを防ぐ、パフォーマンスのノブであり、同期の判定は変えません。名前が似ていてよく混同されますが、目的がまったく違います。
現場での姿
最もよく見る場面はこうです。アプリ10個がすべて黄色で、原因はHPAです。急いでいる人が、グローバルなargocd-cmに、apps_Deploymentの/specをまるごと無視する1行を入れます。画面が静かになり、誰もこの行をもう一度見ません。数か月後、誰かが本番で手でイメージのタグを変えます。Argo CDは相変わらず緑です。リポジトリを信頼できる唯一の情報源と呼ぶシステムが、その日から嘘をつき始めたのに、その事実を知らせる画面がありません。
2つ目は、順序の問題です。サイドカーを無視しようと/spec/template/spec/containers/1を書いたのに、ある日Webhookがサイドカーを前に差し込みます。今度は、無視されるのがアプリケーションのコンテナです。この種のルールは、間違っているというサインを出しません。静かに逆に動作します。
そのため、無視ルールには2つの習慣が必要です。1つ目は、書く前にレンダリングして、消える行を見ることです。2つ目は、ルールを入れた行の横に、そのルールが必要な理由を書くことです。理由がなくなったときにルールを消せるのは、その理由を知っている人だけです。
このラボ環境の限界
ラボのPodには、Argo CDコントローラーがありません。そのため、「ルールを入れたらOutOfSyncがSyncedに変わった」は見られず、managedFieldsManagersが実際にどのフィールドを除くのかも、プレビューでは確認できません。その代わり、ルールを解釈してフィールドを消すそのコードがCLIの中にあるので、どの行が比較から除かれるかは、まったく同じ結果で見られます。
次のラボですること
同じDeployment1枚を材料に、ルールを1つずつ変えながらレンダリングします。ポインターとjq式の違いを自分で見て、/specをまるごと無視したときにイメージの行まで消えることを確認します。マネージャー名のルールとignoreResourceUpdatesがプレビューでどう見えるかも、正直に記録します。最後に、Applicationにアプリごとのルールを載せてkwokクラスターに上げ、「このルールはこの文字を消すか」を表にして、一度に検査します。