Zero to JupyterHub with Kubernetes @aliyun

简介: ## 序言 JupyterHub是一个可以支持多个客户同时在线的Jypter管理平台 ### JupyterHub的目标 • A cloud provider such as Google Cloud, Microsoft Azure, Amazon EC2, IBM Cloud,Alibaba Cloud… • Kubernetes to manage resources on the

序言

JupyterHub是一个可以支持多个客户同时在线的Jypter管理平台

JupyterHub的目标

• A cloud provider such as Google Cloud, Microsoft Azure, Amazon EC2, IBM Cloud,Alibaba Cloud…
• Kubernetes to manage resources on the cloud
• Helm to configure and control the packaged JupyterHub installation
• JupyterHub to give users access to a Jupyter computing environment
• A terminal interface on some operating system

引子

JupyterHub并没有提供alibaba的指导,因此本文补充在JupyterHub在aliyun 容器服务上从零开始的步骤。
此外在GPU的使用上通过GPU共享方案--CGPU来提高GPU的利用率。

操作步骤

创建kubernetes集群

  1. 创建容器服务集群
  2. 添加GPU节点
  3. 设置GPU节点为共享模式,参考《尝鲜阿里云容器服务Kubernetes 1.16,拥抱GPU新姿势》

安装JupyterHub

安装Helm

阿里云容器服务目前默认支持的Helm版本为v3。
https://github.com/helm/helm/releases/ 页面找到最新的版本,下载helm文件,并添加到对应的path路径中。

安装JupyterHub

  1. Generate a random hex string representing 32 bytes to use as a security token. Run this command in a terminal and copy the output:
openssl rand -hex 32
  1. 创建PVC和StorageClass信息
    创建Nas存储,并建立挂载点。参考链接 https://help.aliyun.com/document_detail/144398.html?spm=a2c4g.11186623.6.757.71aa2b8djPh6fE

如下文件存储为storage.yaml 文件,并通过 `kubectl apply -f storage.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: alicloud-nas-subpath
mountOptions:
- nolock,tcp,noresvport
- vers=3
parameters:
  volumeAs: subpath
  server: "0994fd65-66f5.cn-zhangjiakou.extreme.nas.aliyuncs.com:/share"   #需要放自己的nas的挂载点,操作参考 https://help.aliyun.com/document_detail/144398.html?spm=a2c4g.11186623.6.757.71aa2b8djPh6fE
provisioner: nasplugin.csi.alibabacloud.com
reclaimPolicy: Retain
#---
#kind: PersistentVolumeClaim
#apiVersion: v1
#metadata:
#  name: hub-db-dir
#  namespace: jhub
#spec:
#  accessModes:
#    - ReadWriteMany
#  storageClassName: alicloud-nas-subpath
#  resources:
#    requests:
#      storage: 1Gi
  1. 修改原始config文件
  2. 修改config.yaml文件中各个镜像的路径,避免拉取google仓库的镜像而造成的失败
  3. 因为当前使用的版本0.8.2不能和k8s1.16正确匹配,在install脚本中添加了对应的path 脚本参考 https://github.com/jupyterhub/kubespawner/issues/354
  4. 修改pod申请gpu资源的配置,设置CGPU的模式 aliyun.com/gpu-mem: 4 https://zero-to-jupyterhub.readthedocs.io/en/latest/customizing/user-resources.html

     以上修改已经在下面的config.yaml文件中完成了修改。 注意proxy.secretToken必须换为第一步生成的信息
    
proxy:
  secretToken: "d8d198d787f22869e67df3ad3ac5f4d99a843c20243f9ed785f77822fb4ce517" ## 该token选用自己在步骤1中生成的即可
prePuller:
  continuous:
    enabled: false
  extraImages: {}
  hook:
    enabled: true
    image:
      name: jupyterhub/k8s-image-awaiter
      tag: 0.8.2
  pause:
    image:
      # 替换默认的google镜像
      name: registry.cn-zhangjiakou.aliyuncs.com/kubernetesmirror/pause 
      tag: "3.1"
hub:
  #image:
  #  name: jupyterhub/k8s-hub
  #  tag: 0.9.0-beta.3
  #  0.8.2  # 尝试提高该版本来与kubernetes 1.16匹配,待验证https://github.com/jupyterhub/kubespawner/issues/354
  db:
    password: null
    pvc:
      accessModes:
      - ReadWriteOnce
      annotations: {}
      selector: {}
      storage: 1Gi
      storageClassName: alicloud-nas-subpath
singleuser:
  storage:
    capacity: 2Gi
    dynamic:
      pvcNameTemplate: claim-{username}{servername}
      storageAccessModes:
      - ReadWriteOnce
      storageClass: alicloud-nas-subpath
      volumeNameTemplate: volume-{username}{servername}
  profileList:
    - display_name: "CGPU Server" ## 共享GPU使用模式
      description: "Spawns a notebook server with access to a CGPU"
      kubespawner_override:
        extra_resource_limits:
          aliyun.com/gpu-mem: 2
    - display_name: "GPU Server"  ## 普通GPU使用模式
      description: "Spawns a notebook server with access to a GPU"
      kubespawner_override:
        extra_resource_limits:
          nvidia.com/gpu: 1
  image:
    #name: jupyterhub/k8s-singleuser-sample
    #name: tensorflow/tensorflow
    pullPolicy: IfNotPresent
    # 替换为自己需要的镜像即可,本例中使用的是支持TensorFlow的镜像,可以从官方网站上去找合适的镜像
    name: registry.cn-hangzhou.aliyuncs.com/kubeflow-images-public/tensorflow-notebook
    tag: 1.15.2
  1. 执行安装脚本
    将如下内存存储为install.sh 文件,并将步骤3存储的config.yaml 文件放在同一个目录下,执行安装命令

bash sh ./install.sh

# Suggested values: advanced users of Kubernetes and Helm should feel
# free to use different values.
RELEASE=jhub
NAMESPACE=jhub
helm upgrade --install $RELEASE jupyterhub/jupyterhub \
  --namespace $NAMESPACE  \
  --version=0.8.2 \
  --values config.yaml -v 6
sleep 30
export NAMESPACE=jhub
kubectl patch deploy -n $NAMESPACE hub --type json --patch '[{"op": "replace", "path": "/spec/template/spec/containers/0/command", "value": ["bash", "-c", "\nmkdir -p ~/hotfix\ncp -r /usr/local/lib/python3.6/dist-packages/kubespawner ~/hotfix\nls -R ~/hotfix\npatch ~/hotfix/kubespawner/spawner.py << EOT\n72c72\n<             key=lambda x: x.last_timestamp,\n---\n>             key=lambda x: x.last_timestamp and x.last_timestamp.timestamp() or 0.,\nEOT\n\nPYTHONPATH=$HOME/hotfix jupyterhub --config /srv/jupyterhub_config.py --upgrade-db\n"]}]'

注意:“kubectl patch deploy...” 该命令执行是在安装helm后30秒后执行,注意耐心等待,不要提前终止

验证与使用

  1. 验证pod和svc的状态均为正常
jumper(⎈ |zjk-gpu:jhub)➜  ~ k get pod -n jhub
NAME                     READY   STATUS    RESTARTS   AGE
hub-86d7754c55-jnsd8     1/1     Running   0          10h
proxy-657b654c85-htl62   1/1     Running   0          10h
jumper(⎈ |zjk-gpu:jhub)➜  ~ k get svc -n jhub
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
hub            ClusterIP      172.21.10.208   <none>        8081/TCP                     10h
proxy-api      ClusterIP      172.21.13.171   <none>        8001/TCP                     10h
proxy-public   LoadBalancer   172.21.15.40    47.92.24.78   80:30889/TCP,443:31823/TCP   10h
  1. 根据通过svc proxy-public 对应的公网IP访问网站,由于没有设置用户密码,可以随意设置
    01.png
  2. 如下图是在config.yaml文件中配置的多个profile,分别是申请普通的GPU资源,以及共享型的GPU资源
    02.png
  3. 如下图,正在创建正在使用的pod
    03.png
  4. 查看命名空间 jhub下的pod的情况,有一个jupyter-${用户名}的pod生成
jumper(⎈ |zjk-gpu:jhub)➜  54_cgpu_demo git:(master) ✗ k get pod
NAME                     READY   STATUS    RESTARTS   AGE
hub-5ff8cff85f-nmhfl     1/1     Running   0          46h
jupyter-lilong           1/1     Running   0          17s
proxy-657b654c85-8mn6t   1/1     Running   0          46h
  1. 至此,环境创建成功。

问题记录

搭建过程中的问题与记录

问题1 NoneType

错误信息
[E 2020-05-30 00:24:14.373 JupyterHub base:1011] Preventing implicit spawn for a because last spawn failed: '<' not supported between instances of 'NoneType' and 'NoneType'
说明: 已知问题,参考 https://github.com/jupyterhub/kubespawner/issues/354
上面在安装helm chart之后的“kubectl patch deploy...”就是修复该问题

问题2 存储

不管是hub的创建,还是每个客户运行自己环境创建的pod均需要使用到存储,如果pod启动pending,且kubectl describe pod * 里面显示存储资源不足,可以参考nas相关的存储的设置。 https://help.aliyun.com/document_detail/144398.html?spm=a2c4g.11186623.6.757.71aa2b8djPh6fE

参考

  1. NAS动态存储卷 https://help.aliyun.com/document_detail/144398.html
  2. JupyterHub在k8s上的安装 https://zero-to-jupyterhub.readthedocs.io/en/latest/
  3. 自定义环境 https://zero-to-jupyterhub.readthedocs.io/en/latest/customizing/user-environment.html
相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
7月前
|
机器学习/深度学习 传感器 编解码
DINOv3上手指南:改变视觉模型使用方式,一个模型搞定分割、检测、深度估计
DINOv3是Meta推出的自监督视觉模型,支持冻结主干、仅训练轻量任务头即可在分割、深度估计等任务上达到SOTA,极大降低训练成本。其密集特征质量优异,适用于遥感、工业检测等多领域,真正实现“一个模型走天下”。
5031 2
DINOv3上手指南:改变视觉模型使用方式,一个模型搞定分割、检测、深度估计
|
存储 Ubuntu 搜索推荐
构建多用户的 Jupyter 服务器 —— 利用 JupyterHub
【8月更文第29天】**摘要** JupyterHub 是一个易于使用的、可伸缩的、多用户的 Jupyter Notebook 服务器。它允许您在一个集中式服务器上托管多个独立的 Jupyter Notebook 会话,非常适合团队协作和教学环境。本文将详细介绍如何安装和配置 JupyterHub,以及如何利用它来构建一个多用户 Jupyter 服务器环境。
5516 0
|
11月前
|
人工智能 API 开发者
狂揽7.5k星!这款开源API网关彻底解放开发者:一键聚合GPT-4、Suno、Midjourney,还能在线充值!
New API 是一款基于 One API 二次开发的 AI 模型接口管理与分发系统,支持多种大模型(如 GPT-4、Suno、Midjourney 等)统一封装为 OpenAI 格式接口调用。其核心功能包括多模型统一网关、企业级权限管控、“推理力度”分级、无魔法访问全球 AI 服务、灵活计费体系及开发者友好设计。技术架构采用 Golang + Gin 框架,支持高并发低延迟,适用于企业内部 AI 中台、多模型 SaaS 平台、学术研究协作及个人开发者工具等场景。项目开源地址:https://github.com/kingbug/new-api。
6838 10
|
机器学习/深度学习 Kubernetes 监控
Jupyter 集群管理:大规模部署的最佳策略
【8月更文第29天】当涉及大规模部署 Jupyter 笔记本服务器时,组织通常需要考虑如何有效地管理这些资源,以便支持多用户、高可用性和高性能的需求。Jupyter 集群管理不仅关乎于提供一个稳定的开发环境,还涉及到安全性、可扩展性和资源优化等问题。
752 1
|
运维 Serverless 云计算
解锁协作与创新的钥匙:计算巢&JupyterHub 引领数据驱动新时代
在这个数字化转型的时代,JupyterHub 为教育、研究和企业提供了一种强大且灵活的解决方案,帮助团队和个人高效地协作和探索数据。无论您是数据科学家、教育工作者还是开发团队的一员,JupyterHub 都能通过其无与伦比的功能和易用性提升您的生产力和创新能力。计算巢提供
|
NoSQL 关系型数据库 Redis
高可用和性能:基于ACK部署Dify的最佳实践
本文介绍了基于阿里云容器服务ACK,部署高可用、可伸缩且具备高SLA的生产可用的Dify服务的详细解决方案。
|
存储 Kubernetes 网络协议
Kubernetes 集群部署 NFS-Subdir-External-Provisioner 存储插件
Kubernetes 对 Pod 进行调度时,以当时集群中各节点的可用资源作为主要依据,自动选择某一个可用的节点,并将 Pod 分配到该节点上。在这种情况下,Pod 中容器数据的持久化如果存储在所在节点的磁盘上,就会产生不可预知的问题,例如,当 Pod 出现故障,Kubernetes 重新调度之后,Pod 所在的新节点上,并不存在上一次 Pod 运行时所在节点上的数
9252 3
Kubernetes 集群部署 NFS-Subdir-External-Provisioner 存储插件
|
Ubuntu Shell
【Ubuntu系统】三步更新自己的Cmake最新版本
Ubuntu系统中通过三步简单流程更新Cmake到最新版本的具体操作方法,包括卸载旧版本、下载并运行安装脚本以及创建软链接。
4358 1
|
NoSQL 网络安全 Redis
Redis 密码设置和查看密码
【7月更文挑战第28天】
4261 3