どこから見てもメンダコ

軟体動物門頭足綱八腕類メンダコ科

Python初心者講習のためのJupyterHub

JupyterHubを利用して管理者が用意したPythonチュートリアル用 jupyter notebookをユーザーがブラウザからすぐに実行できる環境を構築します。

  • JupyterHubによる、不特定多数のユーザーがブラウザからアクセスするだけでPythonを実行できる環境の提供
  • Dockerコンテナによる、ユーザーごとに隔離された実行サーバ
  • Githubによる、チュートリアル資料の管理

github.com


f:id:horomary:20191107004015p:plain


Pythonワークショップを楽にやりたい

近年のAIブームにより多くの企業においてPython社内教育のニーズが急激に高まっているようですが、外部サービスを利用するならともかく、Pythonによる機械学習研修やワークショップを社内で開催するというのはなかなかに面倒です。

教材を作成するのはまあよいとして、Python環境の構築でコケる人が必ず何人かは出ますし、チュートリアル教材となるjupyter notebookの配布やユーザに教材のバージョンを更新してもらうことなどは大変面倒です。

ここではそのような面倒ごとを解決するために、ユーザー側の事前準備不要で管理者の用意したJupyterNotebookを実行できる環境をJupyterHubによって提供します。

Google ColaboratoryとGoogleCloudによるnotebookの共有機能を利用できる環境ならそっちを利用した方がはるかに楽です。


JupyterHubとは

ブラウザからアクセス/実行できるユーザ認証機能つきJupyterサーバーです。

JupyterHubは、ユーザーグループにノートブックのパワーをもたらします。ユーザーにインストールおよび保守タスクを負担することなく、計算環境とリソースへのアクセスを提供します。ユーザー(学生、研究者、データサイエンティストを含む)は、システム管理者が効率的に管理できる共有リソース上の独自のワークスペースで作業を完了できます。
JupyterHubはクラウドまたは独自のハードウェアで実行され、事前に構成されたデータサイエンス環境を世界中のユーザーに提供することができます。カスタマイズ可能でスケーラブルであり、小規模および大規模なチーム、アカデミックコース、および大規模なインフラストラクチャに適しています。

Google翻訳 from Project Jupyter | JupyterHub

主要な機能は、

  • ユーザ認証機能

  • ユーザごとのsingle jupyter notebook サーバーの生成

の2つですが、これらについてはユースケースに応じて多様なオプションが用意されています。

認証についてはLDAPGithubアカウント認証など多くの選択肢が用意されていますし、single notebook serverの生成についてもDockerを使ったりKubernetesでリソースを管理したりといろいろあります。

今回はPythonワークショップでの使用=使い捨て環境を想定しているので、
NativeAuthenticator (ユーザー名とパスワードでアカウント作成し、管理者が許可する方式)
によってシンプルな認証管理を行い、
DockerSpawner (ユーザーごとにnotebook実行サーバをdockerコンテナで走らせる方式)
によってユーザーごとに使い捨てのnotebook実行サーバーを立ち上げる構成を採用します。


実行環境

テスト環境として

Google Cloud PlatformCompute EngineVMインスタンスで構築します。

VMインスタンスUbuntu 16.04 LTS
ポート開放: TCP 22, 80, 443, 8000


環境準備

関連パッケージのインストール

はじめはpipからjupyterhubをインストールしようとしたのですがnode.jsとのバージョン依存などでハマったのでcondaの使用を推奨します。

#: Minicondaのインストール(AnacondaでもOK)
$ wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh

$ sh Miniconda3-latest-Linux-x86_64.sh

$ source .bashrc

$ conda create -n jupyterhub37 python=3.7

$ conda activate jupyterhub37 

#: jupyterhubと関連パッケージのインストール
$ conda install -c conda-forge jupyterhub

$ conda install jupyter_client

$ git clone https://github.com/jupyterhub/nativeauthenticator.git

$ pip install -e nativeauthenticator/

$ pip install dockerspawner


Dockerのインストール

各ユーザーのnotebook実行サーバは独立したdockerコンテナ内で走るのでdocker-CEをインストールします。 インストール方法は公式ドキュメントの通りです。

$ sudo apt-get -y update && sudo apt-get -y upgrade

$ sudo apt-get remove docker docker-engine docker.io containerd runc

$ sudo apt-get -y install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

$ sudo apt-get -y update

$ sudo apt-get -y install docker-ce docker-ce-cli containerd.io


Notebookサーバ用Docker imageのbuild

各ユーザーのNotebook実行サーバーを走らせるためのdocker imageをbuildします。

以下の内容でDockerfileを作成し、sudo docker build -t hub/test1 . でbuildします。

FROM jupyter/scipy-notebook
USER root
RUN pip install optuna keras
RUN git clone https://github.com/zhiyzuo/python-tutorial.git work
CMD ["jupyterhub-singleuser", "--allow-root"]

Python講習を想定しているのではじめにチュートリアル用のnotebook集githubからcloneしてきます。"python tutorial github "で検索して上の方にあったリポジトリをサンプルに使用しています。

また、scipy-notebookはデータサイエンスに最低限必要なライブラリしかインストールされていないので、この例ではkerasとOptunaを追加インストールしてみます。

rootに切り替えているのは、通常ユーザのままではNotebookサーバーは立ち上がるが新規notebookの作成ができないという状態になったためです。

このトラブルの対処はJupyterHub + dockerspawnerでユーザごとにマウントするボリュームを変える - Qiitaを参考にさせていただきました。


テスト実行

ここまできたらいったんテスト起動してみましょう。

$ mkdir ~/jupyterhub && cd ~/jupyterhub

$ sudo jupyterhub

http;//SERVER_IP:8000へアクセスしてログイン画面が出ればOKです。
httpsではなくhttpであることに注意。

f:id:horomary:20191109163352p:plain

sudo jupyterhubcommand not foundと言われる場合は下記リンクを参考に、visudoで/etc/sudoersをいじりましょう。

sudo したときに「コマンドが見つかりません」と怒られた場合 - 約束の地


jupyterhub_config.pyの作成

まだバニラ状態のjupyterhubが動いただけで、認証はデフォルトのPAM認証(システムユーザー名とパスワードで認証)でありdockerも一切使用していません。


jupyterhubは起動ディレクトリ内にjupyterhub_config.pyというファイルを置くことで認証方法などの詳細な設定が可能になります。

一度起動した後の~/jupyterhubディレクトリを見るとjupyterhub_cookie_secretjupyterhub.sqliteの二つのファイルが生成されているはずです。

このディレクトリ内にさらにjupyterhub_config.pyを下記の内容で追加しましょう。

#: 認証方法と管理ユーザ名の指定
c.JupyterHub.authenticator_class = 'nativeauthenticator.NativeAuthenticator'
c.Authenticator.admin_users = {'admin'}


from jupyter_client.localinterfaces import public_ips
ip = public_ips()[0]
c.JupyterHub.hub_ip = ip

#: SSLを使うなら鍵と証明書の位置を指定
#c.JupyterHub.ssl_key = '/etc/ssl/server.key'
#c.JupyterHub.ssl_cert = '/etc/ssl/server.crt'


c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'

#: Jupyter labを使う
c.Spawner.default_url = '/lab'
c.DockerSpawner.default_url = '/lab'


"""ユーザーの作業ディレクトリの指定
jupyter/scipy-notebook イメージにはjovyanというユーザディレクトリがデフォルトで存在するのでそこを使用する
作業ディレクトリ(/home/jovyan/work)をdocker volumeマウントすることで作業内容が永続化されるように設定する

# jovyanって誰?という疑問についてはこちらを参照
# [https://github.com/jupyter/docker-stacks/issues/358]
"""
notebook_dir = '/home/jovyan/work'
c.DockerSpawner.notebook_dir = notebook_dir
c.DockerSpawner.volumes = {'jupyterhub-user-{username}': notebook_dir}

#: single notebookサーバ用dockerイメージの選択
c.DockerSpawner.container_image = 'hub/test1'

ここで改めてjupyterhubを起動します。

$ sudo jupyterhub
[I 2019-11-09 08:20:02.459 JupyterHub app:2120] Using Authenticator: nativeauthenticator.nativeauthenticator.NativeAuthenticator
[I 2019-11-09 08:20:02.459 JupyterHub app:2120] Using Spawner: dockerspawner.dockerspawner.DockerSpawner-0.11.1
...

ログから設定内容が反映されていることがわかります。

http;//SERVER_IP:8000へアクセスすると、先ほどとは異なりログイン画面下に"Signup!"が追加されています。

f:id:horomary:20191109172436p:plain

まずは"Signup!"からユーザー登録を行いましょう。

config内で管理者に登録されているユーザーも"Signup!"からパスワードを登録する必要があります。

一般ユーザーはアカウントを作成した後、管理者の承認を受ける必要があります(やり方は後述)。

f:id:horomary:20191109172701p:plain

ログインするとJupyterLabが起動します。また、githubからcloneしてきた教材が初期状態で配置されていることが確認できます。

f:id:horomary:20191109173214p:plain

新規ユーザー承認

一般ユーザーはアカウントを作成した後、管理者の承認を受けるとログイン可能になります。

承認のためにはまず管理ユーザーでログインした状態でhttp://SERVER_IP:8000/hub/authorizeにURLの直接打ち込みでアクセスします。やや面倒ですがNativeAuthenticatorではGUIアクセスは実装されていないっぽいです。

f:id:horomary:20191109174717p:plain

承認ボタンを押せば承認作業完了です。


おわりに

ブラウザからアクセスできるPythonのマルチユーザー環境は今回想定したようなワークショップ以外にも、グループでの共同開発や出先でのデモンストレーションなど様々なユースケースがあるかと思います。

公式リポジトリに様々なオプションが用意されているので用途に合わせた最高のJupyterhub環境を構築しましょう。

参考

CentOS 7にJupyterHub 1.0を導入(SSL対応/NativeAuthenticator/DockerSpawner) - hiroki-sawano's diary

JupyterHub + dockerspawnerでユーザごとにマウントするボリュームを変える - Qiita

DockerSpawnerをカスタムして細かいフォルダ共有制御を実現している例

おまけ:ログアウト

ログアウトの方法はわかりづらいのですが、"FIles"にあります。

f:id:horomary:20191109173812p:plain

"Hub Control Panel"からGUIアクセスできる"Admin"ダッシュボードはNativeAuthenticatorを使用している場合は飾りなので無視してください。

おまけ:Volume

dockerの基本的な話ではありますが永続化されたフォルダのvolumeは以下のように確認できます。

$ sudo docker volume ls
DRIVER              VOLUME NAME
local               jupyterhub-user-admin
local               jupyterhub-user-testuser1