はじめに
「お疲れさまでーす」
「あっ、ご丁寧にありがとうございます」
「kfpさんですか。私はにっPといいます。仕掛け人です」
「kfpさんのご担当は?」
思わせぶりな書き出しでしたがミリアニの記事ではなく、技術者nikkieがお送りする技術記事です。
Kubeflow Pipelinesを触り出しました。
目次
Kubeflow Pipelinesとは
こちらのブログが大変分かりやすかったです。
余談:(同じ意味か精査していませんが)『機械学習デザインパターン』にも「デザインパターン25:ワークフローパイプライン(Workflow Pipeline)」がありますね
Kubeflow Pipelinesのゴール
https://www.kubeflow.org/docs/components/pipelines/v1/introduction/ より
- End-to-end orchestration
- Easy experimentation
- Easy re-use
- 再利用簡単になる、結構興味
Kubeflow Pipelinesのインストール
M1 MacでDocker Desktopを使っています。
Docker Desktopの機能でKubernetesを立て、そこにKubeflow Pipelinesをインストールしました。
% docker --version Docker version 24.0.2, build cb74dfc % kubectl version Client Version: v1.28.0 Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3 Server Version: v1.27.2
インストール手順
KubeflowにはPipelines以外の要素もあるのですが、Kubeflow Pipelinesだけをインストールする手順です。
https://www.kubeflow.org/docs/components/pipelines/v1/installation/localcluster-deployment/#deploying-kubeflow-pipelines
このドキュメントはkind, k3s, k3aiのいずれかで進めていますが、Docker DesktopのKubernetesでも動作しました!
export PIPELINE_VERSION=2.0.3 kubectl apply -k "github.com/kubeflow/pipelines/manifests/kustomize/cluster-scoped-resources?ref=$PIPELINE_VERSION" kubectl wait --for condition=established --timeout=60s crd/applications.app.k8s.io kubectl apply -k "github.com/kubeflow/pipelines/manifests/kustomize/env/platform-agnostic-pns?ref=$PIPELINE_VERSION"
kubectl -n kubeflow get po
で全てのPodがRunningになるのを見守ります。
CrushLoopBackoffになるPodもありましたが、おそらく順序の依存関係が満たされないためではないかと思っています。
自動でリスタートするので、放っておいたら全部READY(1/1)になりました
Podが立ち上がったらポートフォワードです。
kubectl port-forward -n kubeflow svc/ml-pipeline-ui 8080:80
Docker Desktopの場合は http://localhost:8080/ でWeb UIが見られました🙌
チュートリアルに沿ってPipelineを作ってRun!
Web UIには2つのチュートリアルPipelineがあります。
今回は「DSL - Control structures」に沿って(途中まで)手を動かしていきます。
https://github.com/kubeflow/pipelines/blob/sdk/release-1.8/samples/tutorials/DSL%20-%20Control%20structures/DSL%20-%20Control%20structures.py
仮想環境を作って、SDKをインストールしました。
- Python 3.11.4
pip install 'kfp<2'
ライブラリバージョン
absl-py==1.4.0 attrs==23.1.0 cachetools==5.3.2 certifi==2023.7.22 charset-normalizer==3.3.2 click==8.1.7 cloudpickle==2.2.1 Deprecated==1.2.14 docstring-parser==0.15 fire==0.5.0 google-api-core==2.14.0 google-api-python-client==1.12.11 google-auth==2.23.4 google-auth-httplib2==0.1.1 google-cloud-core==2.3.3 google-cloud-storage==2.13.0 google-crc32c==1.5.0 google-resumable-media==2.6.0 googleapis-common-protos==1.61.0 httplib2==0.22.0 idna==3.4 jsonschema==4.19.2 jsonschema-specifications==2023.7.1 kfp==1.8.22 kfp-pipeline-spec==0.1.16 kfp-server-api==1.8.5 kubernetes==25.3.0 oauthlib==3.2.2 protobuf==3.20.3 pyasn1==0.5.0 pyasn1-modules==0.3.0 pydantic==1.10.13 pyparsing==3.1.1 python-dateutil==2.8.2 PyYAML==6.0.1 referencing==0.30.2 requests==2.31.0 requests-oauthlib==1.3.1 requests-toolbelt==0.10.1 rpds-py==0.12.0 rsa==4.9 six==1.16.0 strip-hints==0.1.10 tabulate==0.9.0 termcolor==2.3.0 typer==0.9.0 typing_extensions==4.8.0 uritemplate==3.0.1 urllib3==1.26.18 websocket-client==1.6.4 wrapt==1.16.0
Pipelineを作ってRunする手順(現時点の理解)
- kfpが提供するDSLでpipelineを定義したPythonファイルを作る
- Pythonファイルをpipelineの定義のYAMLファイルにコンパイル
- Kubeflow PipelinesのWeb UIでYAMLファイルをUpload(Pipeline作成!)
- Web UIでPipelineをRun
Hello World
複数のタスクを繋いで動かす単純な例です。
「DSL - Control structures」は複数の例が組み合わさっているので、一番簡単なものを切り出しました
dsl.pipeline
で定義した関数hello_world_pipeline
がパイプラインの定義です。
func_to_container_op
1でデコレートした関数を呼び出すと、タスク(ContainerOpインスタンス)を返します。
afterを使ってタスクの依存関係を定義し、パイプラインの定義を完成させています。
if __name__ == "__main__":
のブロックにコンパイルするコードを書いています。
python hello_world_example.py
と実行すると、コンパイルされてhello_world_example.py.yaml
ができます。
中はk8sのリソース定義です。
これをKubeflow Pipelines Web UIにアップロードしてPipelineを作ります。
Pipelineを作った後は実行します(=Runを作ります)。
クラスタにPodができて、Pipelineの実行が進んでいきました
ExitHandler
タスクがfailしたとき、そこでPipelineのRunが落ちないようにできます。
https://kubeflow-pipelines.readthedocs.io/en/1.8.22/source/kfp.dsl.html#kfp.dsl.ExitHandler
fail_op
が絶対に異常終了するタスクです。
Hello Worldと同様にコンパイルしてYAMLファイルを作り、それをWeb UIにアップロードしてPipelineを作ります。
Runは最後まで実行されますが、途中のタスクがfailなのでRunとしてはfail扱い(赤)です
比較として、ExitHandlerを使わない場合は続くタスクが実行されません。
https://gist.github.com/ftnext/9dd64bd49bb1443c0eda4734a2a18a7f
終わりに
ローカル環境にKubeflow Pipelinesをインストールし、SDK(kfpライブラリ)を使って簡単なPipelineを作って実行してみました。
なんだかよくわからない巨大な存在でしたが、環境構築して簡単な例を動かし、最初のハーケンが差せました!(完全に理解はまだまだ先です)
Kubeflow Pipelinesにはv1とv2があり、冒頭で引いたReproさんのブログが詳しいです。
私は今回参照するバージョンを誤り2、@dsl.component
でデコレートしていて動きませんでした。
解決にはGPT-4の力を借りています。ありがとうございます!
- https://kubeflow-pipelines.readthedocs.io/en/1.8.22/source/kfp.components.html#kfp.components.func_to_container_op↩
- Web UIのチュートリアルPipelineに記載されていたリンクから遷移した https://github.com/kubeflow/pipelines/blob/58ce09e07d031964905020c749e77bf0f37e83d4/samples/tutorials/DSL%20-%20Control%20structures/DSL%20-%20Control%20structures.py を最初参照し、コンパイルできずにいました↩