Help us understand the problem. What is going on with this article?

AWSでJupyterHub (JupyterHubのセットアップ)

概要

全体概要は,AWSでJupyterHub (概要) にあるので,参照してください.

今回は,前回インストールしたAnacondaを使ってJupyterHubを組み立てていきます.
また,JupyterHub自体にWebサーバの機能を持っていますが,今回はnginxをWebサーバにおいて,その後ろにJupyterHubを置くような構成にしていきます.

おしながき

  • JupyterHub用ユーザの作成
  • JupyterHubのインストール
  • JupyterHubの設定
    • jupyterhub-config.pyの中身
  • JupyterHubの起動
  • nginxとの接続

前回同様,今回も基本的にec2-userで操作していきます.
細かい説明を入れていくので,記事としては長めになっていますのでご了承ください <(_ _)>

JupyterHub用ユーザの作成

インストールしただけでは,複数ユーザで利用することが出来ないです.また,目的に合わせて権限周りは設定していくべきです.
なので今回は,「jupyterhubグループに属するユーザが利用できる」ように設定しておきます.
次のように設定していきます.

  • jupyterhubグループの追加
  • ec2-userにjupyterhubを追加
  • /opt/anaconda3配下のグループをjupyterhubに変更
  • anacondaの確認

ec2-userへのグループ追加は便宜上,設定しておくものです.きちんと作業用ユーザを用意している場合は,そのユーザに対して追加するほうがよいでしょう.

groupaddを使ってjupyterhubグループを作成して,gpasswdを使ってec2-userにグループ追加していきます.
以下の画像のような流れになってます.
グループが付いているか確認するには,id {username}で確認できます.
※グループ追加したての時は,その接続では有効になっていないので,設定が終わったら再ログインして設定を反映させたほうが良いです

グループ追加.png

/opt/anaconda3のグループを変更していきます.
変更は以下のコマンドになります.
権限もotherに与えないように770にしておきます.

chgrp -R jupyterhub /opt/anaconda3
chmod 770 -R /opt/anaconda3

JupyterHub実行ユーザの追加

ec2-userでJupyterHubを動かしてもいいのですが,せっかくなので専用ユーザで実行するようにします.
グループは先ほど作ったので,それを割り当てるようにします.
JupyterHubだけ動かすアプリユーザということで,ログインできないようにnologinをつけておきます.

sudo useradd -s /sbin/nologin jupyterhub -g jupyterhub

id jupyterhubと入力すれば,jupyterhubユーザの情報が出力されて作成されたことを確認できます.

Anacondaの確認

ec2-user/opt/anaconda3/bin/condaとオプションなしで打ち込むと,「( ゚Д゚)<指定しろや!」ってヘルプ情報をずらーっと出してきます.出てくれば,権限や設定周りがうまくいってそうだということで次に進みます.

パスを通す

今回は特に気にしないのですが,普段からcondaコマンドを利用する場合は,/opt/anaconda3/binにパスを通しておくと何かと便利です.
ホームディレクトリに移動して,.bashrcを編集ツールを使って,最後に以下を追記して保存します.

export PATH=/opt/anaconda3/bin:$PATH

追加出来たら,再ログインするか source .bashrc で設定を反映させます.

JupyterHubのインストール

さっそく,JupyterHubをインストールしていきます.
インストールは以下のコマンドを使います.

/opt/anaconda3/bin/conda install -c conda-forge jupyterhub

# パスを通していれば,こちらでもOK
conda install -c conda-forge jupyterhub

実行すると,リポジトリから探してきて,インストールが必要なパッケージをリストアップしてくれます.
「インストールしてよいか?」と聞かれるので,インストールさせてあげましょう.
しばらく作業していますが,そのうち終わります.
インストール完了したら,以下のコマンドで確認します.

/opt/anaconda3/bin/conda list

このコマンドはAnacondaにインストールされたパッケージを出力してくれます.
このなかに「jupyterhub」のパッケージがあれば,成功しています.
numpyやscikit-learnなど機械学習でよく使われるパッケージはあらかじめインストールされていますが,リストになくて必要なものがあれば,同様にパッケージをインストールしていけば良いのですが,Anacondaは環境ごとにパッケージ管理できるので,この方法でないほうが良いこともあります.(バージョン固定させたいときなど)

JupyterHubの設定

JupyterHubのインストールが終われば,次は設定を行っていきます.
最初は設定ファイルがないので,設定ファイルを作るところから始めていきます.
まず次のコマンドを実行して,設定ファイルを置く場所を作ります.

sudo mkdir /etc/jupyterhub
sudo chmod 770 /etc/jupyterhub
sudo chown jupyterhub:jupyterhub /etc/jupyterhub

次に,以下のコマンドで,設定ファイルを作ります.

cd /etc/jupyterhub/
sudo -u jupyterhub /opt/anaconda3/bin/jupyterhub --generate-config

実行すると,Writing default config to: jupyterhub_config.py と出力されればカレントディレクトリに設定ファイルが出力されています.
もしディレクトリにwrite権限がないと,エラーログが出力されます.
今,出力されたファイルはバックアップも兼ねてデフォルトファイルとしておきます.(しなくてもいいのですが念のため)

sudo -u jupyterhub mv /etc/jupyterhub/jupyterhub_config.py /etc/jupyterhub/jupyterhub_config.py.default

バックアップ用ファイルが出来たらさっそく,jupyterhub-config.pyの作成に取り掛かります.
認証方式は,いろいろあるのですが,今回はLinuxユーザがJupyterHubユーザとして利用するようにしていきます.(ほんとはLDAP認証したかったけどね...)

jupyterhub-config.pyの中身

以下のような設定にします.ファイルはPythonなので,Pythonの文法であればどんな書き方でも大丈夫です.
不要な行は#を使ってコメントアウトすることが出来ます.

/etc/jupyterhub/jupyterhub-config.py
c.JupyterHub.bind_url = 'http://127.0.0.1:8080'

c.Spawner.notebook_dir = '~/notebook'
# c.Spawner.notebook_dir = '/mnt/jupyterhub/{username}/notebook'
# c.Spawner.default_url = '/lab'

c.Authenticator.admin_users = {
  'ec2-user'
}

c.Authenticator.whitelist = {
  'ec2-user',
  'testuser'
}
項目 概要 設定例
c.JupyterHub.bind_url str JupyterHubがリクエストを受け取るためのURLです.ポート番号もここで指定します. http://127.0.0.:8080
c.Spawner.notebook_dir str JupyterHubが利用するnotebookデータのディレクトリを指定します.これはユーザごとに管理されます.~はユーザのホームディレクトリを表していて,{username}とするとユーザ名に置き換わるようになります.(プレスホルダー機能) ~/notebook
c.Spawner.default_url str c.JupyterHub.bind_urlの後ろにつけるURLです.上記のコードではhttp://127.0.0.1:8080/labというようになります.この項目を利用することで,既存システムに追加できるようになっています.labとするとnotebookからJupyterLabに変わります. /lab
c.Authenticator.admin_users set 管理者権限を持つユーザの一覧です.空にすると,管理者がいない状態になります.
c.Authenticator.whitelist set この一覧にあるユーザだけログインすることが出来るようになります.

設定ファイルが出来たら,ec2-userのホームディレクトリにnotebookというディレクトリを作っておきましょう.

mkdir ~/notebook

不足しているものをインストール

設定ファイルを作るだけではなく,JupyterHubを起動する際にnpmconfigurable-http-proxyが必要なので,追加でインストールしていきます.

npmのインストール

# リポジトリの取得
curl -sL https://rpm.nodesource.com/setup_8.x | sudo bash -

# nodejsのインストール
sudo yum install -y nodejs

# 確認
npm -v

configurable-http-proxyのインストール

sudo npm install -g configurable-http-proxy

JupyterHubに接続してみる

ということで,JupyterHubを起動してみます.
起動コマンドは以下のような感じになります.

cd /etc/jupyterhub
/opt/anaconda3/bin/jupyterhub

起動すると起動ログと一緒にエラーが出てきます.
エラーの内容がError adding user testuser already in db というものであれば,「testuserってユーザがシステムにないよ?」といっているので,ひとまず無視して問題ないです.(後で足していくので)
nginxとつなげるので,Ctrl + Cで止めておきます.

nginxとの接続

AWSでJupyterHub (nginx) で後回しにしていたnginxの設定ファイルに手を加えていきます.
/etc/nginx/nginx.confにある設定を以下のようにlistenの部分をコメントアウトします.

/etc/nginx/nginx.conf
...(省略)...

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
#  ★★ 以下2行のlistenをコメントアウトする ★★
#        listen       80 default_server;
#        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

...(省略)...

次に,/etc/nginx/conf.d/に移動します.このディレクトリは初めは空っぽで,/etc/nginx.confが参照するようになっています.
ここに,以下の設定情報を書いたjupyterhub.confというファイルを作ります.
通常のproxyの設定に合わせて,JupyterHubがwebsocketを利用していることから,それに合わせた設定も追加しておきます.

/etc/nginx/conf.d/jupyterhub.conf
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen       80 default_server;
    server_name  xxx.yyy.zzz;                              # ←ここにJupyterHubに接続するためのドメインを指定する
    root         /usr/share/nginx/html;

    access_log /var/log/nginx/jupyterhub.log main;

    client_max_body_size 4M; # 413 Request Entity Too Large

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # websocket headers
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_read_timeout 86400;
        proxy_set_header Origin "http://localhost:8080";
    }
}

nginxが80ポートで受け取って,8080番ポートに受け流す設定になってます.
JupyterHubはファイルのアップロード機能もついているので,アップロード可能のファイルサイズもclient_max_body_sizeで指定しておきます.
この設定によって捌かれたリクエストは/var/log/nginx/jupyterhub.logに記録されるようになっています.出力フォーマットは/etc/nginx.confに定義されてます.

動作確認

JupyterHubとnginxの設定が出来たら,両方とも起動して動作確認してみます.

nginxの起動

まず,sudo systemctl start nginxで起動させます.
Job for nginx.service failed because the control process exited with error code.のような情報が出力されてしまったら設定ファイルに不備がある可能性があるのでsystemctl status nginxと入力して,原因を確認して修正していきます.
先ほど追加した/etc/nginx/conf.d/jupyterhub.confにEC2インスタンスのパブリックDNS名を指定した場合,ドメイン名が長すぎて怒られてしまいます.
そのため,以下のようにserver_names_hash_bucket_sizeの項目を追加しておきます.
設定値は64だと小さいようなので128にしてあります.

/etc/nginx/nginx.conf
... 省略 ...

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    server_names_hash_bucket_size  128;             # ★★ これ ★★

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

... 省略 ...

JupyterHubの起動

nginxが起動したら,先ほどと同様にJupyterHubを起動します.
http://{nginxで指定したサーバー名}/hubとブラウザに打ち込んでアクセスしてみます.
以下のように表示されれば,設定完了です.
ダウンロード.png

/var/log/nginx/jupyterhub.logにもアクセスログが出力されています.
入力フォームに出ているワーニングは,「HTTP接続してんじゃねーよ」って言ってるだけです.あとで,ACMとALBを使ってHTTPS接続できるようにするので放置しておきます.

まとめ

今回は,JupyterHubのインストールと設定,nginxとの接続の3つをやりました.
そして,JupyterHubのログイン画面を表示するところまで進めました.
今回の設定では,ホワイトリストに設定されているLinuxユーザであれば,ログインできるPAM認証というものを使っています.
今のままでは正しくユーザ名・パスワードを入力してもログインが失敗してしまいます.
次回,この失敗を解消させて,JupyterHubにログインできるようにしてきます.

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした