OKE + Argo Workflows ことはじめ

2022年11月2日 Oracle Cloud Hangout Cafe Season6 #3 [「ワークフローツールで楽々Job管理」](https://ochacafe.connpass.com/event/260559/) で実施したデモをベースに Oracle Container Engine for Kubernetes (OKE) + Argo Workflows の環境構築から基本的なワークフロー定義を実行しながら Argo Workflows の最初の一歩を踏み出してみましょう。

以下、スライド資料と公開動画を合わせてご利用頂くとより理解が深まると思います。

- [スライド資料](https://speakerdeck.com/oracle4engineer/20221102-workflow?slide=19)
- [公開動画](https://www.youtube.com/watch?v=flVGZhPOFWQ&t=1012s)

# What is Argo Workflows ?

Argo Workflows は、Kubernetes 上で並列ジョブを構成するオープンソースのコンテナネイティブワークフローエンジンです。 
Argo Workflows は Kubernetes CRD (カスタム リソース定義) として実装されます。

ワークフローの定義を Kubernetes の CRD を利用して定義、実行します。

![argoworkflows.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/d42b8617-3e88-955d-960b-17c94bba217a.png)

[Argo Workflows](https://argoproj.github.io/workflows/)

# DEMO Environment

以下の環境を構築して、実施します。

- Kubernetes Cluster : Oracle Container Engine for Kubernetes
- Node Shape (3 Nodes) : VM.Standard.E3.Flex
- Argo Workflows : v3.1.4

# OKE Set Up

OKE のプロビジョニングについては、以下チュートリアルを参考にしてください。

[Oracle Container Engine for Kubernetes(OKE)をプロビジョニングしよう](https://oracle-japan.github.io/ocitutorials/cloud-native/oke-for-commons/)

# Argo Workflows Set Up

## 1.Argo Workflows Install

Argo Workflows は、kubectl, Helm, Kustomize を利用してインストールできます。ここでは、Helm を利用します。

事前に Helm クライアントをインストールが必要となります。

Oracle Cloud Infrastructure(OCI) の場合は、Cloud Shell を利用することで Helm クライアントのインストールは不要です。

```sh
helm repo add argo https://argoproj.github.io/argo-helm
```

```sh
helm install --create-namespace --namespace argo argo-workflows argo/argo-workflows
```
```sh
NAME: argo-workflows
LAST DEPLOYED: Fri Oct 14 05:45:33 2022
NAMESPACE: argo
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get Argo Server external IP/domain by running:

kubectl --namespace argo get services -o wide | grep argo-workflows-server

2. Submit the hello-world workflow by running:

argo submit https://raw.githubusercontent.com/argoproj/argo-workflows/master/examples/hello-world.yaml --watch
```

[Argo Workflows Chart](https://github.com/argoproj/argo-helm/tree/main/charts/argo-workflows)

argo-workflows-server と argo-workflows-workflow-controller の Pod が Running であることを確認します。

```sh
kubectl get pods -n argo
```
```sh
NAME                                                  READY   STATUS    RESTARTS   AGE
argo-workflows-server-6498c4c886-f8g24                1/1     Running   0          4m4s
argo-workflows-workflow-controller-8674b6b66d-26ks4   1/1     Running   0          4m4s
```

デフォルトでは、Namespace argo に Pod 2個、Service 1個 となります。

![environment.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/7ff49b89-58fa-f545-e56e-0203e4395e74.png)

argo workflows のインストールは完了です。

## 2.Argo Workflows UI Access

Service としてインストールされる argo-workflow-service の type を LoadBalancer に変更して、ブラウザからアクセスできるようにします。

```sh
kubectl edit service/argo-workflows-server -n argo
```
```sh
・
・ ＜省略＞
・
  selector:
    app.kubernetes.io/instance: argo-workflows
    app.kubernetes.io/name: argo-workflows-server
  sessionAffinity: None
  type: ClusterIP # type: LoadBalancer に変更
・
・ ＜省略＞
・
```

EXTERNAL-IP を確認

```sh
kubectl get services -n argo
```
```sh
NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)          AGE
argo-workflows-server   LoadBalancer   10.96.147.139   193.xxx.xxx.xxx   2746:31787/TCP   24m
```

ブラウザを起動して、UI にアクセスします。

http://193.xxx.xxx.xxx:2746/

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/0f1e5ad7-d4ae-63d8-f033-836b3c3dfc35.png)


Token を取得して、ログインします。

argo-workflows-server Podのコンテナから argo auth token コマンドを実行して Token を取得します。

argo-workflows-server の Pod 名を確認します。

```sh
kubectl get pods -n argo
```
```sh
NAME                                                  READY   STATUS    RESTARTS   AGE
argo-workflows-server-6498c4c886-f8g24                1/1     Running   0          36m
argo-workflows-workflow-controller-8674b6b66d-26ks4   1/1     Running   0          36m
```

```sh
kubectl exec -it argo-workflows-server-6498c4c886-f8g24 -n argo -- argo auth token
```
```sh
Bearer eyJ...
```

Bearer を含めて、ログイン画面内で入力して、ログインボタンをクリックします。

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/28cbf6c8-e47d-2051-3a24-94a7d43807e7.png)

ログイン完了です。

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/1409b1d5-2ae2-cc02-bec5-80cb315ac909.png)

# Sample Workflow

ここで利用するマニフェストは、以下リポジトリの manifests ディレクトリにあります。リポジトリからクローンしてご利用ください。

[oracle-japan/ochacafe-s6-3](https://github.com/oracle-japan/ochacafe-s6-3)

```sh
git clone https://github.com/oracle-japan/ochacafe-s6-3.git
```

## 1.Basic

whalesay コンテナイメージを利用したサンプルワークフローを実行してみます。

```sh
kubectl create -f ochacafe-s6-3/manifests/sample-workflows.yaml
```
```sh
workflow.argoproj.io/steps-48wz6 created
```

UI を利用します。 default ネームスペースを指定すると 実行および実行中のワークフローがリスト表示されます。

対象のワークフロー名をクリックして状況を確認します。

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/3cf862ad-c3ed-38ac-948e-657b6664a821.png)

ワークフローの結果を確認できます。

![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/195a600b-351a-90c4-9839-0c349d81df8d.png)

さらにログボタンをクリックして、実行結果を確認します。

![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/1584f054-8b0c-f2c2-c547-c2dc887f39de.png)

以降も kubectl create -f を実行して、UI で確認する手順は同じなので、実行してみましょう。

## 2.並列処理

並列処理を実行します。

```sh
kubectl create -f ochacafe-s6-3/manifests/sample-workflows-parallel.yaml
```
```sh
workflow.argoproj.io/steps-kmbvc created
```

![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/affeb81d-024c-c784-957d-3c1b5ecd88f7.png)

## 3.Directed Acyclic Graph (DAG)

DAGについて、補足します。
![dag.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/e26b0e63-cbe4-538e-6648-f2d8a992e026.png)
並列処理を DAG 形式で記述して実行します。

```sh
kubectl create -f ochacafe-s6-3/manifests/sample-workflows-dag.yaml
```
```sh
workflow.argoproj.io/steps-7r4c6 created
```

![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/4e7cb789-ec88-b6ff-f590-879acb6b12c5.png)

## 4.Script

script を利用したワークフローを実行します。

```sh
kubectl create -f ochacafe-s6-3/manifests/script-workflows.yaml
```
```sh
workflow.argoproj.io/script-template-6wdvt created
```

![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/b1a567cf-67f1-32bd-b2ad-d522cd2d07ae.png)

Python スクリプトにより、以下表示されます。

Oracle Cloud Hangout Cafe 

![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/17b099c1-b6ad-c348-b8a3-e95013d4d96a.png)

## 5.Kubernetes Resource

resource を利用したワークフローを実行します。

初めに default ネームスペースに wf-sa という Service Account を作成します。

```sh
kubectl create sa wf-sa
```
```sh
serviceaccount/wf-sa created
```

role と rolebinding を適用します。

```sh
kubectl apply -f ochacafe-s6-3/manifests/role.yaml
```
```sh
role.rbac.authorization.k8s.io/wf-sa created
```

```sh
kubectl apply -f ochacafe-s6-3/manifests/rolebinding.yaml
```
```sh
rolebinding.rbac.authorization.k8s.io/wf-sa created
```

ワークフローを実行します。

```sh
kubectl create -f ochacafe-s6-3/manifests/resource-workflows.yaml
```
```sh
workflow.argoproj.io/resource-template-28h9s created
```

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/174bfb5d-1be0-e726-610c-be25561e1b20.png)

sample-cm という ConfigMap が作成されていることが分かります。

![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/49ba3b85-1c12-9528-f9de-92fb937ad93d.png)

## 6.Retry

トータルで6回実行して、すべて失敗するワークフローを実行します。

```sh
kubectl create -f ochacafe-s6-3/manifests/retry-workflows.yaml
```
```sh
workflow.argoproj.io/retry-container-4lchw created
```

![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/584527ba-d34d-b68e-db7f-98bd18ede2c1.png)

次に以下の設定をしたワークフローを実行します。
結果は失敗となります。

- backoff を利用して、リトライ間隔、リトライ時間を指定可能
- duration 10秒待つ,20秒待つ,40秒待つ...（factor で何倍するのかを指定）
- maxDuration が “1m” 1分（60秒）なので、limitで5回でも2回のリトライで終了

```sh
kubectl create -f ochacafe-s6-3/manifests/retry-advance-workflows.yaml
```
```sh
workflow.argoproj.io/retry-container-rckjn created
```

![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/6cead105-0eb9-2409-f46e-4108be6546b6.png)

## 7.処理の継続

一つの処理が失敗しても、後続の処理を実行するワークフローを実行します。

```sh
kubectl create -f ochacafe-s6-3/manifests/continue-workflows.yaml
```
```sh
workflow.argoproj.io/continue-on-fail-hf8k2 created
```

![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/0f056fb1-2284-316f-4774-86e8621b5f24.png)

## 8.Suspend & Delay

suspend を利用して、確認後、処理を継続するワークフローを実行します。

delay も利用しているので、確認処理を実行しなくても、20秒後には処理が完了します。

```sh
kubectl create -f ochacafe-s6-3/manifests/suspend-workflows.yaml
```
```sh
workflow.argoproj.io/continue-on-fail-hf8k2 created
```

approve をクリックします。

![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/fdc186db-4cad-acef-fbb6-81b924891835.png)

RESUME ボタンをクリックします。

![17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/86bf5b5d-fc7f-04ed-fb25-c0be1c663336.png)

OK ボタンをクリックします。

![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/ffafdf3a-aa5d-547b-849e-795f39638b15.png)

全ての処理が完了となります。

![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/e46a6382-8962-5ec7-37d4-59b34b7ce6af.png)

## 9.artifact

artifact を利用して、GitHub からソースを取ってきます。

[argo workflows repository](https://github.com/argoproj/argo-workflows) のソースとなります。

```sh
kubectl create -f ochacafe-s6-3/manifests/artifact-workflows.yaml
```
```sh
workflow.argoproj.io/input-artifact-git-p5w6b created
```

![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/d4596bf5-7435-d5a1-ff14-cd4bd20a6f05.png)

![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/e655afb7-c65e-2e93-f8c3-bb4be2a77472.png)

## 10.ファイルの受け渡し

MinIOを利用して、ファイルの受け渡しをするワークフローを実行します。

[MinIO](https://github.com/minio/minio) は、s3 互換オブジェクトストレージサーバ（OSS）です。

MinIOをインストールします。

```sh
helm repo add minio https://helm.min.io/
```
```sh
helm repo update
```
```sh
helm install argo-artifacts minio/minio --set service.type=LoadBalancer --set fullnameOverride=argo-artifacts
```
```sh
NAME: argo-artifacts
LAST DEPLOYED: Fri Oct 14 08:33:02 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Minio can be accessed via port 9000 on an external IP address. Get the service external IP address by:
kubectl get svc --namespace default -l app=argo-artifacts

Note that the public IP may take a couple of minutes to be available.

You can now access Minio server on http://<External-IP>:9000. Follow the below steps to connect to Minio server with mc client:

  1. Download the Minio mc client - https://docs.minio.io/docs/minio-client-quickstart-guide

  2. Get the ACCESS_KEY=$(kubectl get secret argo-artifacts --namespace default -o jsonpath="{.data.accesskey}" | base64 --decode) and the SECRET_KEY=$(kubectl get secret argo-artifacts --namespace default -o jsonpath="{.data.secretkey}" | base64 --decode)
  3. mc alias set argo-artifacts http://<External-IP>:9000 "$ACCESS_KEY" "$SECRET_KEY" --api s3v4

  4. mc ls argo-artifacts

Alternately, you can use your browser or the Minio SDK to access the server - https://docs.minio.io/categories/17
```

MinIO の UI ログインに必要となるアクセスキーとシークレットキーを取得します。

アクセスキー

```sh
kubectl get secret argo-artifacts -o jsonpath='{.data.accesskey}' | base64 --decode
```
```sh
3u...
```

シークレットキー

```sh
kubectl get secret argo-artifacts -o jsonpath='{.data.secretkey}' | base64 --decode
```
```sh
tm...
```

ブラウザでアクセスする UI の EXTERNAL-IP を確認します。

```sh
kubectl get service argo-artifacts
```
```sh
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)          AGE
argo-artifacts   LoadBalancer   10.xxx.xxx.xxx   193.123.229.121   9000:31901/TCP   8m19s
```

ブラウザを起動してアクセスします。

http://10.xxx.xxx.xxx:9000/

アクセスキーとシークレットキーを入力してログインします。

![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/23f1ce0b-38ae-caf3-bd40-67d5da6487e0.png)

ログイン完了です。

![23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/474fe905-e5ac-7c13-a96d-d970293683ec.png)

赤×ボタンをクリック後、create bucket ボタンをクリックします。

![24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/93f6527e-14a9-991a-26dc-5b1ae2704ea3.png)

my-bucket と入力して Enter キーを押します。

![25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/92f58a2c-dda7-2d57-9913-472275551412.png)

my-bucket が作成されます。

![26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/a5a3ea33-79e2-2c02-d7d5-75f939a54ad6.png)

ConfigMap を作成します。

```sh
kubectl apply -f ochacafe-s6-3/manifests/artifact-repo-cm.yaml
```
```sh
configmap/artifact-repo created
```

MinIO を利用してファイルの受け渡しを処理するワークフローを実行します。

```sh
kubectl create -f ochacafe-s6-3/manifests/minio-workflows.yaml
```
```sh
workflow.argoproj.io/artifact-passing-mmmrj created
```

![27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/a24bd0bf-a5a8-13fe-3e8d-5fb1b56f5339.png)

処理が成功すると、MinIO の my-bucket にファイルが格納されていることを確認できます。

![28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/5d26a81b-1eb3-94d8-c242-cf1a9fd05001.png)

volumeClaimTemplates については、Argo Workflows Demo で実施します。

MinIO を利用しましたが、Oracle Cloud Infrastructure (OCI) のオフジェクトストレージも利用できます。

以下、詳細が記載されています。

[Argo Workflows の artifacts に Oracle Cloud Infrastructure (OCI) Object Storage を使う](https://qiita.com/tkote/items/0b21d388ac76e76d9297)

## 11.WorkflowTemplate

WorkflowTemplate を利用して、テンプレート化を実施します。

WorkflowTemplate を登録します。

```sh
kubectl create -f ochacafe-s6-3/manifests/workflow-template.yaml
```
```sh
workflowtemplate.argoproj.io/hello created
```

テンプレート一覧に表示されます。

![29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/a5c21f0e-6936-43a1-538d-e33e89b2b4ec.png)

Workflow を実行します。

```sh
kubectl create -f ochacafe-s6-3/manifests/workflow-template-o.yaml
```
```sh
workflow.argoproj.io/from-template created
```

テンプレートを呼び出して、実行したワークフローが成功しています。

![30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/af8124ff-424b-40e7-ca7d-a7569ba7107e.png)

# Argo Workflows Demo

GitHub + OKE + DockerHub

デモの環境概要

![31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/81b21dd0-e3a6-2406-0490-2495c9cc9647.png)

GitHub からソースコードをクローンして、go のサンプルアプリケーションをビルドします。その後、コンテナイメージのビルド処理を実行して、DockerHub にコンテナイメージを格納するというワークフローのデモです。

事前準備として、DockerHub のアカウントを作成して、リポジトリを作成しておきます。

DockerHub の認証情報を Secret に登録しておきます。

```sh
kubectl create secret generic docker-config --from-literal="config.json={\"auths\": {\"https://index.docker.io/v1/\": {\"auth\": \"$(echo -n ＜Your-Repository-name＞:＜Your-Token＞|base64)\"}}}"
```
```sh
secret/docker-config created
```

ワークフローを実行します。

```sh
kubectl create -f ochacafe-s6-3/manifests/dev-workflows.yaml
```
```sh
workflow.argoproj.io/buildkit created
```

処理が成功します。

![32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/a2d1878f-47c4-ac39-aad7-95f56d5a4a28.png)

DockerHub にイメージが格納されます。

![33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61606/ddf43701-3160-af72-4064-e2c8019c8cd2.png)