フリーランチ食べたい

No Free Lunch in ML and Life. Pythonや機械学習のことを書きます。

【JupyerHub】アカウント作成時/ログイン時に処理を行う、ログインユーザーの環境変数を設定する

f:id:mergyi:20190105234225p:plain

JupyterHubの日本語記事が少ないので書いていこうと思います。

TL;DR

  • アカウント作成時は c.LocalAuthenticator.add_user_cmd で設定
  • ログイン時は c.Spawner.pre_spawn_hook で設定
  • 環境変数c.Spawner.environment で設定

Version

jupyterhub==0.9.1

(事前準備) configファイルを作成

もし設定ファイルを作成していない場合は下のコマンドで生成してください。

jupyterhub --generate-config
# => jupyterhub_config.py が生成される

これ以降の設定は全て jupyterhub_config.py で行っていきます。

アカウント作成時に処理を行う

アカウント作成時の設定は、 jupyterhub.auth moduleで行います。

jupyterhub_config.py

c.LocalAuthenticator.add_user_cmd = ['some_cmd']
# デフォルト: c.LocalAuthenticator.add_user_cmd = ['adduser', '-q', '--gecos', '""', '--disabled-password']

デフォルトはアカウント作成のみ行っています。ちなみにあまりみかけないoption --gecos については以前調べたので良かったら見てみてください。

blog.ikedaosushi.com

自分は、アカウント作成に加えていくつか処理を行いたかったので、下のようなshell scriptを作成してそれを呼び出しています。

add_user.sh

#!/bin/bash
username="${1}"

# some operation

adduser -q --gecos "" --disabled-password "${username}"

jupyterhub_config.py

c.LocalAuthenticator.add_user_cmd = ['./add_user.sh']

ログイン時

ログイン時の処理は jupyterhub.spawner moduleで設定します。spawnという単語はあまり馴染みありませんが、魚などが産卵するという意味 のようです。JupyteHubでは spawner はログインしたユーザーのプロセスを管理するモジュールを指します。masterプロセスから派生してプロセスを生む様子をspawnと表現したということですね。

ログイン時の処理はPythonの関数で渡します。例のようにsubprocessなどを使えばshell scriptも当然実行できます。

jupyterhub_config.py

from subprocess import check_call
def pre_spawn_hook(spawner):
    username = spawner.user.name
    check_call(['./login.sh', username])

c.Spawner.pre_spawn_hook = pre_spawn_hook
# デフォルト: c.Spawner.pre_spawn_hook = None

受け取っているのは Spawner オブジェクトです。 取得できる値は ドキュメント を参照ください。 (Spawner.userに関する言及はないのがちょっと気になりますが😓)

またログアウト時の処理も同様に c.Spawner.post_stop_hook で設定できます。

環境変数の設定

最後はログインユーザーへの環境変数の設定です。例えば共通のAPIサーバーのエンドポイントなど、ログインユーザー共通で環境変数を設定したい場面があると思います。 ログイン時の設定と同様 jupyterhub.spawner moduleで設定します。

環境変数の設定方法は2つあります。

masterプロセスから環境変数を受け渡す

1つ目の方法は、masterプロセス、つまりjupyterhubを動かしているプロセスの環境変数をログインユーザーに受け渡す方法です。下のように設定します。

jupyterhub_config.py

c.Spawner.env_keep = ['SOME_ENV']
# デフォルト: c.Spawner.env_keep = ['PATH', 'PYTHONPATH', 'CONDA_ROOT', 'CONDA_DEFAULT_ENV', 'VIRTUAL_ENV', 'LANG', 'LC_ALL']

ホワイトリスト制になっていて、設定した環境変数のみログインユーザーに受け渡します。

専用に設定する

2つ目の方法は、ログインユーザー専用に環境変数を設定する方法です。下のようにdictで設定します。

jupyterhub_config.py

c.Spawner.environment = {'SOME_ENV': 'FOO'}
# デフォルト: c.Spawner.environment = {}

自分は環境変数だけ切り出して管理したかったので、 python-dotenvと組み合わせて使っています。

.spawnenv

SOME_ENV=FOO

jupyterhub_config.py

from dotenv import dotenv_values
c.Spawner.environment = dotenv_values('.spawnenv')

こうすることで設定ファイルを汚さずスッキリ書くことができます。

最後に

  • 今回はJupyterHubの設定について紹介しました。
  • 現在会社でJupyteHubを運用しているのですが、実用するとやっぱりやりたいことがたくさんでてきますね。
  • まだいくつかネタがあるので継続的に書いていきたいと思います!

参考