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

[Ubuntu18.04] JupyterHubによる機械学習環境の構築手順一式(複数人利用想定)

概要

リモートホストにJupyterHubを入れて
複数人で機械学習の勉強ができる環境がほしくなりました
そのための作業手順一式をまとめます。

手順検証にAzureのUbuntu Server 18.04 LTSイメージを使いましたが
ローカルインストールでもいくつかステップ飛ばすだけでだいたい同じはず。
なお、本来AzureであればDataScienceVirtualMachineをデプロイすれば3分で終わる件

ユースケース

  • Windowsの端末からリモートで利用する
  • 複数人でJupyterNoteを使う形式を想定する
  • 各人が仮想環境を作成し自由にモジュールを構成する

システム仕様

  • XRDPでリモートデスクトップ接続もできるようにする
  • JupyterHubで複数プロファイルに対応させる
  • 個人的に運用が安定する気がするAnacondaで環境構築する

とりあえず

ローカルならUbuntu日本語Remixあたりを導入
OS展開後はとりあえずパッケージをアップデート

$ sudo apt update
$ sudo apt full-upgrade

azureなら使いそうなポートは空けておく
22(SSH), 3389(RDP), 8000(JupyterHub)

Ubuntu自体はファイアウォール動いていないようなので
ローカル環境であれば設定はたぶん不要

GNOMEとXRDPを導入

Serverのためかdesktopが入ってないようのでUbuntu18.04から標準になったGNOMEを入れる
また、リモートデスクトップ接続するためにXRDPも入れる
以前のUnityは色々あったけど、GNOMEならXRDP入れるだけでいけそう

$ sudo apt install ubuntu-gnome-desktop
$ sudo apt install xrdp
$ sudo reboot

ざっくり30分ほどかかる

一応これで接続はできるようになるが、接続するたびに認証画面が出てくる
キャンセルすれば問題ないがパスワードを入力すると切断されてしまう
image.png

通らなくても良い処理のようなので
認証処理の定義ファイルを作成して一律拒否ると良いらしい

参考:xRDP – How to Fix the Infamous system crash popups in Ubuntu 18.04 (and previous versions)
http://c-nergy.be/blog/?p=12043
参考:Ubuntu 18.04に xrdpをインストールしてみる
https://cpoint-lab.co.jp/article/201806/ubuntu-18-04に-xrdpをインストールしてみる/

認証ルールの定義ファイルを作成
sudo cat <<EOF | \
   sudo tee /etc/polkit-1/localauthority/50-local.d/xrdp-color-manager.pkla
 [Netowrkmanager]
 Identity=unix-user:*
 Action=org.freedesktop.color-manager.create-device
 ResultAny=no
 ResultInactive=no
 ResultActive=yes
EOF

あとは普通にリモートデスクトップで接続できる

初回ログオン時のウィザードでJapaneseを選択しておけば
右上のメニューから日本語キーボード配置に切り替えられる
image.png

日本語環境設定

最初からUbuntu日本語Remixでインストールすれば不要だと思うが
今回のテスト環境が英語なので日本語モジュールを導入する

参考:【Ubuntu 18.04 LTS Server】日本語環境にする(日本語ロケールとタイムゾーンの変更)
https://www.yokoweb.net/2018/05/04/ubuntu-18_04-lts-server-japanese/

日本語パッケージの導入とシステム言語設定
$ sudo apt install language-pack-ja-base language-pack-ja ibus-mozc
$ sudo localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"
$ sudo reboot   # 一応リブートしてみる
manコマンドも日本語化する
$ sudo apt install manpages-ja manpages-ja-dev
$ man ls    # 動作確認
タイムゾーン変更のウィザードを起動
sudo dpkg-reconfigure tzdata

タイムゾーンをアジア / 東京にする

また、日本語化してからXRDPでログオンするとhomeのフォルダも日本語に変更するか聞かれる
フォルダ名が日本語だと使いづらいしトラブルの元なので変更はしない

もしやっちゃって直したいとき
参考:フォルダ名の英語表記について(Ubuntu)
http://ojamemo.com/pc-software/english-directory-name/

SettingからRegion&Language->ManageInstalledLanguageを開くと
完全じゃないとか言われるのでインストールを実行

一応システム全体に適用を実施する(認証が2回来るのでパスワード入れる)

iBus-Mozcが入力ソースにないと日本語入力できないので
なければ「+」「日本語」「日本語(Mozc)」をで追加する


日本語(Mozc)を一番上にしておく

右上から日本語(Mozc)に変更すれば
あとは半角 / 全角キーで日本語入力ができるようになる

Anacondaのインストール

pyenvとかも色々やってみたが
anacondaをダウンロードして行う手順が一番安定している気がするので
https://www.anaconda.com/download/ からAnaconda3.7をダウンロード

参考:AnacondaでPythonの分析環境をまとめてインストール
https://www.task-notes.com/entry/20151116/1447642800

rootに切り替えてから
ダウンロードしたファイルを実行する
実行権限ないとコケるので付与してから行う

$ sudo su -
# cd /home/user/Downloads
# chmod 755 ./Anaconda3-5.3.1-Linux-x86_64.sh
# ./Anaconda3-5.3.1-Linux-x86_64.sh

ウィザードに沿って進みEULAに合意する。

Welcome to Anaconda3 5.3.1

In order to continue the installation process, please review the license
agreement.
Please, press ENTER to continue
>>>
===================================
Anaconda End User License Agreement
===================================

Copyright 2015, Anaconda, Inc.

All rights reserved under the 3-clause BSD License:
・
・
・
Do you accept the license terms? [yes|no]
[no] >>> yes

黙っていると/rootに入ってしまうので
/usr/local/lib/anaconda3 をインストール先に指定する

インストール先を指定
Anaconda3 will now be installed into this location:
/root/anaconda3

  - Press ENTER to confirm the location
  - Press CTRL-C to abort the installation
  - Or specify a different location below

[/root/anaconda3] >>> /usr/local/lib/anaconda3

インストールが終わると
Do you wish the installer to initailize Anaconda3...と出るが
PATHの設定は後でetcに対してやるので不要

今のユーザーの環境変数にanacondaへのパスを設定するか
Do you wish the installer to initialize Anaconda3
in your /root/.bashrc ? [yes|no]
[no] >>> 

終わったかと思ったら
VS Code入れないかとのお誘い
とりあえず今回はパス

For this change to become active, you have to open a new terminal.

Thank you for installing Anaconda3!

===========================================================================

Anaconda is partnered with Microsoft! Microsoft VSCode is a streamlined
code editor with support for development operations like debugging, task
running and version control.

To install Visual Studio Code, you will need:
  - Administrator Privileges
  - Internet connectivity

Visual Studio Code License: https://code.visualstudio.com/license

Do you wish to proceed with the installation of Microsoft VSCode? [yes|no]
>>> no
root@Ubuntu:/home/user/Downloads#

AnacondaへのPATHを切る(全ユーザー向け)

echo 'export PATH="/usr/local/lib/anaconda3/bin:$PATH"' >> /etc/profile.d/anaconda.sh

1回再起動してからcondaコマンドが呼び出せていればOK

$ conda --version
conda 4.5.11

JupyterHubの導入

複数ユーザー環境に対応させるためJupyterHubを導入する
といってもconda installを流すだけで完了する

参考:JupyterHubの構築
https://qiita.com/cvusk/items/afa46c35d8d5f0d930ed

JupyterHubをインストール
$ sudo su -                     # rootでやる
# conda install jupyterhub

証明書がないのでJupyterHubを--no-sslオプションで起動する
停止するときはCtrl+[c]

JupyterHubを起動(SSLなし)
jupyterhub --no-ssl

ブラウザから http://IPAddress:8000 で接続し
ubuntuのユーザー / パスワードでログインする

あとは普通のJupyterNotebookと同じ要領で使用が可能

JupyterHubの設定

動かすだけならこれでいけるが
Jupyterからプロファイル見えるのもどうかと思うし
ホームディレクトリなど諸々の設定を行う

JupyterHubの設定ファイルを作成
# cd /usr/local/lib/anaconda3/   # 設定ファイルを作るディレクトリに移動
# jupyterhub --generate-config   # 設定ファイルを生成
    Writing default config to: jupyterhub_config.py
# vi jupyterhub_config.py        # 出来上がったファイルを編集する

DesktopやDocumentの並びで
notebooksフォルダをJupyterのルートにするように設定する。

jupyterhub_config.py
c.Spawner.notebook_dir = '~/notebooks'   # ホームディレクトリの設定
指定したJupyter用のホームディレクトリを作成する
# mkdir ~/notebooks           # 今のユーザー(root)用のディレクトリを作成
# mkdir /etc/skel/notebooks   # 今後新たに作られたユーザーにも配置されるようにしておく

SSLの設定

パスワード入力しているのにhttp通信なのは宜しくないので
一応暗号化できるようオレオレ証明書を作成する。
とりあえず証明書置くためのフォルダを作って移動

証明書格納用のフォルダを作成
# cd /usr/local/lib/anaconda3
# mkdir cert
# chmod 600 cert
# cd cert

証明書作成のウィザードはCommon Nameだけ入れれば十分
ブラウザから繋ぐ時のURLホスト名と一致させる(IPで接続するならIPアドレス)

オレオレ証明書の作成
# openssl req -x509 -nodes -newkey rsa:2048 -keyout secret.key > jupyter.pem
    Generating a 2048 bit RSA private key
    ...........................................................................................+++++
    .................................+++++
    writing new private key to 'secret.key'
    -----
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [AU]:
    State or Province Name (full name) [Some-State]:
    Locality Name (eg, city) []:
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:
    Organizational Unit Name (eg, section) []:
    Common Name (e.g. server FQDN or YOUR name) []:192.168.1.101
    Email Address []:

# ls  # サーバー証明書と秘密鍵ができているのを確認
    jupyter.pem  secret.key

作成した証明書と秘密鍵のパスを設定ファイルに記述する

jupyterhub_config.py
c.JupyterHub.ssl_cert = '/usr/local/lib/anaconda3/cert/jupyter.pem'
c.JupyterHub.ssl_key = '/usr/local/lib/anaconda3/cert/secret.key'

今度は--no-sslオプション無しでjupyterhubを起動する

JupyterHubを起動(SSL有効)
jupyterhub

https://IPAddressOrHost:8000 とhttpで接続する
エラーが出てしまうが気にしない。暗号化はされている。

エラーを消したい場合は接続する端末側に証明書をインポートする
(ChromeはこれやってもIP接続では一律警告が出る模様)

「ファイルにコピー」から一旦ローカルに*.cerでエクスポート

インストールウィザードから「信頼されたルート証明機関」にインポートする

ブラウザから再接続すればOK

JupyterHubのサービス化

現行のままだと手動で起動しないとJupyterに接続できないので
JupyterHubをサービス化しサーバー起動時に自動で立ち上がるようにする
(なお、init.dを使用する方法でもかなり頑張ってみたができなかった)

参考:systemdでの自動起動設定
https://qiita.com/shosan87/items/f65b43373b895edb2946

サービス起動時だとPATHの設定が足りないので
まずはPATHを設定するファイルを作るところから

サービス用のPATH設定スクリプトを作成
# echo 'PATH="/usr/local/lib/anaconda3/bin:$PATH"' >> /usr/local/lib/anaconda3/was_config

続けてサービスを定義するUnitファイルを作成する

Unit定義ファイルを作成
# sudo cat <<EOF | \
   sudo tee /etc/systemd/system/jupyterhub.service
[Unit]
Desctiption = JupyterHub

[Service]
EnvironmentFile=/etc/systemd/system/was_config
WorkingDirectory=/usr/local/lib/anaconda3/bin/
ExecStart=/usr/local/lib/anaconda3/bin/jupyterhub -f /usr/local/lib/anaconda3/jupyterhub_config.py
User=root

[Install]
WantedBy = multi-user.target
EOF

Unitファイルの準備ができたら
サービスに自動起動の設定を行いサービスを開始させます

サービスの有効化と開始
# systemctl enable jupyterhub   # サービスを自動起動に設定する
# systemctl start jupyterhub    # サービスを起動する
# systemctl status jupyterhub   # サービスのステータスを確認する
    ● jupyterhub.service
       Loaded: loaded (/etc/systemd/system/jupyterhub.service; enabled; vendor preset: enabled)
       Active: active (running) since Sun 2018-12-01 00:00:00 JST; 20s ago
     Main PID: 2751 (jupyterhub)
        Tasks: 7 (limit: 4703)
       CGroup: /system.slice/jupyterhub.service
               tq2751 /usr/local/lib/anaconda3/bin/python /usr/local/lib/anaconda3/bin/jupyterhub -f 
    /usr/local/lib/anaconda3/jupyterhu
               mq2775 node /usr/local/lib/anaconda3/bin/configurable-http-proxy --ip --port 8000 --api-ip 127.0.0.1 --
    api-port 8001 --e

以上で基本的な導入作業は完了になります。

サーバー起動時には自動でJupyterHubが起動し
稼働状況もsystemctlから確認できます。

# systemctl list-unit-files --type=service
    ・
    ・
    iscsi.service                              enabled
    iscsid.service                             disabled
    jupyterhub.service                         enabled
    kerneloops.service                         enabled

anacondaの仮想環境を利用する

rootになんでもモジュール入れていくとだんだん環境が汚れていくので
各々個別の実行ディレクトリとしてanacondaの仮想環境を作成してそこで作業する

anacondaの仮想環境を作成する
$ conda create -n MyEnv python=3.7.0     # 仮想環境MyEnvをPython3.7.0で作成
$ source activate MyEnv                  # 仮想環境に切り替える

仮想環境に入ったら状態でjupyterで利用するkernelとして登録する

仮想環境をJupyterに登録する
(MyEnv) $ ipython kernel install --user --name=Myenv --display-name=myenv     # Jupyterに登録
    Installed kernelspec MyEnv in /home/username/.local/share/jupyter/kernels/MyEnv

(MyEnv) $ jupyter kernelspec list       # jupyterで利用できるkernel一覧を表示
    Available kernels:
      python3    /usr/local/lib/anaconda3/share/jupyter/kernels/python3
      MyEnv      /home/username/.local/share/jupyter/kernels/MyEnv

これで、jupyterNoteの新規作成時やメニューから
kernel切り替えができるようになる。

参考:Jupyterで複数カーネルを簡単に選択するための設定
https://qiita.com/tomochiii/items/8b937f15c79a0c3eae0e

ユーザーの追加

ユーザーは普通に以下要領で追加する
プロファイルになるディレクトリが必要なので
-m だけ付け忘れないように注意

ユーザーの追加
$ sudo useradd -m newusername   # newusername というユーザーを作成
$ sudo passwd newusername       # パスワードの設定

完了

ほぼ先人の皆様の知恵で構成されていますがこれで概ね運用できるはず。
rootで共通利用できる仮想環境を用意してあげても良いし
各個人で独自に仮想環境作ってもらっても良いと思います。

ある程度環境分離できている雰囲気ですが
完璧にパーミッション設計はしているわけではないので
多少改善の余地はあるかもしれません。

参考

すべて文中に記載

Why do not you register as a user and use Qiita more conveniently?
  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
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