Edited at

Kubernetesユーザーは待っていた!?コンテナネイティブなワークフローエンジンArgoを試してみた

More than 1 year has passed since last update.


Argoとは?

ArgoはコンテナネイティブなOSSのワークフローエンジンです。

image.png

2018-04-25 追記

Argoはプロジェクトが分割されているようです。

この記事はその中の`Argo Workflows`について記載しています。
その他のプロジェクトはこちら 「これからと期待」に少しだけ記載しています。

ワークフローエンジンだと色々な意味が含まれるため、イメージを掴むため類似するプロダクトを挙げるとAirflowDigdagLuigiとなります。

名前の由来はギリシア神話に登場する巨大な船の名前のアルゴ船?かも

ArgoはKubernetes(以後k8s)上に構築することにより、k8sの機能を利用できる大きなアドバンテージを獲得しています。

例えばワークフローの定義はCustom Resource Definition(以後CRD)で定義できます。

つまりYAMLで定義できるため、k8sのマニフェスト管理と同じにようにhelmksonnetを使用できます。

その他にもk8sリソースのSecretPersistent volumeにアクセスすることも可能です。

k8sを利用しているユーザーには馴染みやすい定義方法となる点は大きな魅力です。

表題の通り個人的には「こういうの待ってた!」という気持ちです。

先日はコミュニティの法人会員(corporate members)にGoogleとNVIDIAの参加がアナウンスされ、これからの成長が楽しみです。


hello-worldで実行までの流れ!

どんなことができるかを説明する前に、まずはhello-worldなワークフローを実行し、イメージを掴んでいきます。

ワークフローの定義はこちら。


hello.yaml

apiVersion: argoproj.io/v1alpha1

kind: Workflow
metadata:
generateName: hello-
spec:
# 実行するテンプレートを指定
entrypoint: hello

# テンプレートの定義
templates:
- name: hello
container:
image: docker/whalesay:latest
command: [cowsay]
args: ["hello world"]


CRDで定義されたkind: Workflowを使うため、k8sのマニフェストを管理している人には馴染みやすいですね。

そして実行方法は以下のようになります。

# ワークフローを作成

$ kubectl create -f hello.yaml
workflow "hello-7wlnt" created

# Podが作成され、ワークフローが実行されている
$ kubectl get pod hello-7wlnt
NAME READY STATUS RESTARTS AGE
hello-7wlnt 0/2 Completed 0 5m

# 実行内容を見てみる(コンテナ名はmainとなる)
$ kubectl logs -c main hello-7wlnt
_____________
< hello world >
-------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/

k8sと同じ感覚で使えてとっても簡単ですね。

また上の例ではkubectlのみでワークフローが実行できており、既存のエコシステムとの連携も簡単そうです。

Webコンソールで結果をみるとこんな感じです。

image.png


どんなワークフローを定義ができる?(v2.1.0-beta2)

それではもう少しどのようなワークフローが定義できるか見ていきます。

公式のドキュメントはまだ少ないのですが、サンプルと合わせて読み取った機能を一問一答の方式で書きます。


処理ごとにパラメーターの変更はできる?



  • spec.arguments.paramtersで定義したパラメーターをargo submit --parametersで指定できるよ。


CPUとMemoryの指定はできる?


  • k8sと同じようにresourcesで指定できるよ。


Gitからコードをチェックアウトできる?



  • spec.templates[].inputs.artifacts[].gitで指定できるよ。


同じワークフローの中でファイルデータの共有はできる?


  • k8sのPersistent Volumeを使って共有できるよ。


同じワークフローの中でパラメーターの引渡しはできる?


  • パラメーターはspec.templates[].outputs.parameters[].(name|globalName)で引き渡せるよ。


定期実行はできる?


  • 現状はできないけど、k8sのCronJobで実現できると思うよ。


(Source)入力のソースとしては何が使える?


  • Git、HTTP、S3が標準では用意されているよ。


    • GCSもS3互換APIを有効にすれば対応できるよ。




(Sink)アーティファクトの保存には何が使える?


  • S3が標準では用意されているよ。


    • GCSもS3互換APIを有効にすれば対応できるよ。




既存の監視設定に組み込みたいから、Podにラベルをつけたいけどできる?



  • metadataの情報としてアノテーションとラベルを付与できるよ。


ワークロードが違うから実行するノードも分けたい。Argoで実行するPodってノードセレクターを指定できる?



  • spec.templates.nodeSelectorが使えるよ。


並列に実行したいけどできる?


  • もちろんできるし、spec.parallelismで並列数の上限も指定できるよ。


フローを分岐できる?



  • whenを使って処理をスキップできるから、擬似的に分岐できるよ。


  • whenの条件には終了ステータスコード、標準出力の内容などが使えるよ。


Slackに通知できる?


  • ネイティブの機能はないので、自分で用意する必要があるよ。


  • curlを使ってSlackに通知できるので簡単に実現できるよ。

  • メールに通知したい場合はSendgridのようなサービスを使えば簡単に実現できるよ。


ワークフローの全体の処理結果によって通知先を変更ってできる?



  • spec.onExitを使えばできるよ。


失敗した処理を再実行できる?



  • spec.templates[].retryStrategyで指定できるよ。

  • 回数制限もできるし、成功するまで実行することもできるよ。


k8sのSecretって読み込める?


  • 環境変数、またはファイルとして参照できるよ。


実行するワークフローに必要なデーモンがあるんだけど、通信させる方法はある?



  • Sidecarもできるし、Daemonの実行もできるからできるよ。


Dockerイメージをビルドってできる?


  • Docker in docker(sidecar)できるよ。


  • kanikoを使ってもいいかもね。


既存のPersistent Volumeって参照できる?


  • できるよ。


タイムアウトって設定できる?


  • できるよ。


CI/CDとして利用できる?


  • 大きなトピックになりそうだから、次の章で!!


CI/CDはできるのか


Continuous integration is a popular appication for workflows. Currently, Argo does not provide event triggers for automatically kicking off your CI jobs, but we plan to do so in the near future. Until then, you can easily write a cron job that checks for new commits and kicks off the needed workflow, or use your existing Jenkins server to kick off the workflow.


Argoのドキュメントに書かれている通り、まだトリガー機能が実装されていないのでArgo Workflow単体では実現できません

JekinsやBotkitなどでトリガーを実装するか、Argo-CIArgo-CDを使ってみるのもありだと思います。

Argo-CIArgo-CDは名前の通りまさにCIとCDをするためのツールです。

ただしArgo-CIは欠けているトリガー機能を提供してくれますが、ARLY DEVELOPMENTの状態です。

またArgo-CDksonnetを使うことが前提のため、既存システムによっては使いにくいツールかなと感じています(将来的に分離して欲しいな)。


これからと期待

v2.1ではDAGモデルもサポートされます。

これでワークフローエンジンとしては便利に使えると思いますが、ワークフローの定義内容がGUIからは確認できなため、事前定義や再利用の機能が入ればいいなと思っています。

また次のコミュニティミーティングでは以下のプロジェクトについて話し会われるようです。


  • Argo Workflows

  • Argo CI

  • Argo CD

  • Argo Events

CI/CDツールとして使える日が近づきそうです!


おまけ


インストール手順(for MAC)


  • kubernetes: v1.9.6(Docker for MAC)


    • Namespace: kube-systemにArgoのコンポーネントがインストールされる



  • Argo: v2.1.0-beta2

# インストールパスの適当に設定

$ install_path=/usr/local/bin

# バージョンを指定
$ version=2.1.0-beta2

# バイナリをダウンロード
# brewであればstableなバージョンをインストールできます
# brew install argoproj/tap/argo
$ curl -sSL -o ${install_path}/argo https://github.com/argoproj/argo/releases/download/v${version}/argo-darwin-amd64

# 実行権限を追加
$ chmod +x ${install_path}/argo

# バイナリインストール確認
$ argo version
argo: v2.1.0-beta2
BuildDate: 2018-03-29T20:49:33Z
GitCommit: fe23c2f651a61a2d7aa877a86edff9802d7b5b47
GitTreeState: clean
GitTag: v2.1.0-beta2
GoVersion: go1.9.3
Compiler: gc
Platform: darwin/amd64

# インストール
$ argo install
Installing Argo v2.1.0-beta2 into namespace 'kube-system'
Proceeding with Kubernetes version 1.9.6
CustomResourceDefinition 'workflows.argoproj.io' created
ServiceAccount 'argo' created
ClusterRole 'argo-cluster-role' created
ClusterRoleBinding 'argo-binding' created
Deployment 'workflow-controller' created
ServiceAccount 'argo-ui' created
ClusterRole 'argo-ui-cluster-role' created
ClusterRoleBinding 'argo-ui-binding' created
Deployment 'argo-ui' created
Service 'argo-ui' created

# インストール確認
$ kubectl -n kube-system get pod
NAME READY STATUS RESTARTS AGE
argo-ui-b94f57cc5-lc7g8 1/1 Running 0 1h
...
workflow-controller-6ff45f57b7-b4s42 1/1 Running 0 1h
...

# argo-uiにアクセスできるようにserviceの内容を変更
# アクセスできれば何でもOK
$ kubectl patch svc argo-ui -n kube-system -p '{"spec":{"$setElementOrder/ports":[{"port":8001}],"ports":[{"port":8001,"protocol":"TCP","targetPort":8001},{"$patch":"delete","port":80}],"type":"LoadBalancer"}}'

# ポート確認
$ kubectl get svc argo-ui -n kube-system -o yaml
kubectl get svc argo-ui -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
argo-ui LoadBalancer 10.105.20.7 localhost 8001:30780/TCP 3h

# Webコンソールにアクセス
$ open http://localhost:8001/

# 試しに実行してみる
$ argo submit https://raw.githubusercontent.com/argoproj/argo/master/examples/hello-world.yaml
Name: hello-world-svlpd
Namespace: default
ServiceAccount: default
Status: Pending
Created: Mon Apr 23 16:35:04 +0900 (29 seconds from now)

# 実行コンテナの内容確認
$ argo list
NAME STATUS AGE DURATION
hello-world-svlpd Succeeded 16s 5s

# 実行内容確認
$ argo get hello-world-svlpd
Name: hello-world-svlpd
Namespace: default
ServiceAccount: default
Status: Succeeded
Created: Mon Apr 23 16:35:04 +0900 (3 seconds from now)
Started: Mon Apr 23 16:35:04 +0900 (3 seconds from now)
Finished: Mon Apr 23 16:35:09 +0900 (8 seconds from now)
Duration: 5 seconds

# 実行ログの内容確認
$ argo logs hello-world-svlpd
_____________
< hello world >
-------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/