在线 IDE
在线开发是一个很重要的功能,对于大部分用户来说,在线的 IDE 比命令行 vim 要方便很多。CubeStudio 主要提供了 VSCode 和 Jupyter 两种在线 IDE,并没有将代码和数据进行分割存储。所以在 Notebook 中打开的就是完全用户自己的代码和数据,可以方便地进行调试。
VSCode
theia 是一个在线 VSCode,更像本地 IDE,主要服务纯代码开发(多实例,一个人可以同时开多个 theia)。

工作目录默认是 /mnt,归档目录是 /archives,可以把一些想永久保存、不易被误删的文件放在归档目录。

在 VSCode 里面(本质为 theia),用户跟本地 VSCode 基本一致,可以上传下载文件/文件夹,也可以在 theia 中打开命令行终端。并且其中封装了用户的基本环境需求,比如 Python。
需要说明的是,由于 theia 的功能中有些进程(例如 rg 进程)会不停地搜索扫描目录下的所有文件。由于个人目录下包含了用户的代码和数据,文件可能非常多(千万到亿级别的文件数量),这些进程扫描会严重拖慢分布式存储的性能。所以 CubeStudio 做了定时检杀的功能,能够及时检杀 rg 和 git 进程,提高在线 VSCode 的响应速度。
Jupyter
数据挖掘的用户使用 Jupyter 会更多一些。在 Jupyter 里面跟 VSCode 里面相同,也安装了一些实用的插件,比如 tensorboard,使用 Jupyter Pro 版本可以在 Jupyter 里面打开。
比如我们在 pipeline/example/tensorboard 中有一个示例文件 demo.py,运行这个文件会生成一个 fit_logs 文件夹,这就是 TF 的 log 目录,进入这个目录后使用 tensorboard 按钮启动 tensorboard,就可以查看该训练的情况。
大数据版本
大数据版本的 Jupyter Notebook,创建 Notebook 时选择 Jupyter(bigdata)镜像,集成了大数据常用的基础包,比如 Spark、Flink 等。支持爬虫、数据分析、数据挖掘和可视化等常用 Python 包的使用。
机器学习版本
机器学习版本的 Jupyter Notebook,创建 Notebook 时选择 Jupyter(machinelearning)镜像,集成了机器学习常用的基础包,比如 sklearn、scipy 等。
深度学习版本
深度学习版本的 Jupyter Notebook,创建 Notebook 时选择 Jupyter(DeepLearning)镜像,集成了深度学习常用的基础包,比如 TensorFlow、Keras 等。
RStudio
R 版本的 Notebook,创建 Notebook 时选择 rstudio(bigdata)镜像,集成了 R 语言的在线 IDE,IDE 名称为 RStudio。
Matlab
MATLAB 版本的 Notebook,创建 Notebook 时选择 matlab(deeplearning)镜像,集成了 MATLAB 的在线 IDE。
注意:Matlab 需要企业申请 Matlab 有效账户,并开通 r2023a 版本的 license。
依据:可选镜像由配置项
NOTEBOOK_IMAGES决定(myapp/config.py:998)。当前默认配置中 Matlab 镜像(matlab-ubuntu-deeplearning)是被注释掉的(myapp/config.py:1017),即开箱默认不可选;管理员如需启用,需在NOTEBOOK_IMAGES中放开该行并具备有效 license。其余jupyter(bigdata/machinelearning/deeplearning)、jupyter-conda-pro(cpu)、rstudio(bigdata)均为默认启用。
Pro 版本
Pro 版本的 Jupyter 中可使用不同版本的 Python 内核,从 Python 2.7 到 Python 3.9 均可支持。

tensorboard 可视化训练
Pro 版本的 Jupyter 有 tensorboard,创建 Notebook 时镜像选择 jupyter-conda-pro(cpu),创建一个 Pro 版本的 Jupyter,运行 /mnt/$username/pipeline/example/tensorboard/demo.py,运行结束会产生结果文件。进入结果文件夹,此时点击"+"符号,打开 tensorboard,再选择需要进行可视化的文件,即可查看可视化结果,如下图所示。

需要注意的是,集成了 tensorboard 的 Notebook 是 CPU 版本的。因此,如果我们需要用 GPU 来训练模型,并且用 tensorboard 做可视化,可以用 GPU 版本的 Notebook 来做模型训练,把需要可视化的结果文件写到分布式存储中,再在 Pro 版本的 Notebook 中打开 tensorboard。
密码保护
需要修改 config.py 配置文件中 ENABLE_JUPYTER_PASSWORD 设置为 True(默认值为 False)并更新到线上,重启后端,则会在每个 Jupyter 后面自动生成密码,每次进入 Jupyter 要使用这个密码。
依据:
myapp/config.py:988默认ENABLE_JUPYTER_PASSWORD = False;myapp/views/view_notebook.py:713处if conf.get('ENABLE_JUPYTER_PASSWORD', False):时为 Jupyter 生成登录密码。

登录 Jupyter 时需要密码:

SSH 远程连接 Jupyter 功能
实现原理
Jupyter 版本的 Notebook 中提供了 sshd,会在 Notebook 创建时自动启动 ssh-server,并且会自动生成配置文件 example/ssh链接。
并为每个 Notebook 的 Pod 配置一个单独的 Service,支持通过 ip:port 访问。
端口分配以 config.py 的 NOTEBOOK_PORT 为准(仓库默认配置为 10000+2*ID),平台会在该基准端口上预留多个端口:
基准端口+0:IDE Web 服务端口(例如 JupyterLab / Theia / RStudio / Matlab 等)基准端口+1:sshd端口(用于ssh远程连接,对应环境变量SSH_PORT)基准端口+2/+3:预留给用户在 Notebook 内启动自定义服务(对应环境变量PORT1/PORT2)
依据(与代码核对):仓库默认
config.py:1105配置为NOTEBOOK_PORT='10000+2*ID'(注释"至少间隔 4");仅当该配置缺失时,代码兜底默认才取10000+10*ID(myapp/views/view_notebook.py:689,conf.get('NOTEBOOK_PORT','10000+10*ID'))。端口分配的+0/+1/+2/+3含义与view_notebook.py:688注释及697-699行环境变量赋值一致。实际端口以你部署的config.py取值为准。
需要公司网络能通过 ip+端口 的形式访问 Notebook 的服务。
操作方法
按照 example/ssh链接 文件中的描述,在本地 ~/.ssh/config 中添加链接配置:
# 将此文件内容追加到 ~/.ssh/config
# root 登录密码为 notebook 的英文名称
# ssh-copy-id -p PORT root@HOST 本地设置免密登录
Host cube-studio
HostName xx.xx.xx.xx
Port xx
User root
ServerAliveInterval 10
ControlMaster auto
然后就可以 SSH 链接远程 Notebook 了,并且可以在本地将文件拖拽到本地 VSCode,这样文件就会自动同步到在线 Notebook 中。
单端口代理 Jupyter 内部 ssh server
使用 ProxyJump 功能:
Host proxy
HostName jumpserver_host # 这里是内网代理机器的 ip
User jumpserver_user # 这里是内网代理机器的用户名
Port jumpserver_port # 这里是内网代理机器的端口
# 下面就是 CubeStudio 的原始 ssh 连接
Host cube-studio-admin-pro
HostName xxxxx
Port xxx
User root
ServerAliveInterval 10
ControlMaster auto
ProxyJump proxy # 添加此处代理
SSH 链接时 matplotlib 弹窗的问题
Mac 电脑:
本地安装 XQuartz,本地 VSCode 安装 remote-ssh 插件,SSH 连接在线 IDE,连接后在容器命令行执行:
apt-get install -y openssh-server xauth x11-apps python3 python3-pip python3-tk
pip install matplotlib
export DISPLAY=:10.0
然后就可以运行 matplotlib 画图的 Python 代码了。
Windows 设置:
参考:https://blog.csdn.net/beginner_921/article/details/142493855
- 本地和远程 VSCode 都安装 Remote X11
- 本地安装 VcXsrv,
vcxsrv-64.1.20.14.0.installer - 安装后打开 XLaunch,不修改配置
- 本地安装 VcXsrv(or XMing)的目录下会有一个
X0.hosts文件,在其中增加一行服务器 ip - 在远程 IDE 命令行增加
export DISPLAY="xx.xx.xx.xx:0.0",其中xx.xx.xx.xx是你电脑的内网 ip
Jupyter 里面连接 Spark
对于需要连接数据中台的场景(例如连接 Hive 或 Spark 集群),我们可以在自定义 Notebook 中预先配置好相关的 XML 文件,以便用户直接使用。这样开发者只需要配置一次,普通用户就可以直接使用,无需再次配置。
在 Jupyter 中启动提交 Spark 任务,作为 driver 端需要监听端口。每个 Notebook 在创建的时候会预留 $PORT1 和 $PORT2 两个环境变量代表的端口来对外监听,同时在 $SERVICE_EXTERNAL_IP 环境变量代表的主机上进行监听,所以需要告诉 Spark 的 master,driver 的服务监听地址,这样能让 master 返回数据到 driver 端。
依据:
PORT1/PORT2/SERVICE_EXTERNAL_IP等环境变量由myapp/views/view_notebook.py:663-699注入 Notebook Pod。
# 创建 SparkSession
spark = SparkSession.builder \
.appName("PythonPi") \
.master('spark://myspark-master-0.myspark-headless.kubeflow.svc.cluster.local:7077') \
.config("spark.executor.memory", "2g") \
.config("spark.executor.cores", "2") \
.config("spark.cores.max", "8") \
.config("spark.driver.memory", "2g") \
.config("spark.ui.enabled", False) \
.config("spark.driver.port", os.getenv('PORT1')) \
.config("spark.blockManager.port", os.getenv('PORT2')) \
.config("spark.driver.bindAddress", '0.0.0.0') \
.config("spark.driver.host", os.getenv('SERVICE_EXTERNAL_IP')) \
.getOrCreate()
tensorboard
使用 Pro 版本的 Jupyter,在左侧目录树进入到 tensorboard 对应的日志目录,再打开右侧的 tensorboard 按钮。

就可以查看日志目录中所包含的训练过程中的信息和模型的信息。

git 功能
Pro 版本的 Notebook 中可以直接使用 git。比如直接 clone 一个项目到 Notebook 中,修改文件,点击 git 图标,就能直接看到原文件和修改后文件的对比。

GPU、CPU、内存监控
图示按钮可帮助用户在 Notebook 中查看资源的使用情况。需要注意的是,只有 GPU 版本的 Notebook 可以在 Notebook 中查看 GPU 监控,其他版本的 Notebook 即使调用了 GPU,也只能在 Grafana 中统一查看 GPU 资源的监控。

Jupyter 多内核态
在使用自定义 Notebook 时,需要注意安装包时应该先激活对应的环境,然后再进行安装。这是因为 Jupyter 的内核和 conda 环境是两个不同的概念,需要分别进行管理。
在线 IDE 的资源占用问题
CubeStudio 采用的方案是只设置 Notebook 的 Pod 的 limit,而不设置 request。这种方案就对资源不进行独占,这样也就不用清理 Notebook,只是允许了 Notebook 中的资源干扰。
GPU 的占用方式上,允许独占、共享、VGPU 三种方式。GPU 申请(单位卡)示例:填写 1、2,表示训练任务每个容器独占整卡;填写 -1 为共享占用方式;填写小数(0.1)为 vGPU 方式;申请具体的卡型号可以类似 1(V100),目前支持 T4 / V100 / A100。

在线 IDE 的环境重置问题
如果 Notebook 因为 OOM、定时清理、机器故障、主动 reset 等可能原因而重启,Notebook 中的环境就会丢失,但分布式存储下的内容都会保留,也就是 /mnt/$username 文件夹下的内容都会保留。
所以如果我们需要环境保存,有两个方案:
- CubeStudio 添加了 Notebook 启动后自动执行
/mnt/$username/init.sh脚本的功能,用户只需要在init.sh中定义 Notebook 特定的环境,就可以在启动 Notebook 后拥有自己独特的环境。 - 在 Notebook 中有一个"镜像保存"按钮,每次 Notebook 环境更改之后都可以点击这个按钮保存环境,下次重启就会自动用这个镜像来启动 Notebook,如下图所示。
依据:Notebook 启动命令中会执行
/init.sh与/mnt/$username/init.sh(myapp/views/view_notebook.py:558、708)。

多实例的 VirtualService 代理
多实例在线 IDE 图示:

每个用户可以配置多个在线 IDE,可以自己配置资源、镜像、类型。每个在线 IDE 都是通过 istio VirtualService 来代理的。所以只要在线 IDE 的镜像启动的 web 服务支持 URL prefix,就可以被加进来作为在线 IDE,比如 Matlab、RStudio。每个在线 IDE 实例都有独立的、以名称为 prefix 的 URL 地址,在 VirtualService 配置绑定 istio ingressgateway,这样来实现多实例。
名为 admin-9d3d 的在线 IDE 的 URL prefix:

名为 admin-e00f 的在线 IDE 的 URL prefix:

在线 IDE 镜像保存
如果想保存自己 Notebook 中的环境,可以在 Notebook 列表中点击"镜像保存"的按钮,平台将自动将该 Notebook 的 Pod 通过 docker commit 成镜像,镜像名称默认为 ccr.ccs.tencentyun.com/cube-studio/jupyter-user:$notebook-name,并推送到仓库,所以还需要管理员提前配置自己内网的仓库地址和账号密码。
依据:镜像名由配置项
NOTEBOOK_TARGET_IMAGES决定,默认ccr.ccs.tencentyun.com/cube-studio/jupyter-user:{name}({name}为 Notebook 名称),见myapp/views/view_notebook.py:1091。
在线 IDE 清理和续期
默认情况下,定时清理任务只是关闭容器、不会清理文件;重启容器后环境会丢失(分布式存储 /mnt/$username 内容仍保留)。每次有效期为 3 天,清理前一天会提醒用户进行续期。
依据(与代码核对):
- 定时任务
task.delete_notebook在myapp/tasks/schedules.py的 celery beat 调度中默认是注释掉的(myapp/config.py:708-712),即开箱默认不自动清理,需要手动开启调度。- 有效期由配置项
ENABLE_JUPYTER_EXPIRY控制,默认60*60*24*3秒 = 3 天(myapp/tasks/schedules.py:189)。- 当前实现中,
delete_notebook任务仅清理 GPU 版本 的过期 Notebook(代码filter(Notebook.resource_gpu!='0'),myapp/tasks/schedules.py:198),过期前一天会推送续期提醒。 清理范围与开启状态以你部署的实际版本与配置为准。
定时清理任务的配置
config.py 中的 task_delete_notebook(celery beat 调度项)控制是否定时清理 Notebook。修改配置以后要重启 infra 命名空间的 schedule 和 worker 组件。
任务续期
点击对应 Notebook 后的续期按钮,可以为当前 Notebook 续期使用时间(实现上把 changed_on 刷新为当前时间,从而重新计算过期时间,见 myapp/views/view_notebook.py 的 renew)。
