Argo Events と Workflow の連携
Argo Eventは、GitHub への git push によって発信される WebHook を受けて、Argo Workflow などへアクションを実行することができる。その連携について検証してみる。
アルゴイベントのアーキテクチャは以下のようになる。ゲートウェイとセンサーのコントローラーからなり、これらのコントローラーに、イベント源に対応したイベントソース、ゲートウェイ、センサーの3つのマニフェストを適応する。そうすることで、対応するポッドを起動する。 ゲートウェイコントローラーによって起動されるポッドでイベントを受ける。その後、ゲートウェイは Cloud Events の形式に変換して、センサーコントローラーから起動されるポットへイベントが伝達され、そのテンプレートに記述されたスペックで、Argoワークフローが開始する。
ワークフローとイベントを分離することで、イベントを様々な処理に繋ぐことができるので、無限に拡張することができる。
Argo Event のインストール
Argo Event の設定変更を簡単にできるように、ローカル環境にクローンしておいて、インストールを実施する。インストールして実行できるリリースのコミットはタグに登録されている。そこで、-b stable
を指定してクローンする。
このオプションを設定しないで、クローンもできるが、そうすると、開発途上の最新コードが落ちてくるので、動かないことも多々なので、開発に参加する人以外は、オプションの設定をお勧めする。
$ git clone -b stable https://github.com/argoproj/argo-events
名前空間 argo-events を設定してインストールを実施する。名前空間に閉じて利用するパターンと、Kubernetesクラスタ ワイドにインストールするパターンを選択できる。ここではクラスタワイドに使用可能なパターンでインストールする。
$ kubectl create ns argo-events
$ kubectl apply -f install.yaml -n argo-events
しばらくすると、二つのコントローラーが起動する。これで Argo Event を利用するためのインストールは完了だけど、これだけでは動かない。これからが長いので頑張ろう!
$ kubectl get pod -n argo-events
NAME READY STATUS RESTARTS AGE
gateway-controller-7b88d47999-b5rwv 1/1 Running 0 2m7s
sensor-controller-6df5cd5d86-svvq5 1/1 Running 0 2m7s
Argo Event は、Gatwayで イベント源からの何らかなの通知を受け取り、Cloud Event 形式に変換、Sensor で実行をリクエストするのが役割だ。そのため、実行をリクエストする部分がセンサーというのは違和感を感じる。今回は Argo workflow と連携させる。
Argo workflow のインストール
Argo workflow のインストールは、過去二つの記事を書いた。一つ目の記事は、Docker CE をコンテナランタイムに持つ Kubernetesクラスタの上で動かすもので、執筆時点では、この構成がArgo workflowのフル機能が使える。しかし、containerd や cri-o がコンテナランタイムの主流となっている現在は、それでは本番システムで使えないので、2番目の記事を書いた。今回は2番目の記事をベースに、Argo Events と Argo Workflow を連携させる。
そこで、PostgreSQLサーバーとオブジェクトストレージが必要になる。 PostgreSQLはオペレーターを利用して起動し、オブジェクトストレージは AWS S3 または IBM Cloud オブジェクトストレージを利用する。
Postgres オペレータを利用した PostgresSQLのサービス環境構築
最初に、Postgres専用の名前空間(namespace)を作成しておく。
$ kubectl create ns postgres
オペレータハブに登録されているデータベースのオペレーターから、Postgres-Operatorを利用することにした。
どれが一番良いか解らないので、他のオペレーターを試した人は、是非、コメント蘭に使用報告を入れてもらえるとありがたい。
$ git clone https://github.com/zalando/postgres-operator
PostgresSQLは、専用の名前空間 postgres で管理したいので、オペレーターのマニフェストに変更を加える。そのためにマニフェストのあるディレクトリへ移動する。
$ cd postgres-operator/manifests
名前空間(Namespace)を変更を自動化するために、kustomization.yamlに変更を加える。
リソース(resources)の次に 'namespace:' を追加する。 これによって、リソース対象にファイルに、名前空間の指定があった場合、自動的に置き換えてくれる。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- configmap.yaml
- operator-service-account-rbac.yaml
- postgres-operator.yaml
- api-service.yaml
namespace: postgres
Kustomization APIを利用するために -k
でデプロイする。 ほんとに Kustomizeation は便利で良いね。
$ kubectl create -k .
デプロイ後の実行状態を確認しておく。これも -k
オプションを利用する。
maho:manifests maho$ kubectl get -k .
NAME SECRETS AGE
serviceaccount/postgres-operator 1 37s
NAME AGE
clusterrole.rbac.authorization.k8s.io/postgres-operator 38s
clusterrole.rbac.authorization.k8s.io/postgres-pod 38s
NAME AGE
clusterrolebinding.rbac.authorization.k8s.io/postgres-operator 38s
NAME DATA AGE
configmap/postgres-operator 39 38s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/postgres-operator ClusterIP 172.21.130.241 <none> 8080/TCP 38s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/postgres-operator 1/1 1 1 38s
以上で PostgreSQL をサービスのように利用できるオペレーターの環境ができた。
データベースインスタンスの作成は、Argo workflow のインスタンス起動と合わせて実施する。
kubectl デフォルトのコンテキストの変更
名前空間 argo-events をデフォルトにするために、コンテキスト argo-events を設定する。
$ kubectl config get-contexts | grep `kubectl config current-context`
* default k8s-vpc-jp/brvsrolt0sihofiav90g takara@jp.ibm.com/753c62201245d3d333a3033556c66d71/iam.cloud.ibm.com-identity default
$ kubectl config set-context argo-events --namespace=argo-events --cluster=k8s-vpc-jp/brvsrolt0sihofiav90g --user=takara@jp.ibm.com/753c62201245d3d333a3033556c66d71/iam.cloud.ibm.com-identity
これで use-context
でデフォルトを切り替えられる。
$ kubectl config use-context argo-events
$ kubectl config current-context
argo-events
Argo Workflow のマニフェスト取得
Arog Workflow の動作する名前空間を argo から argo-events に変更すること、Kubernetes クラスタ内の PostgreSQL と接続すること、クラウドのオブジェクトストレージに結果を保存することから、インストールするマニフェストを変更する。そのため、Argo Workflow リリース v2.9.3 のコードをクローンして編集するが、この記事で紹介するのは大変なので、編集済のコードをGitHubに登録しておいた。
$ git clone -b v2.9.3 https://github.com/argoproj/argo
そして、このソースツリーの中かから argo/manifests/quick-start-postgres.yaml
を元にして、作成したマニフェスト https://github.com/takara9/argo-workflow を使用する。
$ git clone https://github.com/takara9/argo-workflow
この中から、icos-cred.yaml と postgresql-cred.yaml を作成して、kubectl apply -k .
コマンドでデプロイする。
オブジェクトストレージの設定
クラウドで、オブジェクトストレージを作成して、パブリックのエンドポイント、バケット、アクセスキー、シークレットキーを取得する。
次のYAMLファイルを argo-workflow ディレクトリに追加して、accesskey
と secretkey
にセットする。
apiVersion: v1
kind: Secret
metadata:
labels:
app: argo
name: my-icos-cred
stringData:
accesskey: 20a**************************139
secretkey: 090******************************************b12
type: Opaque
オブジェクトストレージのバケットとエンドポイントを artifact-repositories-configmap.yaml に設定する。acceessKerySecretは以下の項目は、上記でシークレットに保存するので、変更してはいけない。
apiVersion: v1
kind: ConfigMap
metadata:
name: artifact-repositories
data:
minio: |
s3:
endpoint: s3.jp-tok.cloud-object-storage.appdomain.cloud <--- エンドポイントURL
bucket: argo-workflow-artifacts <-- バケット名
insecure: false
accessKeySecret:
name: my-icos-cred
key: accesskey
secretKeySecret:
name: my-icos-cred
key: secretkey
データベースの設定
オペレーターPostgres-Operatorに指示を与え、PostgreSQLのサーバーを起動するためのマニフェストを作成する。このファイルは argo-workflowのディレクトリに postgresql-cluster.yamlとして作成する。
これを適用することで、二つのインスタンスと対応する永続ボリュームがプロビジョニングされるので、永続ボリュームの利用料金が発生するので注意して欲しい。このマニフェストのポイントとして、patroni
というキーの項目下にある pg_hba
がある。これは接続を許すクライアントのリストを設定するもので、これが無いとサーバーに接続できないので注意だ。
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
name: postgresql-cluster
spec:
databases:
argodb: argo
numberOfInstances: 2
postgresql:
version: '11'
teamId: POSTGRESQL
users:
argodb_user: []
argo:
- superuser
- createdb
volume:
size: 5Gi
patroni:
pg_hba:
- host all all 0.0.0.0/0 md5
編集が終わったら適用する。
$ vi postgresql-cluster.yaml
$ k apply -f postgresql-cluster.yaml -n postgres
しばらくすると、PostgreSQLサーバーのポッドが起動する。
$ k get pod -n postgres
NAME READY STATUS RESTARTS AGE
postgres-operator-85978df8cf-xjvkf 1/1 Running 0 7m15s
postgresql-cluster-0 1/1 Running 0 4m9s
postgresql-cluster-1 1/1 Running 0 2m5s
パスワードは、以下の方法で取得できるので、メモっておく。
$ export PGPASSWORD=$(kubectl get secret -n postgres postgres.postgresql-cluster.credentials -o 'jsonpath={.data.password}' | base64 -d)
$ echo $PGPASSWORD
hlqEyuVdlGi7fh096MUp84Oe9qgy0U56ptodyjFLKRhuhXv2PmeOjuf2mbxXJGld
次に PostgreSQLの認証情報をシークレットに保存するマニフェストを作成する。
apiVersion: v1
kind: Secret
metadata:
name: argo-postgres-config
labels:
app: argo
stringData:
username: postgres
password: hlqEyuVdlGi7fh096MUp84Oe9qgy0U56ptodyjFLKRhuhXv2PmeOjuf2mbxXJGld
type: Opaque
Argo Workflow のインストールと起動
git clone https://github.com/takara9/argo-workflow
で作成されたディレクトリの kustomization.yaml に変更を加えて適用する。変更箇所は namespace:
の値で、今回は名前空間 argo-events
にデプロイするので、下記のように1行を加える。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- workflow-controller-configmap.yaml
- artifact-repositories-configmap.yaml
- ServiceAccount_RBAC.yaml
- icos-cred.yaml
- postgresql-cred.yaml
- CustomResourceDefinition.yaml
- argo-server.yaml
- workflow-controller-metrics.yaml
namespace: argo-events
以下のコマンドで適用する。しばらくすると、argoサーバーとworkflowコントローラーが起動する。
$ kubectl apply -k .
$ kubectl get po -w
NAME READY STATUS RESTARTS AGE
argo-server-7d7644fbd8-9vwjq 0/1 Running 0 6s
gateway-controller-7b88d47999-b5rwv 1/1 Running 0 67m
sensor-controller-6df5cd5d86-svvq5 1/1 Running 0 67m
workflow-controller-9ddc4456d-54bww 1/1 Running 0 6s
Agro Workflow ウェブ画面の起動
上記のArgoサーバーのポッドのポート番号を指定して、プロキシを設定する。 本格的に動かす場合は、Ingress などの設定や認証を加えると良い。
$ kubectl -n argo-events port-forward argo-server-7d7644fbd8-9vwjq 2746:2746
Forwarding from 127.0.0.1:2746 -> 2746
Forwarding from [::1]:2746 -> 2746
これでhttp://localhost:2746/
で Argo workflow のコンソールが起動される。動作確認として、hello-world.yamlをサブミットして結果を確認する。もし、この時点で問題があれば解決しておく。
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: hello-world-
namespace: argo-events
spec:
entrypoint: whalesay
templates:
- name: whalesay
container:
image: 'docker/whalesay:latest'
command:
- cowsay
args:
- hello world
Argo Eventの動作テスト
Argo Eventで Webhook のイベントを受けて、Argo workflow へコードの実行をリクエストするには、次の3つのマニフェストを提供する必要がある。このマニフェストは argo-events/examples
にある。
kubectl apply -f examples/event-sources/webhook.yaml
kubectl apply -f examples/gateways/webhook.yaml
kubectl apply -f examples/sensors/webhook.yaml
イベントソースには、エンドポイントのディレクトリとポート番号、HTTPリクエストを指定する。今回、event-sources/webhook.yaml は、特に修正する必要はない。
apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
name: webhook-event-source
spec:
type: webhook
webhook:
# gatewayは複数のHTTPサーバーを動作できる。
example:
# ポート 120000 で起動する
port: "12000"
# エンドポイントは /example に設定する
endpoint: /example
# 許可されるHTTP リクエスト
method: POST
イベントソースで受けたリクエストはセンサーのURLへ中継する。この理由は Cloud Event に変換して、センサーへ渡すためである。このYAMLの最終行にセンサーのURLがある。名前空間を含むURLなので、必要に応じて修正する。
apiVersion: argoproj.io/v1alpha1
kind: Gateway
metadata:
name: webhook
spec:
replica: 1
type: webhook
eventSourceRef:
name: webhook-event-source
template:
serviceAccountName: argo-events-sa
service:
ports:
- port: 12000
targetPort: 12000
subscribers:
http:
- "http://webhook-sensor.argo-events.svc:9300/"
次のマニフェストの中で、Argo Workflow にポッドを起動する時のサービスアカウントを変更する必要がある。無修正で argo-events-sa で実行した場合、ログを書き込めないため、ワークフローが失敗する。そこで、argo workflow で使用しているサービスアカウント default に変更する。 変更箇所は template の k8s/source/spec/templates/[0]/name/serviceAccountName: default
である。
apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
name: webhook
spec:
template:
serviceAccountName: argo-events-sa
dependencies:
- name: test-dep
gatewayName: webhook
eventName: example
subscription:
http:
port: 9300
triggers:
- template:
name: webhook-workflow-trigger
k8s:
group: argoproj.io
version: v1alpha1
resource: workflows
operation: create
source:
resource:
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: webhook-
spec:
entrypoint: whalesay
arguments:
parameters:
- name: message
# the value will get overridden by event payload from test-dep
value: hello world
templates:
- name: whalesay
serviceAccountName: default # <--- このサービスアカウントをdefaultに変更
inputs:
parameters:
- name: message
container:
image: docker/whalesay:latest
command: [cowsay]
args: ["{{inputs.parameters.message}}"]
parameters:
- src:
dependencyName: test-dep
dest: spec.arguments.parameters.0.value
この3つのマニフェストを適用すると、webhook-
から始まる二つのポッドが起動する。
$ kubectl get po -w
NAME READY STATUS RESTARTS AGE
argo-server-7d7644fbd8-9vwjq 1/1 Running 0 10m
gateway-controller-7b88d47999-b5rwv 1/1 Running 0 77m
hello-world-fg4ls 0/2 Completed 0 3m8s
sensor-controller-6df5cd5d86-svvq5 1/1 Running 0 77m
webhook-gateway-s86m5-78cc89b7f-b9n5v 2/2 Running 1 20s
webhook-sensor-prlq4-7875b484b6-4x74q 1/1 Running 0 19s
workflow-controller-9ddc4456d-54bww 1/1 Running 0 10m
このポッドにプロキシーを設定する。
kubectl -n argo-events port-forward webhook-gateway-s86m5-78cc89b7f-b9n5v 12000:12000
このアドレスに、curlでポストする。
curl -d '{"message":"this is my first webhook"}' -H "Content-Type: application/json" -X POST http://localhost:12000/example
$ kubeclt get wf
NAME STATUS AGE
webhook-7dgnq Succeeded 15m
Argo workflow のコンソール http://localhost:2746/
から 実行結果を確認することができる。
以下はオブジェクトストレージに保存された実行結果である。
_________________________________________
/ {"context":{"id":"39373962623637332d663 \
| 739352d346362632d386332332d616136653364 |
| 333138336230","source":"webhook","specv |
| ersion":"0.3","type":"webhook","dataCon |
| tentType":"application/json","subject": |
| "example","time":"2020-07-22T14:07:37Z" |
| },"data":"eyJoZWFkZXIiOnsiQWNjZXB0IjpbI |
| iovKiJdLCJDb250ZW50LUxlbmd0aCI6WyIzOCJd |
| LCJDb250ZW50LVR5cGUiOlsiYXBwbGljYXRpb24 |
| vanNvbiJdLCJVc2VyLUFnZW50IjpbImN1cmwvNy |
| 42NC4xIl19LCJib2R5Ijp7Im1lc3NhZ2UiOiJ0a |
\ GlzIGlzIG15IGZpcnN0IHdlYmhvb2sifX0="} /
-----------------------------------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
まとめ
アルゴイベントとワークフローを連携させて動作させることに成功した。
本記事では、プロキシー設定でアルゴワークフローの画面を表示して、WebHookを受ける部分もプロキシーで代用した。本格的に動作させるには、アルゴワークフローのWebコンソールは、IngressやLoadBalancerを利用するのが良い。そして、アルゴワークフローの認証機能を有効化して併用するのが良いと思われる。また、アルゴイベントのイベントソースについても、GitHubと連携するには、TLS暗号が必要となるので、Ingressイングレスを併用して、GitHubからのWebHookを受けると良さそうだ。
次は、DevOpsパイプラインとして、GitHubと連動して、コンテナのビルド、テストKubernetes環境へのデプロイなどを検証してみたい。