Jupyterhub 多用户分析平台在线和离线部署(自定义用户认证)

news2024/10/13 21:55:26

Jupyterhub

文章目录

  • Jupyterhub
    • 1、简介
    • 2、安装配置(在线)
      • 2.1 安装准备
      • 2.2 安装jupyterhub
      • 2.2 自定义身份验证器
      • 2.3 自定义单用户jupyter服务生成器
      • 2.4 配置 jupyterhub_config.py
      • 2.4 启动服务
      • 2.5 登录测试
        • 2.5.1 用户登录 http://da.db.com
        • 2.5.2 管理界面登录 http://da.db.com/hub/admin
      • 2.6 为不同用户分别添加内核
      • 3、离线部署
        • 3.1 方式一
        • 3.2 方式一
      • 4、其他配置
        • 4.1 服务证书配置
        • 4.2 域名配置注意点

1、简介

JupyterHub是为多个不同用户提供Jupyter-notebook环境的最佳方式。由于JupyterHub为每个用户管理一个单独的Jupyter环境,因此它可以用于学生班级、企业数据科学组或科学研究组。它是一个多用户Hub,生成、管理和代理单用户Jupyter-notebook服务器的多个实例。(单个Jupyter-notebook服务可以配置为Jupyter-lab服务)。

发行版本:
The Littlest JupyterHub 适用于少量用户(1-100)的简单服务环境,,是一个简化的Jupyterhub。

Zero to JupyterHub with Kubernetes 适用于更多用户的动态服务版本,Jupyterhub部署在Kubernets集群上。(单台Jupyterhub服务器,大量用户同时使用会竞争资源)

架构:

在这里插入图片描述

  • Hub:是Jupyterhub的核心(tornado process)
  • Http proxy:用于接受来自客户端浏览器的请求
  • Spawners:生成、管理多个单用户Jupyter notebook服务进程
  • Authenticator:用户身份验证

另外:可以通过 config.py 文件添加可选配置;通过admin面板管理用户。

服务流程:

  • Hub 启动一个代理
  • 默认情况下,代理将所有请求转发到Hub
  • Hub处理用户登录(Authenticator)并根据需要生成单用户Jupyter notebook服务进程(Spawners)
  • Hub将用户请求url重定向单用户Jupyter notebook 服务器(/user/)

2、安装配置(在线)

本次先安装单机版 Jupyterhub,官方强烈建议 Jupyterhub on k8s,但Jupyterhub原理都一样.

2.1 安装准备

  • Centos7.9

  • Python 3.8 或更高版本

  • Node.js 12 或更高版本

    # 下载nodejs
    > wget https://mirrors.huaweicloud.com/nodejs/v16.20.2/node-v16.20.2-linux-x64.tar.gz
    # 解压
    > tar -xf node-v16.20.2-linux-x64.tar.gz
    # 创建链接
    > ln -s ~/node-v16.20.2-linux-x64/bin/node  ~/bin/
    
    > node -v
    v16.20.2
    
  • 域名配置(可选)

    da.db.com --> x.x.x.x:8000

2.2 安装jupyterhub

anaconda3 下载 清华开源镜像站

#1. 安装 anaconda3
> sh Anaconda3-2024.06-1-Linux-x86_64.sh

#2. 配置命令(用户家目录.bash_profile文件(登录时自动执行),已将$HOME/bin目录加入$PATH,如果无效 source .bash_profile)
> ln -s ~/anaconda3/bin/conda ~/bin
> ln -s ~/anaconda3/bin/pip3 ~/bin
> ln -s ~/anaconda3/bin/python3 ~/bin

#3. 安装Jupyterhub 
> conda install -c conda-forge jupyterhub # 安装jupyterhub 和 proxy
> conda install -c conda-forge jupyterhub-idle-culler # 可选额外服务,可杀死闲置的单用户jupyter进程,减少资源浪费

#4. 测试安装是否成功
> ln -s ~/anaconda3/bin/jupyterhub ~/bin
> ln -s ~/anaconda3/bin/jupyterhub-singleuser ~/bin    # 启动单用户服务需要使用
> ln -s ~/anaconda3/bin/configurable-http-proxy ~/bin  # 代理启动
> ln -s ~/anaconda3/bin/jupyterhub-idle-culler ~/bin   # 自动清理闲置的单用户jupyter服务进程

> configurable-http-proxy -h
> jupyterhub -h

2.2 自定义身份验证器

Jupyterhub 多用户身份验证,默认使用jupyterhub.auth.PAMAuthenticator 验证器,利用unix/linux系统的用户账户和密码来进行身份验证。

Jupyterhub 身份验证分两步:

  1. 身份验证:验证用户身份

  2. 授权认证:允许通过身份验证的人访问Jupyterhub

自定义身份认证: 官方介绍

import pandas as pd

# 自定义身份验证类()
class CustomAuthenticator(Authenticator):

    # 新增用户(注意:此函数每次启动jupyterhub都会执行此函数)
    def add_user(self, user): 
        username = user.name     
        self._check_user(username,passwd=username,type_=2) # 本地用户文件中增加用户,但无法配置用户密码,该函数主要目的是在jupyterhub.sqlite中用户数据库增加允许访问Hub的用户
        if not self.validate_username(user.name):
            raise ValueError(f"Invalid username: {user.name}")
        if self.allow_existing_users and not self.allow_all:
            self.allowed_users.add(user.name) # 从hub允许登录集合中添加(jupyterhub.sqlite中用户数据库也会跟增加)

        
    # 删除用户
    def delete_user(self, user):
        username = user.name
        self._check_user(username,type_=3) # 从本地用户文件中删除
        self.allowed_users.discard(user.name)  # 从hub允许登录集合中删除(jupyterhub.sqlite中用户数据库也会跟着删除)
       
   
    # 用户验证
    async def authenticate(self,handler,data):
        username = data['username']
        passwd = data['password']
        if self._check_user(username,passwd,type_=1):
            return username
        else:
            return None
        
     # 用户验证
    def _check_user(self,username,passwd=None,type_=1):
         # 本地用户文件 
         users_path = '/自己路径/users.csv'
         users_data = pd.read_csv(users_path,dtype={'passwd':str})
         pwd = users_data.loc[users_data['user'] == username,['passwd']]
         
         # 用户已存在
         if pwd.size:
              # 用户密码验证
              if type_ == 1: 
                 if pwd.iloc[0].item() == passwd:
                    print('用户身份验证成功')
                    return True
                 else:
                    raise ValueError('用户身份验证失败')
                
              # 新增用户
              elif type_ == 2:
                 print('用户已存在')
                
              # 用户删除
              else:
                 users_data.loc[users_data['user'] != username,:].to_csv(users_path,index=False)
                 print('用户删除成功')
         else:

              if type_ == 2:
                  pd.concat([users_data,pd.DataFrame({'user':[username],'passwd':[passwd]})],axis=0).to_csv(users_path,index=False)
                  print('用户添加成功')
              else:
                  raise ValueError('用户不存在')


2.3 自定义单用户jupyter服务生成器

Jupyterhub 默认使用LocalProcessSpawner生成器,要求通过身份验证的用户在linux系统用户中存在。不能在Windows上工作。

from jupyterhub.spawner import LocalProcessSpawner

# 自定义单用户jupyter生成器
class CustomSpawner(LocalProcessSpawner):
     
     # 此处设置jupyterlab 工作目录,可修改,username是Authenticator的返回结果
     home_dir_template = Unicode('/自定义工作目录路径/jupyterhub/{username}',
                                 config=True,
                                 help="""Template to expand to set the user home.{username} is expanded to the jupyterhub username.""",
                                 )

     home_dir = Unicode(help="The home directory for the user")

     @default('home_dir')
     def _default_home_dir(self):
         return self.home_dir_template.format(username=self.user.name)

     def make_preexec_fn(self, name):
         home = self.home_dir
     
         # 创建每个用户工作目录
         def preexec():
             try:
                 os.makedirs(home, 0o755, exist_ok=True)
                 os.chdir(home)
             except Exception as e:
                 self.log.exception("Error in preexec for %s", name)

         return preexec

     def user_env(self, env):
         env['USER'] = self.user.name
         env['HOME'] = self.home_dir
         env['SHELL'] = '/bin/bash'
         return env

     def move_certs(self, paths):
         """No-op for installing certs."""
         return paths
     

2.4 配置 jupyterhub_config.py

#1. 生成配置文件
> jupyterhub --generate-config  # 会在当前文件下生成jupyterhub_config.py文件

#2.服务配置
> vim jupyterhub_config.py

'''
## 设置每个用户的 book类型 和 工作目录(创建.ipynb文件自动保存的地方)
c.Spawner.default_url = '/lab'         # 使用jupyterlab 代替jupyter notebook
c.Spawner.notebook_dir = '~'           # 将每个人的jupyter工作目录,设定为自己用户名文件夹下
# c.Spawner.args = ['--allow-root']    # 运行以root用户启动;此参数可配置jupyterlab 或jupyter命令 启动时的参数

## configurable_http_proxy 代理设置
c.ConfigurableHTTPProxy.api_url = 'http://localhost:8001' # hub与http代理进行通信的API端点的URL,这应该是默认值不写也行
c.ConfigurableHTTPProxy.should_start = True #允许hub启动代理 可以不写,默认的,为False 就需要自己去 启动configurable-http-proxy
# proxy 对外暴露的端口
c.JupyterHub.ip = '0.0.0.0'
c.JupyterHub.port = 8000
# hub服务地址
c.JupyterHub.hub_bind_url = 'http://127.0.0.1:8082'

## 用户验证配置 authenticator
c.JupyterHub.authenticator_class = 'jupyterhub.auth.CustomAuthenticator'  # 采用自定义身份验证器

c.Authenticator.allow_existing_users = True #允许通过 JupyterHub API或管理页面/hub/admin 管理用户(只管理通过身份认证的用户与hub之间的访问权限)
'''当添加用户时:\
   如果allow_existing_users为True,该用户将自动添加到allowed_users集和数据库中,则重新启动Hub将不需要手动更新配置文件中的allowed_users设置,因为用户将从数据库加载。\
   如果allow_existing_users为False,则不允许未通过配置(如allowed_users)授予访问权限的用户登录,即使他们存在于数据库中。
'''
c.Authenticator.admin_users = {'zyp'}  # 管理员用户

c.Authenticator.allow_all = False  # 允许所有通过身份验证的人,有访问jupyterhub的权限
c.Authenticator.allowed_users = set() # 允许部分通过身份验证的人,有访问jupyterhub的权限
c.Authenticator.delete_invalid_users = True  # 从jupyterhub.sqlite用户数据库中自动删除没有通过身份认证的用户


## 单用户进程孵化器 spawner
c.JupyterHub.spawner_class = 'jupyterhub.spawner.CustomSpawner'   # 单用户jupyter服务生成器

# 额外服务 单用户jupyter进程关闭服务,默认3600s后kill,减少资源浪费
c.JupyterHub.services = [
    {
        'name': 'idle-culler',
        'command': ['python3', '-m', 'jupyterhub_idle_culler', '--timeout=3600'], 
    }
]

c.JupyterHub.load_roles = [
    {
        "name": "list-and-cull", # name the role
        "services": [
            "idle-culler", # assign the service to this role
        ],
        "scopes": [
            # declare what permissions the service should have
            "list:users", # list users
            "read:users:activity", # read user last-activity
            "admin:servers", # start/stop servers
        ],
    }
]

## 其他文件配置
c.JupyterHub.cookie_secret_file = '/自己路径/jupyterhub_cookie_secret'
c.JupyterHub.db_url = 'sqlite:自定义存储路径/jupyterhub.sqlite'
c.JupyterHub.pid_file = '/自己路径/jupyterhub.pid'

'''

2.4 启动服务

# 启动服务(无安全认证)
> jupyterhub  -f=/自己路径/jupyterhub_config.py --no-ssl   # 指定生成的配置文件路径

# 后台服务启动(无安全认证)
> nohup jupyterhub  -f=/自己路径/jupyterhub_config.py --no-ssl >> jupyterhub.log 2>&1 &

2.5 登录测试

2.5.1 用户登录 http://da.db.com

在这里插入图片描述

在这里插入图片描述

  • 2.5.2 管理界面登录 http://da.db.com/hub/admin

在这里插入图片描述

2.6 为不同用户分别添加内核

内核生成参考文档:jupyter-lab 添加内核、修改工作目录、多行输出、指定浏览器等常用配置

# 展示所有可以内核
> jupyter kernelspec list

<< EOF
Available kernels:
  python3.8_da    /home/用户名/.local/share/jupyter/kernels/python3.8    # 新添加Python3.8 内核
  python3         /home/用户名/anaconda3/share/jupyter/kernels/python3   
EOF

# 为用户配置内核
> cp -r ~/.local/share/jupyter/kernels  /自定义用户工作目录/jupyterhub/zyp/.local/share/jupyter/

在这里插入图片描述

3、离线部署

3.1 方式一

在联网机器上安装好anaconda3和配置好jupyterhub后,直接整体拷贝到离线机器,即开开箱使用(使用docker移植更为方便
注意点:

  1. 整个anaconda3环境或envs下虚拟环境移植,需提前打包成文件python.tar.gz后再拷贝传输,传输过程中不易丢失文件
  2. 离线机器的用户和安装目录最好与联网机器保持一致,python/bin下一些可执行命令文件里包含路径信息(路径不一致就需要修改命令文件)
3.2 方式一

若离线机器已python或anaconda环境,则进行离线包的安装。

  1. 直接copy联网机器下的site-packags的相关包到离线机器下(此种方式可能需要进行一些命令文件的配置python/bin)
  2. 复制离线安装包
#联网机器
> conda install --download-only xxx     # 离线包默认存储目录 anaconda3/pkgs/xxx.conda
# 离线机器
> conda install xxx.conda

4、其他配置

4.1 服务证书配置
# 生成自签名证书和私钥文件
> openssl req -x509 -newkey rsa:4096 -keyout mykey.pem -out mycert.cert -days 365 -nodes

# 修改jupyterhub_config.py 配置文件
> vim jupyterhub_config.py

'
c.JupyterHub.ssl_key = '/自己路径/mykey.pem'
c.JupyterHub.ssl_cert = '/自己路径/mycert.cert'
'

# 重新启动服务
> nohup jupyterhub  -f=/自己路径/jupyterhub_config.py  >> jupyterhub.log 2>&1 &

这里没有验证

4.2 域名配置注意点

使用域名da.db.com做服务映射,再做ip:port的http或https代理时,注意jupyterhub服务请求包含4类websocket请求会报错,需要增加websocket代理

  • ws://da.db.com/user//api/events/subscribe
  • ws://da.db.com/user//api/kernels//channels*
  • ws://da.db.com/user//terminals/websocket
  • ws://da.db.com/user/*/lsp/ws/pylsp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2185229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

synchronized底层是怎么通过monitor进行加锁的?

一、monitor是什么 monitor叫做对象监视器、也叫作监视器锁&#xff0c;JVM规定了每一个java对象都有一个monitor对象与之对应&#xff0c;这monitor是JVM帮我们创建的&#xff0c;在底层使用C实现的。 ObjectMonitor() {_header;_count ; // 非常重要&#xff0c;表示锁计数…

3 个简单的微分段项目

与许多大型网络安全项目一样&#xff0c;微分段似乎很复杂、耗时且成本高昂。 它涉及管理有关设备间服务连接的复杂细节。 一台 Web 服务器应连接到特定数据库&#xff0c;但不连接到其他数据库&#xff0c;或者负载平衡器应连接到某些 Web 服务器&#xff0c;同时限制与其他…

图解大模型计算加速系列:vLLM源码解析1,整体架构

整个vLLM代码读下来&#xff0c;给我最深的感觉就是&#xff1a;代码呈现上非常干净历练&#xff0c;但是逻辑比较复杂&#xff0c;环环嵌套&#xff0c;毕竟它是一个耦合了工程调度和模型架构改进的巨大工程。 所以在源码解读的第一篇&#xff0c;我想先写一下对整个代码架构…

Golang | Leetcode Golang题解之第449题序列化和反序列化二叉搜索树

题目&#xff1a; 题解&#xff1a; type Codec struct{}func Constructor() (_ Codec) { return }func (Codec) serialize(root *TreeNode) string {arr : []string{}var postOrder func(*TreeNode)postOrder func(node *TreeNode) {if node nil {return}postOrder(node.Le…

java基础 day1

学习视频链接 人机交互的小故事 微软和乔布斯借鉴了施乐实现了如今的图形化界面 图形化界面对于用户来说&#xff0c;操作更加容易上手&#xff0c;但是也存在一些问题。使用图形化界面需要加载许多图片&#xff0c;所以消耗内存&#xff1b;此外运行的速度没有命令行快 Wi…

针对考研的C语言学习(2019链表大题)

题目解析&#xff1a; 【考】双指针算法&#xff0c;逆置法&#xff0c;归并法。 解析&#xff1a;因为题目要求空间复杂度为O(1)&#xff0c;即不能再开辟一条链表&#xff0c;因此我们只能用变量来整体挪动原链表。 第一步先找出中间节点 typedef NODE* Node; Node find_m…

latex有哪些颜色中文叫什么,Python绘制出来

latex有哪些颜色中文叫什么&#xff0c;Python绘制出来 为了展示xcolor包预定义的颜色及其对应的中文名称&#xff0c;并使用Python打印出来&#xff0c;我们可以先列出常见的预定义颜色名称&#xff0c;然后将它们翻译成中文&#xff0c;并最后用Python打印出来。 步骤 列出…

家庭记账本的设计与实现+ssm(lw+演示+源码+运行)

摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;家庭记账本小程序被用户普遍使用&#xff0c;为方便用户能…

MySQL高阶2066-账户余额

目录 题目 准备数据 分析数据 总结 题目 请写出能够返回用户每次交易完成后的账户余额. 我们约定所有用户在进行交易前的账户余额都为0&#xff0c; 并且保证所有交易行为后的余额不为负数。 返回的结果请依次按照 账户&#xff08;account_id), 日期( day ) 进行升序排序…

leetcode_238:除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂…

Conditional Generative Adversarial Nets

条件生成对抗网络 1.生成对抗网络 生成对网络由两个“对抗性”模型组成&#xff1a;一个生成模型 G&#xff0c;用于捕获数据分布&#xff0c;另一个判别模型 D&#xff0c;用于估计样本来自训练数据而不是 G 的概率。G 和 D 都可以是非线性映射函数。 为了学习数据 x 上的生…

设计模式-生成器模式/建造者模式Builder

构建起模式&#xff1a;将一个复杂类的表示与其构造分离&#xff0c;使得相同的构建过程能够得出不同的表示。&#xff08;建造者其实和工厂模式差不多&#xff09; 详细的UML类图 图文说明&#xff1a;距离相同的构建过程 得出不同的展示。此时就用两个类&#xff08;文本生成…

探索未来:hbmqtt,Python中的AI驱动MQTT

文章目录 **探索未来&#xff1a;hbmqtt&#xff0c;Python中的AI驱动MQTT**1. 背景介绍2. hbmqtt是什么&#xff1f;3. 安装hbmqtt4. 简单的库函数使用方法4.1 连接到MQTT服务器4.2 发布消息4.3 订阅主题4.4 接收消息4.5 断开连接 5. 应用场景示例5.1 智能家居控制5.2 环境监测…

WebGIS之Cesium三维软件开发

目录 第 1 章 三维 WebGIS 概述 1.1 Google Earth 1 1.2 SkylineGlobe 2 1.3 LocaSpace Viewe 2 1.4 Cesium 3 1.5 Cesium API 概要 4 第 2 章 Cesium 快速入门 2.1 Cesium 环境搭建 7 2.1.1 安装 Node.js 环境 7 2.1.2 配置 Cesium 依赖 8 2.2 搭建第一个 Cesi…

【2006.07】UMLS工具——MetaMap原理深度解析

文献&#xff1a;《MetaMap: Mapping Text to the UMLS Metathesaurus》2006 年 7 月 14 日 https://lhncbc.nlm.nih.gov/ii/information/Papers/metamap06.pdf MetaMap&#xff1a;将文本映射到 UMLS 元数据库 总结 解决的问题 自动概念映射问题&#xff1a;解决如何将文本…

Vue3丨进一步了解这 20 个响应式 API,写码如有神

前面说的话 在 Vue2 中&#xff0c;个人觉得对于数据的操作比较 “黑盒” 。而 Vue3 把响应式系统更显式地暴露出来&#xff0c;使得我们对数据的操作有了更多的灵活性。所以&#xff0c;对于 Vue3 的几个响应式的 API &#xff0c;我们需要更加的理解掌握&#xff0c;才能在实…

【MySQL】子查询、合并查询、表的连接

目录 一、子查询 1、单行子查询 显示SMITH同一部门的员工信息 2、多行子查询 in关键字 查询和10号部门的工作岗位相同的雇员的名字、岗位、工资、部门号&#xff0c;但是筛选出的雇员的部门不能有10号部门 all关键字 查询工资比30号部门中所有雇员工资高的雇员的姓名、…

TS(type,属性修饰符,抽象类,interface)一次性全部总结

目录 1.type 1.基本用法 2.联合类型 3.交叉类型 2.属性修饰符 1.public 属性修饰符 属性的简写形式 2.proteced 属性修饰符 3.private 属性修饰符 4.readonly 属性修饰符 3.抽象类 4.interface 1.定义类结构 2.定义对象结构 3.定义函数结构 4.接口之间的继…

postgresql|数据库|postgis编译完成后的插件迁移应该如何做(postgis插件最终章)

一、 本文的写作理由 postgis插件一般是编译安装&#xff0c;编译安装的原因是可以选择自己喜欢的版本&#xff0c;但编译的难度也是比较高的&#xff0c;因为有各种依赖&#xff0c;依赖之间还有依赖&#xff0c;非常容易形成依赖循环&#xff0c;因此&#xff0c;失败率是比…

【Python】CSVKit:强大的命令行CSV工具套件

CSVKit 是一个基于命令行的工具集&#xff0c;用于简化 CSV 文件的处理和管理。它提供了从数据转换、筛选、格式化到分析的全方位支持&#xff0c;特别适合需要处理复杂表格数据的用户。相比传统的 Excel 操作&#xff0c;CSVKit 更高效且功能更强大&#xff0c;非常适合数据分…