Skip to content

Jupyter Notebook GPU 环境部署指南

适用环境: K3s + HAMi vGPU 集群
最后更新: 2026-08-22


目录

  1. Jupyter 简介
  2. 镜像选择与国内配置
  3. 部署方案
  4. 访问与使用
  5. 自定义环境
  6. GPU 使用示例
  7. 运维指南
  8. 故障排查

1. Jupyter 简介

Jupyter Notebook 是一个交互式计算环境,广泛用于数据探索、机器学习、可视化和教学演示。

架构示意

浏览器 → Jupyter Server (HTTP/WebSocket) → Python Kernel → GPU (CUDA)

        Notebook 文件 (.ipynb)

版本选择

发行版适用场景镜像大小
jupyter/base-notebook纯 Python 数据分析~500MB
jupyter/scipy-notebook科学计算~1.2GB
jupyter/tensorflow-notebookTensorFlow 深度学习~4GB
jupyter/pytorch-notebookPyTorch 深度学习~5GB

2. 镜像选择与国内配置

2.1 推荐镜像

bash
# PyTorch GPU 版本(推荐)
jupyter/pytorch-notebook:cuda12-latest

2.2 国内拉取与推送

bash
# 从华为云镜像拉取
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/jupyter/pytorch-notebook:cuda12-latest

# 重新打标签
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/jupyter/pytorch-notebook:cuda12-latest \
  jupyter/pytorch-notebook:cuda12-latest

# 推送到本地 Registry
REGISTRY="117.50.188.237:30000"
docker tag jupyter/pytorch-notebook:cuda12-latest \
  ${REGISTRY}/jupyter/pytorch-notebook:cuda12-latest
docker push ${REGISTRY}/jupyter/pytorch-notebook:cuda12-latest

2.3 pip 国内源

在 Notebook 第一个 Cell 中执行:

python
import subprocess
subprocess.run(["pip", "config", "set", "global.index-url",
    "https://pypi.tuna.tsinghua.edu.cn/simple"])

2.4 HuggingFace 镜像

yaml
env:
- name: HF_ENDPOINT
  value: "https://hf-mirror.com"
- name: HF_HOME
  value: "/home/jovyan/.cache/huggingface"
---

## 3. 部署方案

### 3.1 单用户 Deployment

```yaml
# jupyter-gpu.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jupyter-gpu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jupyter-gpu
  template:
    metadata:
      labels:
        app: jupyter-gpu
    spec:
      schedulerName: hami-scheduler
      nodeSelector:
        kubernetes.io/hostname: "10-60-205-41"
      containers:
      - name: jupyter
        image: 117.50.188.237:30000/jupyter/pytorch-notebook:cuda12-latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8888
          name: http
        env:
        - name: JUPYTER_TOKEN
          value: "your-secure-password"
        - name: HF_ENDPOINT
          value: "https://hf-mirror.com"
        - name: GRANT_SUDO
          value: "yes"
        resources:
          requests:
            cpu: "1"
            memory: "4Gi"
            nvidia.com/gpu: "1"
            nvidia.com/gpumem: "6k"
          limits:
            cpu: "4"
            memory: "8Gi"
            nvidia.com/gpu: "1"
            nvidia.com/gpumem: "6k"
        volumeMounts:
        - name: workspace
          mountPath: /home/jovyan/work
        - name: models
          mountPath: /models
          readOnly: true
        - name: cache
          mountPath: /home/jovyan/.cache
      volumes:
      - name: workspace
        persistentVolumeClaim:
          claimName: jupyter-workspace
      - name: models
        persistentVolumeClaim:
          claimName: nfs-modelscope
          readOnly: true
      - name: cache
        emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: jupyter-gpu
spec:
  selector:
    app: jupyter-gpu
  ports:
  - port: 8888
    targetPort: 8888
    nodePort: 30888
  type: NodePort

3.2 持久化工作目录

yaml
# jupyter-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jupyter-workspace
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 50Gi

3.3 部署命令

bash
kubectl apply -f jupyter-pvc.yaml
kubectl apply -f jupyter-gpu.yaml
kubectl get pods -o wide | grep jupyter
kubectl logs -f deploy/jupyter-gpu

4. 访问与使用

4.1 获取访问地址

bash
# 方式一:NodePort
# http://<node-ip>:30888

# 方式二:kubectl port-forward(推荐)
kubectl port-forward svc/jupyter-gpu 8888:8888
# 访问 http://localhost:8888

# 方式三:Traefik Ingress

4.2 登录

使用部署时设置的 JUPYTER_TOKEN 环境变量值登录。

4.3 Traefik Ingress 配置

yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: jupyter-ingress
spec:
  entryPoints:
    - web
  routes:
  - match: PathPrefix("/jupyter")
    kind: Rule
    services:
    - name: jupyter-gpu
      port: 8888
    middlewares:
    - name: jupyter-strip-prefix
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: jupyter-strip-prefix
spec:
  stripPrefix:
    prefixes:
      - /jupyter

访问:http://117.50.188.237/jupyter

5. 自定义环境

5.1 安装额外包

在 Notebook 第一个 Cell 中执行:

python
!pip install transformers datasets accelerate peft
!pip install matplotlib seaborn scikit-learn

5.2 自定义 Dockerfile

dockerfile
FROM jupyter/pytorch-notebook:cuda12-latest

USER root

# 安装系统依赖
RUN apt-get update && apt-get install -y \
    git vim htop \
    && rm -rf /var/lib/apt/lists/*

# 配置 pip 国内源
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

# 安装额外 Python 包
RUN pip install \
    transformers datasets accelerate peft bitsandbytes \
    matplotlib seaborn

USER $NB_UID

构建并推送:

bash
docker build -t jupyter-custom:latest .
docker tag jupyter-custom:latest 117.50.188.237:30000/jupyter-custom:latest
docker push 117.50.188.237:30000/jupyter-custom:latest

6. GPU 使用示例

6.1 PyTorch GPU 检测

python
import torch

print(f"PyTorch version: {torch.__version__}")
print(f"CUDA available: {torch.cuda.is_available()}")
print(f"CUDA version: {torch.version.cuda}")
print(f"GPU count: {torch.cuda.device_count()}")

if torch.cuda.is_available():
    print(f"GPU name: {torch.cuda.get_device_name(0)}")
    print(f"GPU memory: {torch.cuda.get_device_properties(0).total_memory / 1e9:.2f} GB")

6.2 简单训练示例

python
import torch
import torch.nn as nn
import torch.optim as optim

# 创建简单模型
model = nn.Sequential(
    nn.Linear(784, 128),
    nn.ReLU(),
    nn.Linear(128, 10)
).cuda()

# 创建虚拟数据
X = torch.randn(64, 784).cuda()
y = torch.randint(0, 10, (64,)).cuda()

# 训练
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

for epoch in range(10):
    optimizer.zero_grad()
    output = model(X)
    loss = criterion(output, y)
    loss.backward()
    optimizer.step()
    print(f"Epoch {epoch+1}, Loss: {loss.item():.4f}")

print("Training complete!")

6.3 HuggingFace Transformers 示例

python
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

# 加载模型(使用本地路径)
model_path = "/models/Qwen/Qwen3-0.6B"
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(model_path).cuda()

# 生成文本
prompt = "人工智能的未来是"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
outputs = model.generate(
    **inputs,
    max_new_tokens=100,
    temperature=0.7,
    do_sample=True
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(response)

6.4 显存监控

python
import torch

def print_gpu_memory():
    if torch.cuda.is_available():
        allocated = torch.cuda.memory_allocated() / 1024**3
        reserved = torch.cuda.memory_reserved() / 1024**3
        max_allocated = torch.cuda.max_memory_allocated() / 1024**3
        print(f"Allocated: {allocated:.2f} GB")
        print(f"Reserved: {reserved:.2f} GB")
        print(f"Max Allocated: {max_allocated:.2f} GB")

print_gpu_memory()

7. 运维指南

7.1 日志与监控

bash
# 查看 Jupyter 日志
kubectl logs -f deploy/jupyter-gpu

# 查看资源使用
kubectl top pod -l app=jupyter-gpu

# 查看 GPU 使用
kubectl exec -it $(kubectl get pod -l app=jupyter-gpu -o name) -- nvidia-smi

7.2 数据备份

bash
# 导出工作目录
kubectl cp $(kubectl get pod -l app=jupyter-gpu -o jsonpath='{.items[0].metadata.name}'):/home/jovyan/work ./jupyter-backup

# 导入
kubectl cp ./jupyter-backup $(kubectl get pod -l app=jupyter-gpu -o jsonpath='{.items[0].metadata.name}'):/home/jovyan/work

7.3 资源调整

bash
# 增加内存
kubectl patch deploy jupyter-gpu --type='json' \
  -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/resources/limits/memory", "value":"16Gi"}]'

# 增加 GPU 显存
kubectl patch deploy jupyter-gpu --type='json' \
  -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/resources/limits/nvidia.com~1gpumem", "value":"8k"}]'

8. 故障排查

8.1 GPU 不可见

现象torch.cuda.is_available() 返回 False

解决:确保使用 schedulerName: hami-scheduler 并请求 nvidia.com/gpumem

8.2 权限问题

PermissionError: [Errno 13] Permission denied

解决

yaml
env:
- name: GRANT_SUDO
  value: "yes"
- name: CHOWN_HOME
  value: "yes"

8.3 Notebook 无法保存

Unexpected error while saving file

解决:检查 PVC 挂载权限

bash
kubectl exec -it <pod-name> -- ls -la /home/jovyan/work

8.4 内存不足 (OOM)

The kernel appears to have died. It will restart automatically.

解决:增加 Pod 内存限制

yaml
resources:
  limits:
    memory: "16Gi"

附录

A. 常用快捷键

快捷键功能
Shift + Enter运行当前 Cell
Esc + A在上方插入 Cell
Esc + B在下方插入 Cell
Esc + D + D删除 Cell
Esc + M转为 Markdown
Esc + Y转为 Code

B. JupyterLab vs Notebook

特性Jupyter NotebookJupyterLab
界面经典单页现代多标签
多文件不支持支持
终端不支持支持
插件有限丰富

JupyterLab 已默认启用,访问时自动跳转。


文档版本: v1.0
更新时间: 2026-08-22
适用版本: Jupyter PyTorch CUDA 12