Oracle Container Engine for Kubernetes(OKE)にKubeflowをインストールしてみる

# はじめに

ふとしたきかっけでKubeflowを触る機会があったので、OKEにインストールしてみました。
せっかくなので、インストール手順をまとめてみようと思います。

# [Kubeflow](https://www.kubeflow.org)とは

Kubeflowは、Kubernetes上にエンドツーエンドの機械学習基盤を構築できるプラットフォームです。
モデルのトレーニングやデプロイなどといった機械学習サイクルの各プロセスに関するコンポーネントをKubernetes上に構築できます。

Kubeflowのシステムコンポーネントは以下のようになっています。（[公式ドキュメント](https://www.kubeflow.org/docs/started/kubeflow-overview/)からお借りしました）
![スクリーンショット 2021-08-06 15.19.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/a3f78002-6fe0-1aca-403e-89b332579978.png)

これをOKE上に構築していきます。

# インストール手順

Kubeflowのインストール手順は、[こちらのドキュメント](https://www.kubeflow.org/docs/started/installing-kubeflow/)にまとまっていますが、今回は[kfctl](https://github.com/kubeflow/kfctl)というKubeflowを管理するためのCLIツールを利用してインストールしていきます。

残念ながら、ドキュメントにはOKEへのインストールに直接言及したページはありません... :cry: 
それがこの記事を書こうと思ったきっかけでもあります:pensive:

## OKEの構築

OKEの構築は[こちら](https://oracle-japan.github.io/ocitutorials/cloud-native/oke-for-commons/)の1~3の手順を参考にしてください。

## `kfctl`のインストール

`kfctl`はGitHubから最新版をダウンロードしてインストールします。
2021年8月時点の最新バージョンはv1.2.0です。

```sh
curl -LO https://github.com/kubeflow/kfctl/releases/download/v1.2.0/kfctl_v1.2.0-0-gbc038f9_linux.tar.gz
tar zxf kfctl_v1.2.0-0-gbc038f9_linux.tar.gz
chmod +x kfctl
sudo mv kfctl /usr/local/bin/kfctl
```

次に`kfctl`が利用する環境変数を設定していきます。(必須ではありません)

```sh
export BASE_DIR=$HOME/kubeflow
export PATH=$PATH:$BASE_DIR
export KF_NAME=mykubeflow
export KF_DIR=${BASE_DIR}/${KF_NAME}
export CONFIG_URI="https://raw.githubusercontent.com/kubeflow/manifests/v1.2-branch/kfdef/kfctl_k8s_istio.v1.2.0.yaml"
```

最後に作業ディレクトリを作成しておきます。

```sh
mkdir -p ${KF_DIR}
cd ${KF_DIR}
```

これで`kfctl`のインストールは完了です！
簡単ですね！

## Kubeflowのインストール

いよいよ、Kubeflowをインストールしていきます。

`kfctl`を利用するとKubeflowのインストールはコマンド１発でできます。

```sh
kfctl apply -V -f ${CONFIG_URI}
```

`${CONFIG_URI}`は前の手順で環境変数として定義したものです。

たったこれだけです！非常に簡単ですね！！

このコマンドによって様々なコンポーネントがインストールされるので、全てのPodが`Ready`になるまで待機します。
環境にもよりますが、大体20分程度かなと思います。

全てのPodが`Ready`になると以下のような感じになります。(`kube-system` Namespaceは除外しています)

```sh
[opc@kubeflow-client mykubeflow]$ kubectl get pod -A
NAMESPACE         NAME                                                         READY   STATUS      RESTARTS   AGE
cert-manager      cert-manager-7c75b559c4-s7tjm                                1/1     Running     0          6m23s
cert-manager      cert-manager-cainjector-7f964fd7b5-lvdvc                     1/1     Running     0          6m23s
cert-manager      cert-manager-webhook-566dd99d6-5wrmg                         1/1     Running     1          6m23s
istio-system      cluster-local-gateway-5898bc5c74-djc9t                       1/1     Running     0          6m37s
istio-system      istio-citadel-6dffd79d7-n4cvl                                1/1     Running     0          6m47s
istio-system      istio-galley-77cb9b44dc-548gl                                1/1     Running     0          6m48s
istio-system      istio-ingressgateway-7bb77f89b8-k2pnl                        1/1     Running     0          6m48s
istio-system      istio-nodeagent-59lvb                                        1/1     Running     0          6m48s
istio-system      istio-nodeagent-b5f6m                                        1/1     Running     0          6m49s
istio-system      istio-nodeagent-p2k8f                                        1/1     Running     0          6m48s
istio-system      istio-nodeagent-xtw66                                        1/1     Running     0          6m48s
istio-system      istio-pilot-67d94fc954-vjj8k                                 2/2     Running     0          6m48s
istio-system      istio-policy-546596d4b4-784pl                                2/2     Running     1          6m47s
istio-system      istio-security-post-install-release-1.3-latest-daily-6bm4w   0/1     Completed   0          6m47s
istio-system      istio-sidecar-injector-796b6454d9-fq5gj                      1/1     Running     0          6m47s
istio-system      istio-telemetry-58f9cd4bf5-qv6tn                             2/2     Running     1          6m47s
istio-system      prometheus-7c6d764c48-7k5ss                                  1/1     Running     0          6m48s
knative-serving   activator-6c87fcbbb6-jlk6x                                   1/1     Running     0          4m28s
knative-serving   autoscaler-847b9f89dc-7mspk                                  1/1     Running     0          4m29s
knative-serving   controller-55f67c9ddb-q7xk5                                  1/1     Running     0          4m28s
knative-serving   istio-webhook-db664df87-czd2r                                1/1     Running     0          4m30s
knative-serving   networking-istio-76f8cc7796-rw458                            1/1     Running     0          4m29s
knative-serving   webhook-6bff77594b-b5rz5                                     1/1     Running     0          4m30s
kubeflow          admission-webhook-bootstrap-stateful-set-0                   1/1     Running     2          5m22s
kubeflow          admission-webhook-deployment-5cd7dc96f5-x9xls                1/1     Running     1          4m47s
kubeflow          application-controller-stateful-set-0                        1/1     Running     0          7m4s
kubeflow          argo-ui-65df8c7c84-vnz74                                     1/1     Running     0          4m55s
kubeflow          cache-deployer-deployment-5f4979f45-2d5s6                    2/2     Running     2          4m55s
kubeflow          cache-server-7859fd67f5-w56hs                                2/2     Running     0          4m48s
kubeflow          centraldashboard-67767584dc-r9wvq                            1/1     Running     0          4m54s
kubeflow          jupyter-web-app-deployment-8486d5ffff-j76h4                  1/1     Running     0          4m54s
kubeflow          katib-controller-7fcc95676b-b5qfc                            1/1     Running     1          4m54s
kubeflow          katib-db-manager-85db457c64-lzprn                            1/1     Running     1          4m54s
kubeflow          katib-mysql-6c7f7fb869-cd4s2                                 1/1     Running     0          4m51s
kubeflow          katib-ui-65dc4cf6f5-8vw4s                                    1/1     Running     0          4m53s
kubeflow          kfserving-controller-manager-0                               2/2     Running     0          4m18s
kubeflow          kubeflow-pipelines-profile-controller-797fb44db9-b6dn6       1/1     Running     0          4m53s
kubeflow          metacontroller-0                                             1/1     Running     0          5m22s
kubeflow          metadata-db-6dd978c5b-ppdzw                                  1/1     Running     0          4m53s
kubeflow          metadata-envoy-deployment-67bd5954c-6kqqv                    1/1     Running     0          4m53s
kubeflow          metadata-grpc-deployment-577c67c96f-fmwd2                    1/1     Running     1          4m52s
kubeflow          metadata-writer-756dbdd478-mbg8z                             2/2     Running     0          4m52s
kubeflow          minio-54d995c97b-qcv5m                                       1/1     Running     0          4m52s
kubeflow          ml-pipeline-7c56db5db9-s2scf                                 2/2     Running     1          4m52s
kubeflow          ml-pipeline-persistenceagent-d984c9585-4gq6b                 2/2     Running     0          4m52s
kubeflow          ml-pipeline-scheduledworkflow-5ccf4c9fcc-rzr7c               2/2     Running     0          4m51s
kubeflow          ml-pipeline-ui-7ddcd74489-bqp66                              2/2     Running     0          4m48s
kubeflow          ml-pipeline-viewer-crd-56c68f6c85-z7829                      2/2     Running     3          4m51s
kubeflow          ml-pipeline-visualizationserver-5b9bd8f6bf-wjww6             2/2     Running     0          4m51s
kubeflow          mpi-operator-d5bfb8489-69h7h                                 1/1     Running     0          4m50s
kubeflow          mxnet-operator-7576d697d6-2gvfm                              1/1     Running     0          4m50s
kubeflow          mysql-74f8f99bc8-hjc7t                                       2/2     Running     0          4m50s
kubeflow          notebook-controller-deployment-5bb6bdbd6d-4ldpf              1/1     Running     0          4m50s
kubeflow          profiles-deployment-56bc5d7dcb-2rs8x                         2/2     Running     0          4m49s
kubeflow          pytorch-operator-847c8d55d8-v5dwn                            1/1     Running     0          4m49s
kubeflow          seldon-controller-manager-6bf8b45656-46g4m                   1/1     Running     0          4m49s
kubeflow          spark-operatorsparkoperator-fdfbfd99-qvr2f                   1/1     Running     0          5m22s
kubeflow          spartakus-volunteer-558f8bfd47-zj66n                         1/1     Running     0          4m16s
kubeflow          tf-job-operator-58477797f8-27fv8                             1/1     Running     0          4m48s
kubeflow          workflow-controller-64fd7cffc5-hlx6n                         1/1     Running     0          4m48s
```

これでインストールは完了です。

## KubeflowのUIにアクセス

Kubeflowのインストールが完了したので、UIにアクセスしてみます。

デフォルトでは、以下のようにistio-ingressgatewayがNodePortタイプで作成されているので、こちらを利用します。

```sh
[opc@oke-client ~]$ kubectl get svc -A | grep istio-ingressgateway   
istio-system         istio-ingressgateway                           NodePort    10.96.221.79    <none>        15020:31800/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:31756/TCP,15030:32683/TCP,15031:31867/TCP,15032:30051/TCP,15443:32296/TCP   31d
```

今回は、Worker Nodeはプライベート・サブネット上に作成しているので、`kubectl port-forward`を利用してポートフォワードでアクセスしてみます。
パブリック・サブネット上に作成された場合は、Worker NodeのパブリックIPとポートを利用してアクセスできます。

```sh
kubectl port-forward -n istio-system svc/istio-ingressgateway 8080:80 --address 0.0.0.0
```

OKEクライアントがリモートに存在しSSHなどで接続している場合は、OKEクライアント側の8080ポートとローカル側の任意のポートをバインドすれば接続できます

アクセスするとこんな画面が表示されます。
![スクリーンショット 2021-08-06 16.34.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/dd3ec225-bd2c-1bef-ad62-45eb77d04f8c.png)

この環境で、様々なML開発プロセスが回せそうです！

## 注意事項

Kubeflowのインストールで記載した通り、KubeflowをインストールするとたくさんのPodがデプロイされ、そこそこWorker Nodeのリソースを消費します。
私が試した感じでは、[OCIのCompute Shape](https://docs.oracle.com/ja-jp/iaas/Content/Compute/References/computeshapes.htm)として2oCPU/メモリ16GB×3Nodeは最低でも必要そうな感じがしました。
機械学習を行うプラットフォームで、貧弱なスペックで運用するということはあまりないと思いますが、注意事項として残しておきます。

# まとめ
簡単にKubeflowの環境を構築することができ、Kubeflowの便利さを改めて実感しました。
次回は、今回構築した環境とJupyter Enterprise Gatewayという仕組みを利用して、OKEのWorker Nodeのリソースプール(カーネル)をローカルから使ってみる手順を紹介したいと思います。

# 参考情報

* Kubeflow公式ドキュメント
https://www.kubeflow.org/

* `kfctl`のレポジトリ
https://github.com/kubeflow/kfctl