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

CAPA — Argoプロジェクト認定アソシエイト

イベントがワークフローになるまで、チャートがマニフェストになるまで

TT Labで続きを見る

一言でいうと

Argo Eventsは、EventSourceが外部のイベントをCloudEventsに変換してEventBusに載せ、Sensorがそれを依存関係として受け取ってTriggerを実行する、4つの部品で動きます。Argo CDは、Helmをhelm templateでマニフェストを展開(inflate)することにだけ使い、ライフサイクルは自分で管理し、pathにkustomization.yamlがあればKustomizeでレンダリングします。

なぜ必要なのか

「リポジトリにpushされたらパイプラインを実行せよ」、「S3にファイルが来たら処理のワークフローを起動せよ」のような要件は、イベントが先にあり、そのあとに実行が来ます。ワークフローエンジン自体は、イベントを待ち受けません。Argo Eventsは、この前段を担い、20を超えるイベントソース(Webhook、S3、スケジュール、メッセージキュー、GCP PubSub、SNS、SQSなど)からイベントを受け取って、Kubernetesオブジェクト・Argo Workflow・サーバーレスのワークロードを実行します。CAPAのEventsドメイン(12%)は、この4つの構成要素がそれぞれ何を担当し、イベントがどのような順序で流れるかを問います。

Argo CD側の問題は異なります。チームは、HelmチャートやKustomizeオーバーレイでデプロイ成果物を管理しますが、Argo CDがそれをどのようにマニフェストに変換するのかを知らないと、「valuesを変えたのに反映されない」、「アプリがずっとOutOfSyncだ」のような問題の原因を見つけられません。Argo CDドメイン(34%)のHelm & Kustomizeの項目が、この部分です。

どう動くのか

Argo Eventsの4つの部品

構成要素 役割 ドキュメントの定義
EventSource 外部のイベントを受け取り、CloudEventsに変換して、EventBusへ送ります AWS SNS・SQS・PubSub・Webhookなどの外部ソースからイベントを消費する設定
EventBus EventSourceとSensorをつなぐ転送層 NATS(非推奨)、Jetstream、Kafkaの3つの実装
Sensor イベントの依存関係(入力)とトリガー(出力)の集合 EventBusを購読し、依存関係が解決されたらトリガーを実行する、依存関係マネージャー
Trigger 依存関係が解決されたときに実行されるリソース・ワークロード Argo Workflow、K8sオブジェクト、HTTP、Lambda、Kafka/NATSメッセージ、Slack、Argo Rollouts、Logなど

流れは次のとおりです。Webhook EventSourceを作成すると、event-sourceのPodとServiceができ(例は12000ポート)、ここにPOSTすると、イベントがCloudEventsに変換されて、EventBusに載ります。Sensorは、dependenciesに「どのEventSourceのどのイベント」を待つかを書き、triggersに、何を実行するかを書きます。トリガーされたワークフローのログには、イベントのcontext(type、source、eventID、time、subject)と、base64でエンコードされたdataが、一緒に出力されます。パラメーター化(parameterization)で、イベントの特定のキーを取り出して、ワークフローの引数として渡すことができ、トリガーポリシー(policy)で、実行されたオブジェクトの状態を見て、続行するか止めるかを決めます。

EventBusはネームスペースリソースで、EventSourceとSensorが動作するには、そのネームスペースにEventBusがある必要があります。慣例は、defaultという名前で1つ置くことで、別の名前を使ったり、複数置いたりするには、EventSourceとSensorのspecにeventBusNameを書いて、対応を合わせます。ワークフローのロジックがすでにWorkflowTemplateにあれば、Sensorがステップを書き直す必要なく、workflowTemplateRefで参照するWorkflowを提出します。

triggers:
- template:
    name: argo-workflow-trigger
    argoWorkflow:
      operation: submit
      source:
        resource:
          apiVersion: argoproj.io/v1alpha1
          kind: Workflow
          metadata: {generateName: from-template-}
          spec:
            workflowTemplateRef: {name: workflow-template-print-message}

Argo CDとHelm: 展開するだけ

ドキュメントの一文が核心です。「Helmはhelm templateでチャートを展開する用途にだけ使われ、アプリケーションのライフサイクルは、HelmではなくArgo CDが管理する」というものです。Helmリポジトリのチャートは、source.chartとrepoURL、targetRevisionで指定し(OCIはoci://プレフィックスなしで)、Gitにあるチャートは、pathで指定します。valuesを渡す方法は複数あり、優先順位が決まっています。

낮음  valueFiles  →  values  →  valuesObject  →  parameters  높음
      (여러 파일이면 뒤에 적은 파일이 이김)        (차트의 values.yaml 은 그보다 아래)

このコードブロックの韓国語は、左が優先度が低く右が高いこと、複数のファイルの場合は、後ろに書いたファイルが勝つこと、チャートのvalues.yamlは、それよりさらに下であることを述べています。

valueFilesは複数書けて、後ろに書いたファイルが前を上書きします。存在しないファイルがあると、Helmがエラーを出しますが、ignoreMissingValueFiles: trueで無視でき、「デフォルト+あれば上書き」のパターンに使います。glob(envs/*.yaml)は辞書順に展開されるため、00-defaults.yaml、10-region.yamlのように、数字のプレフィックスで順序を示すことが推奨されます。チャートと別のリポジトリのvaluesは、複数ソース(sources[].refと$ref/path)で取得します。parametersは--setに相当し、forceStringで文字列として扱うよう強制でき、fileParametersは--set-fileです。

ドキュメントから、落とし穴を3つ挙げます。1つ目は、リリース名はデフォルトでApplication名と同じで、releaseNameで変えると、Argo CDが追跡用に付けるapp.kubernetes.io/instanceラベルとずれて、セレクターが壊れることがあります。2つ目は、Argo CDは、初回のインストールかアップグレードかを区別できず、すべての操作がsyncであるため、pre-installとpre-upgradeフックが同時に動きます。Argo CDのフックを1つでも定義すると、Helmのフックはすべて無視されます。3つ目は、randAlphaNumで値を生成するチャートは、比較のたびに値が変わるため、常にOutOfSyncになるので、値を固定する必要があります。CRDをチャートがインストールしないようにするには、skipCrds: trueを使います。

Argo CDとKustomize

repoURLとpathが指す場所にkustomization.yamlがあれば、Argo CDはKustomizeでレンダリングします。オーバーレイを使うには、pathをオーバーレイのディレクトリにします。Applicationのsource.kustomizeには、namePrefix、nameSuffix、images(イメージの上書き)、replicas、commonLabels、commonAnnotations、namespace、patches、components(2.10から)などを書けます。patchesは、Kustomizationファイルのpatchesと同じロジックで動作し、既存のpatchesにマージされます。ドキュメントは、ApplicationSetと一緒に使う例を挙げて、クラスターごとにオーバーレイを作る代わりに、テンプレートのkustomize.patchesにジェネレーターの属性({{.name}})を入れて、一度に解決する方法を示しています。リモートのbaseが非公開なら、アプリのリポジトリの認証情報を引き継ぎますが、別の認証情報が必要なリポジトリには、アクセスできません。

source:
  path: kustomize-guestbook
  repoURL: https://github.com/argoproj/argocd-example-apps.git
  targetRevision: master
  kustomize:
    patches:
    - target: {kind: Deployment, name: guestbook-ui}
      patch: |-
        - op: replace
          path: /spec/template/spec/containers/0/ports/0/containerPort
          value: 443

現場での姿

Argo Eventsで最もよくある最初の障害は、「EventSourceとSensorを作ったのにPodが起動しない」です。ドキュメントのトラブルシューティングの手順は、EventSourceとSensorオブジェクトのStatusをまず見て、ServiceAccountのRole/RoleBindingを確認し、2つのコントローラーのログを見ることです。ネームスペースにEventBusがなければ、何も動作しないので、それから確認します。

Argo CDでは、「UIでvaluesがすべて見えない」という問い合わせが来ます。ドキュメントに既知のバグとして書かれていて、UIはparametersだけを表示し、values/valuesObjectで入れた値は表示しません。レンダリングは正確に行われるため、値が抜けているわけではなく、ドキュメントは、ひと目で見えるようにするには、parametersを使うという回避策を示しています。

次のクイズで確認すること

4つの構成要素の役割とEventBusの3つの実装、EventBusがネームスペースリソースであるという点とeventBusName、Helm valuesの優先順位とignoreMissingValueFiles、releaseNameを変えるときのラベルの問題、フックとrandAlphaNumの落とし穴、Kustomizeの検出条件とkustomize.patchesを問います。参考: Argo Events Architecture、EventBus、Sensor、Argo CD Helm、Argo CD Kustomize。