9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Argo Events と Workflow の連携

Last updated at Posted at 2020-07-27

Argo Events と Workflow の連携

Argo Eventは、GitHub への git push によって発信される WebHook を受けて、Argo Workflow などへアクションを実行することができる。その連携について検証してみる。

アルゴイベントのアーキテクチャは以下のようになる。ゲートウェイとセンサーのコントローラーからなり、これらのコントローラーに、イベント源に対応したイベントソース、ゲートウェイ、センサーの3つのマニフェストを適応する。そうすることで、対応するポッドを起動する。 ゲートウェイコントローラーによって起動されるポッドでイベントを受ける。その後、ゲートウェイは Cloud Events の形式に変換して、センサーコントローラーから起動されるポットへイベントが伝達され、そのテンプレートに記述されたスペックで、Argoワークフローが開始する。

screenshot-argo-events.png

ワークフローとイベントを分離することで、イベントを様々な処理に繋ぐことができるので、無限に拡張することができる。

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:' を追加する。 これによって、リソース対象にファイルに、名前空間の指定があった場合、自動的に置き換えてくれる。

kustomization.yaml
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 ディレクトリに追加して、accesskeysecretkey にセットする。

icos-cred.yaml
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は以下の項目は、上記でシークレットに保存するので、変更してはいけない。

artifact-repositories-configmap.yaml
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 がある。これは接続を許すクライアントのリストを設定するもので、これが無いとサーバーに接続できないので注意だ。

postgresql-cluster.yaml
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の認証情報をシークレットに保存するマニフェストを作成する。

postgresql-cred.yaml
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行を加える。

kustomization.yaml
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をサブミットして結果を確認する。もし、この時点で問題があれば解決しておく。

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 は、特に修正する必要はない。

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なので、必要に応じて修正する。

gateways/webhook.yaml
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 である。

sensors/webhook.yaml
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/ から 実行結果を確認することができる。

screenshot-argo-wf.png

以下はオブジェクトストレージに保存された実行結果である。

 _________________________________________ 
/ {"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環境へのデプロイなどを検証してみたい。

9
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?