イベントがワークフローになるまで、チャートがマニフェストになるまで
一言でいうと
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。