阿里云ECS上CentOS7部署Jupyter Notebook/Lab服务(支持多用户)

对于自己部署的JupyterHub的一次总结,其实本人Linux方面也只小白,很多做法可能不算最佳实践,摸爬滚打终究还是把服务给Host起来了,希望能用自己的经验给其他人一些参考。关于JupyterHub更多细节,可以访问他们的文档。

JupyterHub是为Jupyter Notebook和JupyterLab提供多用户支持的服务,支持在Linux/Unix系统上部署。我主要是为了方便在云服务器上使用JupyterLab,所以尝试部署了下。

安装JupyterHub

JupyterHub目前仅支持在Linux/Unix系统上安装,不支持Windows系统。我是在阿里云ECS实例上部署的,系统直接安装的阿里云提供的CentOS7的镜像。

安装依赖项

安装JupyterHub需要先安装Python3.5+和nodejs/npm。我是在阿里云ECS实例上部署的,因为默认只安装了Python2,出于方便起见,我直接安装的Anaconda 5.3.1。

关于Anaconda3的安装,如果不熟悉的同学可以参考这篇。Anaconda默认会被安装在执行用户的HOME目录下。因为后续会被多用户使用,建议将安装位置放在公共的地方,比如我放在了/opt/anaconda3下头。

安装完成conda后,其实Python3、jupyter也已经安装完成了。另外需要安装下nodejs/npm,执行下面的命令可以进行安装:

conda install -c conda-forge nodejs

安装JupyterHub

如果是已经安装了anaconda,可以使用conda执行下面的命令进行安装:


conda install -c conda-forge jupyterhub

当然也可以使用pipnpm安装:

python3 -m pip install jupyterhub
npm install -g configurable-http-proxy

执行下面的命令确认安装成功:


jupyterhub -h

configurable-http-proxy -h

JupyterHub配置

JupyterHub可以说就是开箱即用的,但是如果有些特殊需求也可以进一步配置。

要配置JupyterHub,首先需要生产一个默认配置文件,执行下面的命令,在执行的目录下会生成一个jupyterhub_config.py文件。

jupyterhub --generate-config

在jupyterhub_config.py文件中找到想要修改的内容,进行修改,并取消注释,然后执行:

jupyterhub -f /path/to/jupyterhub_config.py

就能让JupyterHub按照你的配置运行了。

JupyterHub的配置主要分为以下几大块:Application、JupyterHub、Spawner、Authenticator,涉及的东西不少,具体的按需配置。下面只根据我个人的配置说几个简单的配置项,更多配置请访问官方文档查看

登录方式配置

JupyterHub默认采用PAMAuthenticator授权:c.JupyterHub.authenticator_class = 'jupyterhub.auth.PAMAuthenticator'

这个授权方式其实就是走服务器用户的登录认证。你在服务器加了个user1的用户,你就可以配置允许这个用户登录。

JupyterHub也支持别授权方式,比如接入GitHub、Google的OAuth认证。

登录用户控制

JupyterHub支持多用户登录,对于用户登录的控制也提供多种方式:

  • 用户黑名单控制 – c.Authenticator.blacklist
    写在黑名单的用户会被限制登录。如配置:c.Authenticator.whitelist = { 'user1' },则user1就不能登录了。
  • 用户白名单控制 – c.Authenticator.whitelist
    写在白名单的用户才能登录。如配置:c.Authenticator.whitelist = { 'user1' },则只有user1能登录。该项优先级高于黑名单。
  • 管理员用户 – c.Authenticator.admin_users
    管理员用户可以查看登录的用户,某些授权方式下可以添加/删除用户,可以重启或停止Hub,可以停止其他用户的服务,如果有配置的话还可以访问其用户的内容。
  • 用户组白名单 – c.LocalAuthenticator.group_whitelist
    如果是采用默认的基于本地用户的授权方式,还能够通过用户组白名单来进行授权。如果配置了这项,用户白名单会失效。

c.Authenticator.whitelist是配置控制用户登录的配置项,默认不限制任何用户登录。如果有配置内容,则限制只有配置的这些用户可以登录。如:c.Authenticator.whitelist = { 'user1' },则只有user1能登录。

运行端口

默认JupyterHub运行在8000端口上,可以通过修改默认配置c.JupyterHub.bind_url = 'http://:8000'中的端口号来指定运行的端口。

文件保存位置

默认在JupyterHub下头创建的文件会创建在登录用户的HOME目录下。可以通过修改默认配置c.Spawner.notebook_dir来修改生成文件目录。设置这个值的时候有两个特殊的标识可以用:~会被实际展开为登录用户的HOME目录,{username}会被实际展开为登录用户的用户名。

需要注意配置的目录,登录用户需要有读写权限,不然会出问题。


配置完成后,通过-f指定配置文件,就可以让JupyterHub按你配置的执行了:

jupyterhub -f /path/to/your/jupyterhub_config.py

访问JupyterHub

运行起来后,我们肯定是希望能够通过公网访问,我们可以直接通过端口访问,或者也可以通过Nginx进行反向代理。

开放端口访问

阿里云ECS的端口开放是通过安全组控制的,具体参考阿里云文档

Nginx反向代理

为了通过公网访问,我们可以配置nginx方向代理,将80端口的请求转发到8000端口。我是直接在nginx.conf中修改的,具体配置如下:

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  YOUR_SERVER_NAME;

    # Load configuration files for the default server block.

    location ~* ^/user/\w+/api/kernels {
      proxy_pass http://127.0.0.1:8000;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
    }

    location / {
      proxy_pass http://127.0.0.1:8000;
    }

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

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

上面的配置就是简单的监听80端口(域名备案还没弄下来,所以直接更改默认配置了,有域名的可以把server_name后面改成自己想要的域名),通过proxy_pass http://127.0.0.1:8000;配置就把请求转发给8000端口了。

JupyterHub的API接口里,有个请求很特殊,是个WebSocket请求:
ws://example.com/user/user1/api/kernels/4cad141f-0885-4dd2-b963-7c9b2cc2bf37/channels?session_id=3fe22e75-66f1-4eaa-b00c-5741166d955e&token=9fbea75abdf14fad934951fa36c46f35
如果这个请求简单的走Http代理的话,请求返回会是400Bad Request。好在nginx在1.3版本后支持代理WebSocket协议,所以像上面那样特殊处理下这个请求就可以了。

创建个JupyterHub服务

上面说的运行JupyterHub是直接从命令行运行起来的,调试阶段这样很适合,因为在终端上会一直输出JupyterHub的运行情况。但是真的让它就这样一直跑着,无论从使用还是后续的管理上都不是很方便。最好还是把它变成个系统服务。

vim /usr/lib/systemd/system/jupyterhub.service

在编辑器里像下面这样写:

[Unit]
Description=Jupyterhub
After=network-online.target


[Service]
User=root
Environment="PATH=/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/anaconda3/bin"
ExecStart=/opt/anaconda3/bin/jupyterhub -f /home/.config//jupyterhub_config.py
WorkingDirectory=/etc/jupyterhub

[Install]
WantedBy=multi-user.target

ExecStartWorkingDirectory根据个人实际情况修改,如果不知道jupyterhub是在哪,可以执行whereis jupyterhub查看。

安装JupyterLab和jupyter-labhub

JupyterHub默认是使用Jupyter Notebook,如果有和我一样喜欢用JupyterLab的人,可以参照以下内容进行配置。

关于JupyterLab的更多细节,参见官方文档。

安装JupyterLab和所需拓展

首先得安装JupyterLab。安装了anaconda的话可以直接使用conda安装JupyterLab:


conda install -c conda-forge jupyterlab

也可以通过pip进行安装:


pip install jupyterhub

要想在JupyterHub使用JupyterLab还需要安装个插件,执行下面的命令可以进行安装:


jupyter labextension install @jupyterlab/hub-extension

配置JupyterHub使用JupyterLab

配置JupyterHub使用JupyterLab还需要在修改jupyterhub_config.py文件,修改配置:c.Spawner.cmd = ['jupyterhub-singleuser'],将jupyterhub-singleuser修改为jupyter-labhub,重启服务就行。

后记

在使用服务方式启动JupyterHub的时候如果遇到问题可以执行journalctl -l -u jupyterhub.service | less或者systemctl -l status jupyterhub.service查看服务运行日志来排查问题。

安装完成后,其实还有个遗留的错误:pam_loginuid(login:session): set_loginuid failed。但是因为对于我的使用没有影响我也就没有处理。关于这个问题在JupyterHub项目有Issue,如果有需要处理这个问题的可以查看下这个Issue。


版权声明:本文为jh0218原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。