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

GitOpsとArgo CD

緑ランプなのに根拠を誰も知らない — ヘルス判定を自分で書く

TT Labで続きを見る

目標

argocd-cmのresource.customizations.health.<그룹>_<종류>にLuaのルールを書いて、CRDのヘルスをHealthy・Progressing・Degraded・Suspendedの4つの欄に分け、サンプルと期待値を表にまとめて回帰チェックします(プレースホルダーは、順にグループと種類です)。

なぜ重要なのか

Argo CDの画面で人が実際に見ているのは、同期ではなくヘルスです。Deployment・Service・Jobのような組み込みの種類は、コントローラーが自動で判定しますが、CRDには組み込みのルールがありません。Operatorが作るリソースが画面でいつも同じ色に見えるなら、それはうまくいっているという意味ではなく、判定する根拠がないという意味です。ルールを自分で書くことが重要な理由は2つです。1つ目は、まだ作られている途中のものと、すでに壊れているものを分けて初めて、アラートを設定できることです。2つ目は、ルールは一度書くと忘れられるコードなので、サンプルと期待値を一緒にリポジトリに置いておかないと、あとでstatusフィールドが変わったときに、静かに間違うことです。

ステップ

  1. /root/ga-health/argocd-cm.yamlをdata: {}の空のargocd-cm ConfigMapとして作り、/root/ga-health/deploy.yamlにga-healthネームスペースのDeploymentwebを置いてください。spec.replicasは3で、statusにはobservedGeneration: 1、replicas: 3、updatedReplicas: 2、readyReplicas: 1、availableReplicas: 1を書きます。argocd admin settings resource-overrides health /root/ga-health/deploy.yaml --argocd-cm-path /root/ga-health/argocd-cm.yamlの出力を、/root/ga-health/builtin.txtに保存してください。
  2. /root/ga-health/w-ready.yamlにexample.com/v1のWidgetを作ってください。名前はw-ready、ネームスペースはga-health、spec.sizeは3、status.phaseはReadyです。ステップ1の空のargocd-cmで、このファイルのヘルスを尋ねて、出力を/root/ga-health/nocustom.txtに保存してください。
  3. /root/ga-health/argocd-cm-healthy.yamlにキーresource.customizations.health.example.com_Widgetを置いて、status.phaseがReadyならHealthyを、それ以外はProgressingを返すLuaを書いてください。どちらの場合もhs.messageを埋めます。/root/ga-health/w-ready.yamlをこのConfigMapで判定した出力を、/root/ga-health/healthy.txtに保存してください。
  4. /root/ga-health/w-failed.yamlを作ってください。名前はw-failed、status.phaseはFailed、status.reasonはDiskFullです。/root/ga-health/argocd-cm-degraded.yamlは、ステップ3のルールにFailedの分岐を加えて、Degradedを返すようにしてください。ただし、hs.messageの中に、そのリソースのstatus.reasonの値が入る必要があります。判定の出力を/root/ga-health/degraded.txtに保存してください。
  5. /root/ga-health/w-building.yaml(status.phaseがBuilding、名前w-building)と、/root/ga-health/w-nostatus.yaml(status自体がない、名前w-nostatus)を作ってください。ステップ4のConfigMapで、2つを順に判定して、出力を/root/ga-health/progressing.txtに追記してください。どちらもProgressingである必要があります。
  6. /root/ga-health/w-paused.yamlを作ってください。名前はw-paused、spec.pausedはtrue、status.phaseはReadyです。/root/ga-health/argocd-cm-full.yamlは、前のルールに分岐を1つ加えて、spec.pausedが真ならほかの条件より先にSuspendedを返す必要があります。判定の出力を/root/ga-health/suspended.txtに保存してください。
  7. /root/ga-health/argocd-cm-typo.yamlを作ってください。ステップ6と内容は同じですが、キー名だけをresource.customizations.health.example.com_Widgets(種類を複数形に)にします。このConfigMapで/root/ga-health/w-ready.yamlを判定した出力を、/root/ga-health/typo.txtに保存してください。
  8. /root/ga-health/health-matrix.tsvに<샘플파일이름>\t<기대 STATUS>を4行以上書いてください。Healthy・Degraded・Progressing・Suspendedが、すべて1回以上出る必要があります。/root/ga-health/check-health.shは、この表を読んで/root/ga-health/argocd-cm-full.yamlで各サンプルを判定し、合っていればOK …、違っていればMISMATCH …を標準出力にだけ出力して、1行でも違えば0以外のコードで終了する必要があります。その出力を/root/ga-health/health-result.txtに保存してください(プレースホルダーは、順にサンプルファイル名と期待するSTATUSです)。

参考

まず組み込みの判定を見る

/root/ga-health/argocd-cm.yamlをdata: {}の空のargocd-cm ConfigMapとして作り、/root/ga-health/deploy.yamlにga-healthネームスペースのDeploymentwebを置いてください。spec.replicasは3で、statusにはobservedGeneration: 1、replicas: 3、updatedReplicas: 2、readyReplicas: 1、availableReplicas: 1を書きます。argocd admin settings resource-overrides health /root/ga-health/deploy.yaml --argocd-cm-path /root/ga-health/argocd-cm.yamlの出力を、/root/ga-health/builtin.txtに保存してください。

Deploymentには組み込みのヘルスルールがあるので、argocd-cmが空でも判定が出ます。3つを望んでいるのに、1つしか準備できていないので、どんな状態で出るか予想してみてください。出力の最初の行がSTATUSです。

CRDにはルールがそもそもない

/root/ga-health/w-ready.yamlにexample.com/v1のWidgetを作ってください。名前はw-ready、ネームスペースはga-health、spec.sizeは3、status.phaseはReadyです。ステップ1の空のargocd-cmで、このファイルのヘルスを尋ねて、出力を/root/ga-health/nocustom.txtに保存してください。

Argo CDは、自分が知らない種類について、判定をでっち上げません。画面では、こうしたリソースはたいてい緑に見えますが、実際には「判定する根拠がない」という意味です。出力の文をそのまま読んでみてください。

緑の条件をLuaで書く

/root/ga-health/argocd-cm-healthy.yamlにキーresource.customizations.health.example.com_Widgetを置いて、status.phaseがReadyならHealthyを、それ以外はProgressingを返すLuaを書いてください。どちらの場合もhs.messageを埋めます。/root/ga-health/w-ready.yamlをこのConfigMapで判定した出力を、/root/ga-health/healthy.txtに保存してください。

Luaの断片は、objというグローバル変数でリソースを受け取り、hs.statusとhs.messageを埋めたテーブルをreturnします。statusがまったくないリソースも入ってくるので、obj.status ~= nilを先に確認してください。キー名の区切り文字は、ドットではなくアンダースコアです。<그룹>_<종류>です(プレースホルダーは、順にグループと種類です)。

赤信号には理由も一緒に出る必要がある

/root/ga-health/w-failed.yamlを作ってください。名前はw-failed、status.phaseはFailed、status.reasonはDiskFullです。/root/ga-health/argocd-cm-degraded.yamlは、ステップ3のルールにFailedの分岐を加えて、Degradedを返すようにしてください。ただし、hs.messageの中に、そのリソースのstatus.reasonの値が入る必要があります。判定の出力を/root/ga-health/degraded.txtに保存してください。

メッセージを固定文字列で書くと、どのリソースがなぜ落ちたのか、画面でわかりません。Luaの文字列の連結は..で、値がない場合もあるので、(obj.status.reason or "unknown")のようにデフォルト値を置きます。

知らない状態と状態がないものは、同じ欄に送る

/root/ga-health/w-building.yaml(status.phaseがBuilding、名前w-building)と、/root/ga-health/w-nostatus.yaml(status自体がない、名前w-nostatus)を作ってください。ステップ4のConfigMapで、2つを順に判定して、出力を/root/ga-health/progressing.txtに追記してください。どちらもProgressingである必要があります。

ルールを書くときに抜かしやすいのが、「まだコントローラーがstatusを書いていない瞬間」です。このときDegradedを出すと、新しく作ったリソースが毎回赤信号で始まります。デフォルトの分岐をProgressingにしておく理由です。

わざと止めておいたものは故障ではない

/root/ga-health/w-paused.yamlを作ってください。名前はw-paused、spec.pausedはtrue、status.phaseはReadyです。/root/ga-health/argocd-cm-full.yamlは、前のルールに分岐を1つ加えて、spec.pausedが真ならほかの条件より先にSuspendedを返す必要があります。判定の出力を/root/ga-health/suspended.txtに保存してください。

Suspendedは、Argo CDが知っている4番目のヘルス状態です。人がわざと止めておいたものなので、アラートを鳴らしてはいけない場所です。分岐の順序を入れ替えてみれば、なぜ一番前でなければならないかがすぐにわかります(phaseがReadyなので、緑のほうが先に当てはまります)。

キー名を1文字間違えると、ルールがまるごと消える

/root/ga-health/argocd-cm-typo.yamlを作ってください。ステップ6と内容は同じですが、キー名だけをresource.customizations.health.example.com_Widgets(種類を複数形に)にします。このConfigMapで/root/ga-health/w-ready.yamlを判定した出力を、/root/ga-health/typo.txtに保存してください。

キー名の種類は、マニフェストのkindと文字どおり同じである必要があります。間違えるとエラーは出ず、単にルールがないかのように動作します。このようなミスは、画面を見て初めてわかります。ステップ2の出力と比べてみてください。

サンプルと期待値を表にまとめて、ルールを回帰チェックする

/root/ga-health/health-matrix.tsvに<샘플파일이름>\t<기대 STATUS>を4行以上書いてください。Healthy・Degraded・Progressing・Suspendedが、すべて1回以上出る必要があります。/root/ga-health/check-health.shは、この表を読んで/root/ga-health/argocd-cm-full.yamlで各サンプルを判定し、合っていればOK …、違っていればMISMATCH …を標準出力にだけ出力して、1行でも違えば0以外のコードで終了する必要があります。その出力を/root/ga-health/health-result.txtに保存してください(プレースホルダーは、順にサンプルファイル名と期待するSTATUSです)。

サンプルファイルの名前だけを書いて、パスはスクリプトが付ければ、表が短くなります。STATUSの1行だけを取り出すなら、sed -n 's/^STATUS: //p'が楽です。スクリプトがファイルを直接書くと、採点ツールが再実行するときに学習者の成果物を上書きするので、標準出力にだけ出してください。