LoginSignup
5
2

More than 5 years have passed since last update.

Local Volumeを使ったKubeflowの動作検証

Last updated at Posted at 2018-10-18

はじめに

 今回の検証では、Kubernetes上でML環境を提供するKubeflowを試します。Kubeflowは、シングルノードのKubernetesの実験環境であるminikubeでも実行できます。しかし、大規模な計算を行うMLにおいて、シングルノードの計算リソースでは実用に耐えられません。そのため、マルチノードのKubernetesクラスタ上にKubeflowをセットアップしたい人も多いかと思います。
 しかし、セットアップに際し、ひとつ問題があります。それが永続ストレージです。Kubeflowをセットアップするためには、データを保存するための永続ストレージが必要となります。minikubeでは、minikubeが提供するprovisionerによって、minikubeのVMを利用し永続ストレージを提供しています。GKEなどのパブリッククラウドのサービスを使っている場合も、比較的容易に永続ストレージを準備することができます。しかし、自宅や小規模なオフィスなどでKubernetesを運用している場合は、なかなか準備できない人も多いかと思います。さらには、Kubeflowで必要とされている永続ストレージはDBなどのバックエンドで利用することから、ファイルストレージ(NAS)は非推奨であることからブロックストレージを準備しないといけません。
 そこで、今回は、自宅や小規模なオフィスでも容易に準備できるブロックストレージとしてKubernetes: Local Volumeの検証で紹介したLocal Volumeを使ってKubeflowを使いKubeflowの動作検証を行います。

検証環境

以下のKubernetes環境を使います。

  • Kubernetes v1.11.1
    • Master x 1, Worker x 2
  • Kubeflow v0.3

動作検証

ksnonnet のインストール

Kubeflow 0.3では、ksonnet 0.11.0 or laterが必要になります。
そのため、brewを使いksonnetをインストールします。

$ brew install ksonnet/tap/ks
...

$ ks version
ksonnet version: 0.13.0
jsonnet version: v0.11.2
client-go version: kubernetes-1.10.4

Kubeflowのダウンロード

GitHubにあるKubeflowのセットアップに必要なファイル一式をダウンロードします。

$ mkdir kubeflow
$ cd kubeflow/
$ export KUBEFLOW_TAG=v0.3.0
$ curl https://raw.githubusercontent.com/kubeflow/kubeflow/${KUBEFLOW_TAG}/scripts/download.sh | bash
...

ダウンロードが完了するとkubeflowscriptディレクトリが作成され、その配下にセットアップで利用するスクリプトが配置されます。

Kubeflowのセットアップ

はじめに、セットアップ用の環境変数の設定スクリプトを生成します。

$ scripts/kfctl.sh init kfapp --platform none
...

$ cd kfapp/

次に、環境変数の設定スクリプトのあるディレクトリにて、ksonnet appを生成します。

$ ../scripts/kfctl.sh generate k8s
...

続いて、Kubeflowをデプロイする先のNamespace(kubeflow)をKubernetes上に作成します。

$ kubectl create ns kubeflow

Kubeflowをデプロイします。

$ ../scripts/kfctl.sh apply k8s
...

デプロイが完了後、KubernetesにデプロイされたPodを確認します。

$ kubectl get pod
NAME                                        READY   STATUS    RESTARTS   AGE
ambassador-868d5dbdc4-6psgx                 3/3     Running   0          22m
ambassador-868d5dbdc4-rxz2s                 3/3     Running   0          22m
ambassador-868d5dbdc4-wpw67                 3/3     Running   0          22m
argo-ui-84464bd59c-9gwsn                    1/1     Running   0          21m
centraldashboard-c76877875-x4pgb            1/1     Running   0          22m
modeldb-backend-58969447f6-hszg9            1/1     Running   0          21m
modeldb-db-57b855f5b7-lc47p                 1/1     Running   0          21m
modeldb-frontend-769d5bdd66-77964           1/1     Running   0          21m
spartakus-volunteer-5974ff4c8c-8qmfr        1/1     Running   0          20m
studyjob-controller-56588dc6f9-l4rqc        1/1     Running   0          21m
tf-hub-0                                    1/1     Running   0          22m
tf-job-dashboard-7777b6bf-mlk2g             1/1     Running   0          22m
tf-job-operator-v1alpha2-5c5b4dcfdf-2knwd   1/1     Running   0          22m
vizier-core-5584ccbd8-wt9zm                 0/1     Error     6          21m
vizier-db-547967c899-sgmmz                  0/1     Pending   0          21m
vizier-suggestion-grid-8547dbb55b-4qpwp     1/1     Running   0          21m
vizier-suggestion-random-d7c5cd68b-fg7sl    1/1     Running   0          21m
workflow-controller-5c95f95f58-cpbh5        1/1     Running   0          21m

すると、残念ながらvizierの起動に失敗しています。
失敗している原因は、vizer-db(実体はMySQL)にPersistentVolumeが割り当てられていないためです。そのため、vizier-dbがPendingとなりvizier-coreの起動に失敗しています。
kubectl describeコマンドで確認することで原因がわかります。
なお、PersistentVolumeがDynamic Provisioningできる環境であれば、本問題は発生しないかもしれません。

$ kubectl describe pod vizier-db-547967c899-sgmmz
...
Events:
  Type     Reason            Age                    From               Message
  ----     ------            ----                   ----               -------
  Warning  FailedScheduling  3m46s (x363 over 23m)  default-scheduler  pod has unbound PersistentVolumeClaims (repeated 3 times)

$ kubectl get pvc
NAME        STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
vizier-db   Pending                                                     24m

$ kubectl get pv
No resources found.

そこで、Kubernetes: Local Volumeの検証を参考にし、Local Volumeを割り当てるようにします。
作成したPersistent Volumeは以下です。

$ kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS    REASON   AGE
local-pv   10Gi       RWO            Retain           Available           local-storage            17s

以上で、KubeflowがKubernetes上にデプロイされます。
vizer-dbが利用するPersistentVolumeClaim(vizier-db)が要求しているサイズが10Gbyteのため、Local VolumeのPersistentVolume(local-pv)も10GByteとしています。
次に、PersistentVolumeClaim(vizier-db)と、PersistentVolume(local-pv)をBoundさせます。
まず、PersistentVolumeClaim(vizier-db)をYAMLフォーマットでManifestファイルに保存します。

$ kubectl get pvc vizier-db -o yaml > vizier-db.yaml

続いて、保存したManifestファイルを編集します。
編集箇所を以下に示します。
特に必要なのは、.spec.storageClassNameにLocal Volume用のStorageClassであるlocal-storageを指定することです。

--- vizier-db.yaml.org  2018-10-17 17:45:09.000000000 +0900
+++ vizier-db.yaml  2018-10-17 17:45:41.000000000 +0900
@@ -3,7 +3,6 @@
 metadata:
   annotations:
     ksonnet.io/managed: '{"pristine":"H4sIAAAAAAAA/0yOsU7tQAxE+/cZU+cBt01LQYVAFJcCUTibAVlJ1svaAYmr/Xe0KRDd6Nhz7Auk6JnV1TJGfJ4wYNE8Y8Rjpx7McbZ133i7im4YsDFklhCMF6wycfWepJTe129lxYBkW7HMHBgxT13qljPjSu3672yR0AltQJaNv4L/R6UjL5I6X/aJb6t99VUvTMfJlOh+bzMd4wueKPNz1eBDTsTrgEq3vSYe/1V+7PQ4sodVee/a082dorXW/v0AAAD//wEAAP//j1cT1gkBAAA="}'
-  creationTimestamp: 2018-10-17T07:51:18Z
   finalizers:
   - kubernetes.io/pvc-protection
   labels:
@@ -14,13 +13,11 @@
   name: vizier-db
   namespace: kubeflow
   resourceVersion: "4672936"
-  selfLink: /api/v1/namespaces/kubeflow/persistentvolumeclaims/vizier-db
   uid: 6eb34226-d1e1-11e8-a0a0-080027571559
 spec:
+  storageClassName: local-storage
   accessModes:
   - ReadWriteOnce
   resources:
     requests:
       storage: 10Gi
-status:
-  phase: Pending

編集が完了後、Manifestファイルを使いデプロイします。

$ kubectl delete pvc vizier-db
persistentvolumeclaim "vizier-db" deleted

$ kubectl create -f vizier-db.yaml
persistentvolumeclaim/vizier-db created

PersistentVolumeClimのデプロイが完了すると、vizier-coreとvizier-dbが起動します。

$ kubectl get pod
...
vizier-core-5584ccbd8-wt9zm                 1/1     Running   12         1h
vizier-db-547967c899-sgmmz                  1/1     Running   0          1h
...

これでKubeflowのPodが全て起動しました。

動作確認

port-forwadingの設定

次のコマンドでreverse proxyを提供するambassadorのPodにポートをフォワードします。

$ export NAMESPACE=kubeflow
$ kubectl port-forward -n ${NAMESPACE}  `kubectl get pods -n ${NAMESPACE} --selector=service=ambassador -o jsonpath='{.items[0].metadata.name}'` 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

Webブラウザでhttp://localhost:8080/にアクセスすると以下のようなKubeflow navigation UIにアクセスできます。

スクリーンショット 2018-10-17 18.16.27.png

Jupyter Notebookへのアクセス

Kubeflow navigation UIからJUPYTERHUBを選択します。
すると、ログイン画面が起動するため、好きなUsername, Passwordを入力しSign inをクリックします。

スクリーンショット 2018-10-17 18.13.49.png

次にSpawnerの選択画面が出てます。

スクリーンショット 2018-10-17 18.14.01.png

Imageに、tensorflowのイメージを指定します。
GPUを使う人は、イメージ名にgpuが入ったものを選択し、CPUのみ使う人はcpuが入ったものを選択します。

スクリーンショット 2018-10-17 18.38.28.png

Imageを選択後、Spawnを選択します。
すると、Jupyter Notebookの環境作成が始まります。

スクリーンショット 2018-10-17 18.14.43.png

ここで、数分待っても終わらないようであれば、Jupyter NotebookのPodの状態を確認してください。kubectl getコマンドで確認すると、jupyter-のPod(本検証ではjupyter-ysakashita)が生成され、Pendingになっています。
これは、vizier-dbと同じく、jupyter-のPodが利用するPersistent Volumeが作成出来ていないからです。

$ kubectl get pod
NAME                                        READY   STATUS              RESTARTS   AGE
...
jupyter-ysakashita                          0/1     Pending
   0          2m
...

$ kubectl get pvc
NAME        STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
...
claim-ysakashita   Pending                                                     2m

そこで、Kubernetes: Local Volumeの検証を参考にし、Local Volumeを割り当てるようにします。
作成したPersistent Volumeは以下です。

$ kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS    REASON   AGE
...
local-pv2   10Gi       RWO            Retain           Available           local-storage            18s

次に、PersistentVolumeClaim(claim-ysakashita)と、PersistentVolume(local-pv2)をBoundさせます。
まず、PersistentVolumeClaim(claim-ysakashita)をYAMLフォーマットでManifestファイルに保存します。

$ kubectl get pvc claim-ysakashita -o yaml >claim-ysakashita.yaml

続いて、保存したManifestファイルを編集します。
編集箇所を以下に示します。

$ diff -u claim-ysakashita.yaml.org claim-ysakashita.yaml
--- claim-ysakashita.yaml.org 2018-10-17 18:25:18.000000000 +0900
+++ claim-ysakashita.yaml 2018-10-17 18:25:59.000000000 +0900
@@ -3,7 +3,6 @@
 metadata:
   annotations:
     hub.jupyter.org/username: ysakashita
-  creationTimestamp: 2018-10-17T09:14:11Z
   finalizers:
   - kubernetes.io/pvc-protection
   labels:
@@ -12,9 +11,9 @@
   name: claim-ysakashita
   namespace: kubeflow
   resourceVersion: "4681970"
-  selfLink: /api/v1/namespaces/kubeflow/persistentvolumeclaims/claim-ysakashita
   uid: 026fd018-d1ed-11e8-a0a0-080027571559
 spec:
+  storageClassName: local-storage
   accessModes:
   - ReadWriteOnce
   resources:

編集が完了後、Manifestファイルを使いデプロイします。

$ kubectl delete pvc claim-ysakashita
persistentvolumeclaim "claim-ysakashita" deleted

$ kubectl create -f claim-ysakashita.yaml
persistentvolumeclaim/claim-ysakashita created

PersistentVolumeClimのデプロイが完了すると、jupyter-ysakashitaのPodが起動します。

$ kubectl get pod
NAME                                        READY   STATUS    RESTARTS   AGE
...
jupyter-ysakashita                          1/1     Running   0          19m
...

Podが起動すると、以下のようにJupyter Notebookが立ち上がります。

スクリーンショット 2018-10-17 18.33.21.png

Jupyter Notebookでnewを選択し、新しいソースコードを作成し開発を開始します。

スクリーンショット 2018-10-17 19.02.26.png

以上で、KuberflowのセットアップとJupyter Notebookの起動まで動作検証を実施しました。

おわりに

 今回は、Local Volumeを使ったKubeflowのセットアップと動作検証を行いました。
これまで、永続ストレージが準備できずminikubeで仕方なくKubeflowを使っていた人もいたかと思います。minikubeだと、どうしてもCPUやメモリなどのリソースが不足しがちになります。
今回の検証で単にLocal Volumeを使うというだけでなく、minikubeから卒業しCPUやメモリに加えGPUなどのリソースが潤沢に使えるKubernetesクラスタ環境へ移行出来るのではないでしょうか。
 また、今回利用したLocal Volumeは、自宅や小規模オフィスのようにあまりインフラにお金をかけられない環境において、手軽に利用できるブロックストレージです。しかし、2018/10時点での最新のKubernetes 1.12.1でもLocal Volumeは、未だDynamic Provisioningが正式にサポートされていません。KubeflowのようにDynamic Provisioningを前提としている場合、Local Volumeはまだまだ扱いにくいのが現状です。今回実施したように一つ一つ確かめながらLocal Volumeを割り当てていく必要があります。そのため、非常に手間がかかってしまうのが残念です。お金をかけるか手間をかけるかの天秤ですね。もし、Local VolumeのDynamic Provisioningの正式サポートが待てないという人はKubernetes incubatorのDynamic Provisioningを利用する方法もあります。私も機会があれば試してみたいと思います。

参考情報

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2