TT Lab
はじめる
学ぶ 学習パス コース

GitOpsとArgo CD

比較から何を外すか

TT Labで続きを見る

一言でいうと

無視ルールは、同期の判定から特定のフィールドを除く仕組みです。広く使うと、ノイズと一緒に本物のドリフトも消えてしまうので、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クラスターに上げ、「このルールはこの文字を消すか」を表にして、一度に検査します。