4、Kubeflow PVC 实战:Notebook 挂载 PVC、跨 Pod 共享数据、PVC 扩容与快照、使用 ReadWriteMany 卷

这一章,我们直接动手。PVC 在 Kubeflow 里到底怎么用?我见过不少团队,YAML 写得飞起,结果 Notebook 一重启数据丢了,或者两个 Pod 抢同一个盘直接报错。说白了,PVC 用不好,你的 ML 工作流就是纸糊的。

咱们今天就把四个核心场景讲透:Notebook 挂载、跨 Pod 共享、动态扩容、快照恢复。最后再聊聊 ReadWriteMany 这个“神器”到底怎么用。

4.1 Notebook 挂载 PVC:你的代码和数据不会丢

先看最常用的场景。你在 Kubeflow 里启动一个 Notebook,最怕什么?怕写了一半的代码,重启后全没了。我个人习惯,所有 Notebook 都挂载独立的 PVC。

创建 PVC 的 YAML 很简单:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-notebook-pvc
  namespace: kubeflow-user
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: standard

然后在 Kubeflow 的 Notebook UI 里,创建 Notebook 时,在 “Data Volumes” 部分添加这个 PVC。挂载路径我建议用 /home/jovyan/data。为什么?因为 Jupyter 镜像默认用户是 jovyan,挂载到 home 目录下,权限问题最少。

我的经验: 挂载路径千万别用 / 或者 /home 本身。我曾经有个同事直接挂载到 /home,结果把系统配置文件都覆盖了,Notebook 直接起不来。挂载到一个子目录,干净又安全。

启动后,你在 Notebook 里执行:

!ls /home/jovyan/data/

就能看到你的持久化数据了。写个文件试试:

with open('/home/jovyan/data/test.txt', 'w') as f:
    f.write('Hello Kubeflow PVC!')

重启 Notebook 实例,这个文件还在。嗯,这就是 PVC 的基本功。

4.2 跨 Pod 共享数据:ReadWriteMany 登场

单个 Notebook 挂载 PVC 太简单了。真正考验人的是:两个 Pod 怎么共享同一份数据?

比如你有一个训练任务,数据预处理 Pod 写数据,训练 Pod 读数据。如果用 ReadWriteOnce,两个 Pod 不能同时挂载同一个 PVC。怎么办?

答案就是 ReadWriteMany (RWX)

但注意,不是所有存储后端都支持 RWX。我列个表给你看:

存储后端 支持 RWX? 说明
NFS ✅ 是 最经典方案,性能一般但稳定
GlusterFS ✅ 是 适合大文件,小文件性能差
CephFS ✅ 是 性能好,但部署复杂
HostPath ❌ 否 仅单节点,别用于生产
AWS EBS ❌ 否 只能 ReadWriteOnce

如果你在本地测试,最简单的办法是部署一个 NFS 服务。然后创建 PVC 时指定 accessModes: [ "ReadWriteMany" ]

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: shared-data-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 50Gi
  storageClassName: nfs-client

两个 Pod 都挂载这个 PVC,就能同时读写同一份数据了。我在项目中遇到过一个问题:两个 Pod 同时写同一个文件,导致数据损坏。解决办法是让每个 Pod 写自己的子目录,或者用文件锁。说白了,RWX 只是解决了“能同时挂载”的问题,不解决“并发写冲突”的问题。

注意: ReadWriteMany 不是银弹。高并发写入场景下,建议用对象存储(如 MinIO)或者分布式文件系统。RWX 更适合“一写多读”或者“各自写不同文件”的场景。

4.3 PVC 扩容:数据不够了怎么办?

训练数据越来越大,PVC 不够用了。你怎么办?删了重建?那数据不就丢了?

Kubernetes 1.11 之后支持 PVC 在线扩容。前提是你的 StorageClass 开启了 allowVolumeExpansion: true

先检查一下:

kubectl get storageclass standard -o yaml

看输出里有没有这一行:

allowVolumeExpansion: true

如果没有,你需要修改 StorageClass。我个人习惯在部署集群时就加上这个配置,省得后面抓狂。

扩容操作非常简单。直接编辑 PVC:

kubectl edit pvc my-notebook-pvc

spec.resources.requests.storage10Gi 改成 20Gi。保存退出,Kubernetes 会自动触发扩容。

你可以用这个命令观察状态:

kubectl get pvc my-notebook-pvc -w

等状态变成 Bound,容量显示 20Gi,就搞定了。Pod 不需要重启,数据也不会丢。

避坑指南: 我曾经在生产环境扩容一个 500Gi 的 PVC,结果等了 20 分钟还没完成。后来发现是存储后端在做数据迁移。扩容前最好先看看存储后端的负载,别在高峰期操作。

4.4 PVC 快照:后悔药你得备着

扩容是正向操作。那万一你误删了数据呢?或者模型训练到一半,发现数据预处理错了,想回滚到之前的状态?

这时候就需要 VolumeSnapshot。它是 Kubernetes 1.12 之后引入的功能,相当于给 PVC 拍个照片。

首先,你得确保集群里有 VolumeSnapshotClass

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: csi-snapclass
driver: csi-hostpath
deletionPolicy: Delete

然后创建快照:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: my-pvc-snapshot-20240601
spec:
  volumeSnapshotClassName: csi-snapclass
  source:
    persistentVolumeClaimName: my-notebook-pvc

创建后,你可以用这个快照恢复数据。恢复的方式是从快照创建一个新的 PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc-restored
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  dataSource:
    name: my-pvc-snapshot-20240601
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io

这个新 PVC 里的数据,就是拍快照那一刻的状态。你可以把它挂载到新的 Pod 里,把数据拷出来。

注意: 快照不是备份。它依赖存储后端的快照能力,而且通常只保存在同一个存储系统上。如果你的存储挂了,快照也保不住。真正的备份,还是得把数据拷贝到对象存储或者另一个集群。

4.5 实战:用 ReadWriteMany 卷搭建数据流水线

最后,咱们串一个完整的例子。假设你要搭建一个 ML 数据流水线:

  1. 数据采集 Pod 从外部拉取数据,写入共享 PVC
  2. 数据清洗 Pod 读取数据,清洗后写回同一个 PVC
  3. 训练 Pod 读取清洗后的数据,开始训练

三个 Pod 需要同时挂载同一个 PVC。这就是 ReadWriteMany 的典型场景。

共享 PVC 的 YAML 前面已经给了。三个 Pod 的挂载配置类似:

volumes:
- name: shared-data
  persistentVolumeClaim:
    claimName: shared-data-pvc

containers:
- name: data-collector
  volumeMounts:
  - name: shared-data
    mountPath: /data

每个 Pod 写不同的子目录:

  • 采集 Pod 写 /data/raw/
  • 清洗 Pod 读 /data/raw/,写 /data/clean/
  • 训练 Pod 读 /data/clean/

这样既共享了存储,又避免了文件冲突。我在一个客户现场就是这么干的,跑了半年没出过问题。

核心要点: ReadWriteMany 解决的是“同时挂载”的问题。数据组织、并发控制、权限管理,这些还是得你自己操心。别指望一个 RWX 就能搞定所有共享需求。

好了,这一章的内容就是这些。PVC 的四个核心操作——挂载、共享、扩容、快照——你都亲手实践过了。下一章我们聊聊更高级的话题:如何在 Kubeflow 里管理多个 PVC 的生命周期。


公众号:蓝海资料掘金营,微信deep3321