Kubernetes native なワークフローエンジン Argo workflow を動かす

Argo workflow は Cloud Native Computing Foundation にホストされている Kubernetes native なワークフローエンジンです。

github.com

Kubeflow でも機械学習のパイプラインエンジンとして使用されています。

blog.kondoumh.com

公式の manifest でインストールできます。

https://github.com/argoproj/argo-workflows/tree/master/manifests

Helm charts もコミュニティベースでメンテナンスされています。

argo-helm/charts/argo at master · argoproj/argo-helm · GitHub

今回は Docker Desktop の Kubernetes 環境に argo namespace を作成して quick-start 用の manifest を適用してみました。

$ kubectl create namespace argo
$ kubectl apply -n argo -f https://raw.githubusercontent.com/argoproj/argo-workflows/stable/manifests/quick-start-postgres.yaml

argo-server と workflow-controller が起動し、ストレージ用の minio と DB サーバ postgres も起動されました。

$ kubectl get po,deploy,svc -n argo            
NAME                                      READY   STATUS    RESTARTS   AGE
pod/argo-server-5b86d9f84b-vjhhq          1/1     Running   4          23m
pod/minio-58977b4b48-ts9zn                1/1     Running   0          23m
pod/postgres-6b5c55f477-ss24g             1/1     Running   0          23m
pod/workflow-controller-d9cbfcc86-jkf8j   1/1     Running   2          23m

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/argo-server           1/1     1            1           23m
deployment.apps/minio                 1/1     1            1           23m
deployment.apps/postgres              1/1     1            1           23m
deployment.apps/workflow-controller   1/1     1            1           23m

NAME                                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/argo-server                   ClusterIP   10.106.203.74   <none>        2746/TCP   23m
service/minio                         ClusterIP   10.96.161.227   <none>        9000/TCP   23m
service/postgres                      ClusterIP   10.98.163.40    <none>        5432/TCP   23m
service/workflow-controller-metrics   ClusterIP   10.102.138.81   <none>        9090/TCP   23m

CRD もインストールされました。

$ kubectl get crd | grep argo
NAME                                   CREATED AT
clusterworkflowtemplates.argoproj.io   2021-05-06T03:32:28Z
cronworkflows.argoproj.io              2021-05-06T03:32:28Z
workfloweventbindings.argoproj.io      2021-05-06T03:32:28Z
workflows.argoproj.io                  2021-05-06T03:32:28Z
workflowtemplates.argoproj.io          2021-05-06T03:32:28Z

Argo Server の Web UI を使うために port-forward します。

kubectl -n argo port-forward deployment/argo-server 2746:2746

Chrome で https://localhost:2746 に接続すると NET::ERR_CERT_INVALID と自己証明書のエラーで接続できないので、thisisunsafe の呪文をタイプして接続しました。

f:id:kondoumh:20210507083016p:plain

まだワークフローは何も登録されていない状態です。

Argo workflow は kubectl コマンドでも操作できますが、Argo CLI に便利コマンドが用意されているのでインストールします。

$ curl -sLO https://github.com/argoproj/argo/releases/download/v3.0.2/argo-linux-amd64.gz
$ gunzip argo-linux-amd64.gz
$ chmod +x argo-linux-amd64
$ mv ./argo-linux-amd64 /usr/local/bin/argo

サンプルワークフローをデプロイしてみます。hello-world- というプレフィクス付きのワークフローを生成します。whalesay という template が定義されており、コンテナイメージ whalesay を起動して cowsay コマンドを叩くものです。メモリと CPU リソースの limit も指定しています。この template を entrypoint に指定することで起動します。

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: hello-world-
  labels:
    workflows.argoproj.io/archive-strategy: "false"
spec:
  entrypoint: whalesay
  templates:
  - name: whalesay
    container:
      image: docker/whalesay:latest
      command: [cowsay]
      args: ["hello world"]
      resources:
        limits:
          memory: 32Mi
          cpu: 100m
$ argo submit -n argo --watch https://raw.githubusercontent.com/argoproj/argo-workflows/master/examples/hello-world.yaml

Name:                hello-world-mg6x7
Namespace:           argo
ServiceAccount:      default
Status:              Succeeded
Conditions:          
 PodRunning          False
 Completed           True
Created:             Tue May 11 12:27:50 +0900 (1 minute ago)
Started:             Tue May 11 12:27:50 +0900 (1 minute ago)
Finished:            Tue May 11 12:29:25 +0900 (now)
Duration:            1 minute 35 seconds
Progress:            1/1
ResourcesDuration:   35s*(100Mi memory),35s*(1 cpu)

STEP                  TEMPLATE  PODNAME            DURATION  MESSAGE
 ✔ hello-world-mg6x7  whalesay  hello-world-mg6x7  1m 

1分ほどでコンテナ作成から実行までが完了しました。

最新のジョブの状態やログを Argo CLI で確認できます。

$ argo list -n argo @latest
NAME                STATUS      AGE   DURATION   PRIORITY
hello-world-mg6x7   Succeeded   23m   1m         0

$ argo logs -n argo @latest
hello-world-mg6x7:  _____________ 
hello-world-mg6x7: < hello world >
hello-world-mg6x7:  ------------- 
hello-world-mg6x7:     \
hello-world-mg6x7:      \
hello-world-mg6x7:       \     
hello-world-mg6x7:                     ##        .            
hello-world-mg6x7:               ## ## ##       ==            
hello-world-mg6x7:            ## ## ## ##      ===            
hello-world-mg6x7:        /""""""""""""""""___/ ===        
hello-world-mg6x7:   ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~   
hello-world-mg6x7:        \______ o          __/            
hello-world-mg6x7:         \    \        __/             
hello-world-mg6x7:           \____\______/

もちろん Web UI でも結果を閲覧できます。

f:id:kondoumh:20210511123323p:plain

f:id:kondoumh:20210511123343p:plain

ジョブの詳細画面からログ出力を確認できます。

f:id:kondoumh:20210511124600p:plain

f:id:kondoumh:20210511124623p:plain

タスクの依存関係を dependencies で指定するサンプルです。

# The following workflow executes a diamond workflow
# 
#   A
#  / \
# B   C
#  \ /
#   D
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: dag-diamond-
spec:
  entrypoint: diamond
  templates:
  - name: diamond
    dag:
      tasks:
      - name: A
        template: echo
        arguments:
          parameters: [{name: message, value: A}]
      - name: B
        dependencies: [A]
        template: echo
        arguments:
          parameters: [{name: message, value: B}]
      - name: C
        dependencies: [A]
        template: echo
        arguments:
          parameters: [{name: message, value: C}]
      - name: D
        dependencies: [B, C]
        template: echo
        arguments:
          parameters: [{name: message, value: D}]

  - name: echo
    inputs:
      parameters:
      - name: message
    container:
      image: alpine:3.7
      command: [echo, "{{inputs.parameters.message}}"]

CLI の実行結果

 ✔ dag-diamond-vqswz  diamond                                             
 ├─✔ A                echo      dag-diamond-vqswz-4245884217  16s         
 ├─✔ B                echo      dag-diamond-vqswz-4195551360  6s          
 ├─✔ C                echo      dag-diamond-vqswz-4212328979  6s          
 └─✔ D                echo      dag-diamond-vqswz-1249778     5s 

Web UI での表示

f:id:kondoumh:20210515083827p:plain

以上、ローカルでの Argo 環境構築と動作確認でした。