sh19910711 / test

:coffee: test
3 stars 0 forks source link

🔥🐙🔥 Argo Workflows #8

Closed sh19910711 closed 1 year ago

sh19910711 commented 1 year ago

これは「気にはなってるけど触ってないビッグデータ系のツール・サービスを触る Advent Calendar 2022」(19日目)の記事です。今回はワークフローエンジン関連でよく見かけるArgo Workflowsを触ってみようかと思います。

アドカレURL https://qiita.com/advent-calendar/2022/bigdata-tools-you-heard-not-used

🐙 Argo Workflows + 考古学

argoproj/argo-workflowsのInitial Commit (2017年10月)を眺めていたところ、ROADMAP.mdというファイルを発掘しました。これによると2015年11月頃には開発をスタートしていたみたいです。初期はApache MesosとRabbitMQを使った構成だったらしく、途中でKubernetesにスイッチしたようでした。

※ ROADMAP.md https://github.com/argoproj/argo-workflows/blob/3ed1dfeb073829d3c4f92b95c9a74118caaec1b4/ROADMAP.md

🐙 2022年のArgo Workflows

https://blog.argoproj.io を眺めて気になったものを並べてみました。ブログにはArgo Workflows以外のArgoファミリー系の記事も色々あるようです。

📝 日本語資料

CloudNative Days Tokyo 2021の発表資料ですが、導入から具体的なワークフローの記述までよくまとまっており参考になりました。

URL: https://speakerdeck.com/makocchi/how-to-use-argo-workflows

導入に関してざっくり箇条書きすると、以下のようになります。

🐙💨 とりあえず動かしてみる

ひとまずスタンドアロンっぽい感じで動かしてみたいなということで、今回はGKE Autopilotを使って、自分で用意したコンテナを走らせるところまでやってみることにしました。利用したArgo WorkflowsとGKEクラスタのバージョンはそれぞれ以下の通りです。

ちなみに日本語圏でのGKE Autopilot + Argo Workflowsの事例は既に何度か見かけているような気がするので、検索してみると他にも情報が見つかるかもしれません。

kubectl applyコマンドでインストールしてみる

まずはargoという名前のnamespaceを作成していきます。

$ kubectl create namespace argo

今回はnamespace-install.yamlのほうをapplyしてみます。他のバージョンを利用したい場合は https://github.com/argoproj/argo-workflows/releases から発掘しましょう。CLIのバイナリなどもこちらにあるようです。

$ kubectl apply -n argo -f https://github.com/argoproj/argo-workflows/releases/download/v3.4.4/namespace-install.yaml

kubectl applyコマンドを実行すると、デプロイメントだけではなくリソース定義やサービスアカウントなども作成され、2分半ほどでpodがRunningの状態に遷移しました。

$ kubectl get -n argo pods 
NAME                                   READY   STATUS    RESTARTS   AGE
argo-server-5c8498b5d8-p9xqz           1/1     Running   0          2m37s
workflow-controller-64f9c8cf86-dqr59   1/1     Running   0          2m37s

Web UIを開いてみる

kubectl port-forwardコマンドで手元にポート転送できます。

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

ポート番号は 2746 です。覚えにくくて手打ちすると 2467 とか 2764 にタイポしちゃうのでコピペを推奨します。今回はCloud ShellのWebプレビュー経由で開いてみましたが、Runningになっているのになぜか疎通せず、どうやらデフォルトではHTTPSで待受になっていて、Cloud ShellのWebプレビューだと表示できないようでした。

今回はargo-serverのデプロイメントに直接パッチを当てる形で修正を行い、以下のようなコマンドで引数に --secure=false が渡るようにするとHTTP経由で接続できるようになり、readinessProbeのスキーマをHTTPに変更するとRunningに遷移しました。

$ kubectl patch deployment \
  argo-server \
  --namespace argo \
  --type='json' \
  -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/args",
    "value": [
    "server",
    "--auth-mode",
+    "server",
+    "--secure=false"
  ]},
+  {"op": "replace", "path": "/spec/template/spec/containers/0/readinessProbe/httpGet/scheme", "value": "HTTP"}]'

Web UIについてはport-forward + プロキシ経由な構成でしたが問題なく動作していそうでした。namespaceを切り分けている場合は https://host/workflows => https://host/workflows/<namespace名> などに書き換える必要があるようです。

GKE: SpotVMを使いたい

GKEのSpot VMについてはこちら => https://cloud.google.com/kubernetes-engine/docs/how-to/spot-vms?hl=ja

こちらも先と同様に kubectl patch コマンドでデプロイメントを直接書き換えてみることにしました。実行後、しばらくするとSpotVM用のノードが立ち上がって、新しいノードで稼働しているpodに入れ替わります。本番のバッチ処理など落ちると困るようなケースでは色々検討する必要がありそうですが、とりあえず試してみる分には安く使えて良さそうです。

$ kubectl patch deployment \
  argo-server \
  --namespace argo \
  --type='json' \
  -p='[{"op": "replace", "path": "/spec/template/spec/nodeSelector", "value": {"cloud.google.com/gke-spot":"true"}},
  {"op": "replace", "path": "/spec/template/spec/terminationGracePeriodSeconds", "value": 25}]'

$ kubectl patch deployment \
  workflow-controller \
  --namespace argo \
  --type='json' \
  -p='[{"op": "replace", "path": "/spec/template/spec/nodeSelector", "value": {"cloud.google.com/gke-spot":"true"}},
  {"op": "replace", "path": "/spec/template/spec/terminationGracePeriodSeconds", "value": 25}]'

サンプルのワークフローを実行してみる

GitHubリポジトリ内でサンプルのワークフローが公開されているので、これを稼働中のpodに含まれている argo submit コマンドを使って実行してみます。 --watch オプションを付与すると実行完了するまで稼働状況などを標準出力に表示してくれます。

$ kubectl exec -n argo deployments/argo-server -- \
    argo submit -n argo --watch https://raw.githubusercontent.com/argoproj/argo-workflows/master/examples/hello-world.yaml

argo submitコマンドのドキュメント https://argoproj.github.io/argo-workflows/cli/argo_submit/

自分でワークフローを書いて実行してみる

ひとまずパッと思いついたdbtでDuckDBにクエリを投入するワークフローを動かしてみようかと思います。dbtの方はv1以前だと pip install dbt でインストールできてたようですが、今は dbt-core と利用するプラグインなどを適宜指定する形になっているようでした。

コンテナイメージの作成

Dockerfile

FROM python:3.10

RUN pip3 install dbt-core dbt-duckdb

RUN mkdir -p /root/.dbt
ADD profiles.yml /root/.dbt/profiles.yml

RUN mkdir -p /app
WORKDIR /app
ADD dbt_project.yml /app/
ADD models /app/models/
# RUN dbt run --vars '{"date":"2022-12-18"}' # 動作確認用

profiles.yml / duckdbの設定

appdb:
  target: 'dev'
  outputs:
    dev:
      type: 'duckdb'
      path: 'appdb.duckdb'

dbt_project.yml

name: 'duck'
version: '1.0.0'
config-version: 2
profile: 'appdb'

models/answers.sql / コマンド実行時にパラメータを指定してみる

{{ config(materialized='incremental', unique_key=['date']) }}
select
  42 as answer,
  '{{ var('date') }}'::timestamp as dates

GCRにArgo Workflowsで使うイメージをpushしておきます。

$ gcloud builds submit --tag=gcr.io/<Project ID>/tmp/dbt:latest ./

Workflow Templateの作成

参考: https://argoproj.github.io/argo-workflows/workflow-templates/

今回は試していませんが、DAG形式の記法も存在するようです。以下はステップ実行の記述例になります。ちなみに spec.template 配下にnodeSelectorを追加するとWorkflowのジョブもSpot VMで実行することができました。

# workflow.yaml
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
  name: dbt-template
spec:
  serviceAccountName: argo
  templates:
    - name: dbt_run
      nodeSelector:
        "cloud.google.com/gke-spot": "true"
      container:
        image: gcr.io/<Project ID>/tmp/dbt:latest
        command: ["dbt"]
        args:
        - run
        - --vars
        - '{"date":"2022-12-18"}'

通常のリソースと同様に kubectl apply コマンドでワークフローの定義を反映することができます。反映後はWeb UIから実行することができ無事に実行完了しました。このテンプレートをCron Workflowというもので呼び出すと定期実行などができるようです(今回は未検証)。

$ kubectl apply -n argo -f workflow.yaml

リソースの片付けは kubectl delete コマンドでいけました。

$ kubectl delete -n argo -f https://github.com/argoproj/argo-workflows/releases/download/v3.4.4/namespace-install.yaml

🐙 わかったこと

この記事ではArgo WorkflowsをGKE AutopilotのSpotVMで動かしてみるところまでやってみました。Kubernetesと聞いて割と身構えていたのですが、ちょっと動かしてみるだけならコマンド叩くだけで試すことができるような状態にあるようです。それでもやっぱりそこそこ学習コストは掛かる感じでApache Airflowと同様の問題を抱えているようにも感じました(身構えて最初の一歩が踏み出せない問題もありそう)。

あと、ETL処理で使えないかなと思っていたのですが、それだけのためにArgo Workflowsを導入するのはちょっとオーバーかなという印象ですね。既にArgoファミリーのツールに熟れていたり、Kubernetes自体のCronJobで積み上げてきたバッチ処理が管理しきれなくなってきたくらいのタイミングだとめっちゃハマってくれそうな気もします。

sh19910711 commented 1 year ago

done ✔️