Helmで最新のJupyterHub(0.8-b6bdb73)をMinikubeにデプロイする

by

@wapa5pow

ogp

以前、マルチユーザ機械学習環境をJupyterHubとKubernetesで構築で構築していたJupyterHubはGKE(Google Kubernetes Engine)にデプロイしていて、ローカル開発環境ではJupyterHubのかわりに、普通のJupyter Notebookを動かしていました。JupyterHubはHubやNotebookの部分をカスタマイズしていることもあり、Jupyter Notebookを動かすのは実際の本番環境と異なっており、開発がしんどくなってきたので、今回、Minikubeを使ってJupyterHubをローカル開発環境上に構築しました。

HubやNotebookを独自にビルドしてGCR(Google Container Registry)などにpushしてから利用する場合、Helmの最新安定版の0.7.0では対応できなかったので記事をかいている現在最新の0.8-b6bdb73を利用して構築しました。

JupyterHub(0.8-b6bdb73)をMinikubeにデプロイする

JupyterHubでGCRにおいてあるDockerイメージを使わない場合は、MinikubeがDockerイメージを取得する際のGCRの設定をする必要がないので簡単です。(この場合は、JupyterHubのHelmチャートのバージョンが0.7.0でも動かすことができます。)

まずMinikubeを立ち上げます。Kubernetesで使うVMの、Diskサイズ40GB、メモリ8GB、CPUの数6を指定していますが、ここらへんはローカルのマシンの状況に応じて変えてください。あまりリソースが少ないとJupyterHubのほかにPodを立ち上げたときにリソース不足でPodが立ち上がらなくなるので調整してください。

minikube start --disk-size 40g --memory 8192 --cpus 6

しばらくするとMinikubeが立ち上がるので、IngressのAdd-onを有効にします。JupyterHubをそのままデプロイしてもServiceのLoad BalancerがMinikubeだと機能しないのでIngressを通してJupyterHubにアクセスします。

minikube addons enable ingress

Ingressを通してアクセスするドメインの設定をしておきます。今回はjupyterhub.example.comというドメインを仮に/etc/hostsに登録しますが、各自すきなドメインとしてください。ただし、*.devのようなドメインの場合、ChromeがHSTSをきかせてHTTPSにリダイレクトされてこまるのでそれを避けるようなドメインにしてください。

# MinikubeのIPを取得する
minikube ip

# /etc/hostsに登録する。以下は例
192.168.99.100 jupyterhub.example.com

次にHelmをMinikubeのKubernetes側にインストールします。Helmのバージョンが低いとJupyterHubのデプロイがうまくいかないときがあるので、最新にしておきます(今回はv2.12.3)

helm init --service-account tiller --wait

次にJupyterHubをHelmでインストールします(Setting up JupyterHubが参考になります)。まずは設定ファイルをつくります。secretTokenとcookieSecretはよしなに設定してください。singleuserはデフォルトで10GBのディスク容量でユーザごとのディスクを作成するのですが、そんなには必要ないので2GBとしています。proxyのserviceはIngressを使うのでNodePortを指定しています。

title=values.yaml
proxy:
  secretToken: xxx
  service:
    type: NodePort

hub:
  cookieSecret: yyy

singleuser:
  storage:
    capacity: 2Gi
    dynamic:
      storageClass: standard

prePuller:
  hook:
    enabled: true

cull:
  enabled: false

次に、最新のJupyterHubのHelmファイルを取得します。JupyterHubの最新のHelmチャートはJupyterHub and BinderHub Helm charts for Kubernetesにあるので、そこからダウンロードします。今回は、jupyterhub-0.8-b6bdb73.tgzをダウンロードして、解凍しました。解凍したフォルダをjupyterhubとします。

HelmでJupyterHubをデプロイするには以下のようにします。ネットワークの環境によっては結構時間がかかるので完了するまでしばらく待ちます。

helm upgrade --install jhub ./jupyterhub --values values.yaml --timeout 1800

デプロイしたらkubectl get podなどで正しくPodが作成されているか確かめます。

最後に、Ingressの設定をします。設定ファイルは以下です。

title=ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress
spec:
  backend:
    serviceName: proxy-public
    servicePort: 80

MinikubeのKubernetesに適用します。

kubectl config use-context minikube
kubectl apply -f ingress.yaml

これで、http://jupyterhub.example.comにアクセスすればJupyterHubにただしくアクセスできます。

GCRにある独自ビルドしたHubやNotebookのイメージを利用してデプロイする

GCRにあるDockerイメージをHubやNotebookのイメージとして使った場合の手順を説明します。HubやNotebookのイメージの作成自体はとくに特別なことはありませんが、HubのベースイメージはJupyterのHelmチャートと合わせる必要があります。今回はFROM jupyterhub/k8s-hub:80a76acとしました。

今回は、以下のGCRのアドレスのイメージを使用するものとします。

  • Hub: gcr.io/example/jupyter-hub-minikube:1.0.0
  • Notebook: gcr.io/example/jupyter-singleuser-minikube:1.0.0

MinikubeからGCRのDockerイメージを取得するにはJupyterのHelmチャートのvalues.yamlhub.imagePullSecretsingleuser.imagePullSecretにGCRのサービスアカウントを登録します。GCRのやりかたについてはJupyterHubのHelmチャートに詳しくかいてあります。以下は今回使うvalues.yamlimagePullSecret設定の一部です。

title=values.yamlの一部
hub:
  image:
    name: gcr.io/example/jupyter-hub-minikube
    tag: 1.0.0
  imagePullSecret:
    enabled: true
    registry: gcr.io
    username: _json_key
    password: |-
      {
        ...
      }
...
singleuser:
  image:
    name: gcr.io/example/jupyter-singleuser-minikube
    tag: 1.0.0
  imagePullSecret:
    enabled: true
    registry: gcr.io
    username: _json_key
    password: |-
      {
        ...
      }

あとは先程と同じようにHelmでJupyterHubをデプロイします。これで独自にビルドしたDockerイメージをMinikube上のJupyterHubでうごかせました。

helm upgrade --install jhub ./jupyterhub --values values.yaml --timeout 1800

まとめ

JupyterHubを、最新のHelmチャートを使ってMinikubeでデプロイする手順を説明しました。
最新のバージョン(0.8-b6bdb73)で、imagePullSecretを使えば、GCRにあるDockerイメージもHubやNotebookとして使うことができます。

初めて、Minikubeを使いましたがなかなか使えそうです。これでローカルでの開発もはかどりそうですね。