はじめに
こんにちは、サイバーエージェントのAI事業本部SREチームの田口です。 今回は、argo-workflowsについて、半年間運用してみたのでその感想など話していきます。
argo-workflowとは
argo-workflowは、kubernetes上で並列ジョブを実行するためのオープンソースのコンテナネイティブエンジンです。Kubernetes CRD (カスタム リソース定義) として実装されています。 詳しくは、公式のページに詳しく情報が載っているのでこちらをご覧になってください。
構成はどのようになっているか
社内のkubernetes基盤であるAKE上に2つのクラスタを作成しています。 1つは、CI/CD ならびワークフロー処理をするクラスタ、もう1つはアプリケーションクラスターになります。 開発者はgitの状態と同期を行い、OPSクラスターから、自動もしくは、コマンド、GUI上で、デプロイや定期実行のワークフローを動かしています。
どのようなことに利用しているのか
担当プロダクトでは、現状以下のような機能を動かしています。
- logの収集や転送のワークフロー
- dbのtableの変更や作成のワークフロー
- mlの特徴量作成やmodelのデプロイのワークフロー
これらは、argo-workflowsの機能の1つである「Cron Workflows」を使うことによって定期実行しています。
以下の例では、実際に並列で動かしているworkflowsのUIです。ワークフローの実行結果を表示しています。 UIは変更できますが、この場合上から下にワークフローがステップ実行されている様子を表しています。 横に並んでいる箇所は1つのステップ内で、並列処理をしている状態を表してます。 「...」で省略されている箇所はありますが、こちらも開くと10個ほどの並列ステップが実行されていることがわかります。※1参照
※1 一部展開した例)
何が便利か
実際に使ってみて便利だった点を数点ご紹介します。 まずはこちらのワークフローをご確認ください。こちら公式に載っているものを少し加工したものになります。
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: exit-handlers-
spec:
entrypoint: intentional-fail
onExit: exit-handler # invoke exit-handler template at end of the workflow
templates:
# primary workflow template
- name: intentional-fail
container:
image: alpine:latest
command: [sh, -c]
args: ["echo intentional failure; exit 1"]
# Exit handler templates
# After the completion of the entrypoint template, the status of the
# workflow is made available in the global variable {{workflow.status}}.
# {{workflow.status}} will be one of: Succeeded, Failed, Error
- name: exit-handler
steps:
- - name: notify
template: send-email
- name: celebrate
template: celebrate
when: "{{workflow.status}} == Succeeded"
- name: cry
template: cry
when: "{{workflow.status}} != Succeeded"
- name: send-email
container:
image: alpine:latest
command: [sh, -c]
args: ["echo send e-mail: {{workflow.name}} {{workflow.status}} {{workflow.duration}}"]
- name: celebrate
container:
image: alpine:latest
command: [sh, -c]
args: ["echo hooray!"]
- name: cry
container:
image: alpine:latest
command: [sh, -c]
args: ["echo boohoo!"]
エラーハンドリングが容易にできる
「spec.onExit」を定義することで(この場合、exit-handler)ワークフローの最後で必ず呼び出すことができます。上記の例ではワークフローのステータスを確認することにより、エラーハンドリングできます。この機能はkubernetes標準のjobやCronJobではやりにくい点だと思うので、この辺りはかなり便利かなと思います。
shellやdockerとの相性が良い
基本dockerのimageベースで各ステップを記載します。 こちらpythonの例ですが、pythonのプレーンなdocker imageを指定し、処理自体は、workflow上に簡単に書くことによって、簡単な処理などはわざわざ、dockerをビルドして、作る必要もなく非常に簡単に実装でき、開発の効率をあげることができます
- name: gen-random-int-python
script:
image: python:alpine3.6
command: [python]
source: |
import random
i = random.randint(1, 100)
print(i)
外部からの呼び出しが簡単
workflowを外部から実行したい場合はよくあるケースだと思います。 そういった場合でも以下のように、argo-workflowのクライアントのインストールなどをしなくても呼び出し方ができ、簡単に外から呼び出すことができます。
curl $ARGO_SERVER/api/v1/events/argo/my-discriminator \\
-H "Authorization: $ARGO_TOKEN" \\
-H "X-Argo-E2E: true" \\
-d '{"message": "hello events"}'
最後に
使い始めて半年ぐらいですが、簡単に並列処理やジョブが作成でき便利に感じています。 まだまだ便利な使い方や、機能がたくさんので、今後とも最新情報を追っていく予定です。
また、私たちのチームブログも別途公開していますので、よかったらこちらもご覧ください