土法炼钢 · 系统与基础设施

【Rook / CSI】CephFS CSI:subvolume、RWX 与编排侧 MDS 税

文章导航

分类入口
storagekubernetes
标签入口
#rook#csi#cephfs#subvolume#rwx#mds#squid#v1.20.4

目录

需要多个 Pod 同时读写同一份数据时,RBD 的 RWO 模型不够用。Rook 给出的文件系统答案是 CephFS CSI:Provisioner 名默认 rook-ceph.cephfs.csi.ceph.com,每个 PVC 对应文件系统上的 subvolume,AccessMode 可走 ReadWriteMany。编排看起来「开箱即用」,账单却写在 MDS、capability 与元数据池上——这些税不在 StorageClass YAML 里出现。

本文是「Rook / CSI」系列第 8 篇(共 16 篇)。→ 系列目录

篇目 核心内容
第 7 篇 · 挂载与 features RBD NodeStage / krbd
第 8 篇 · CephFS CSI subvolume、RWX、MDS 编排税
第 9 篇 · 快照与克隆 VolumeSnapshot 语义差

版本锚定:Rook v1.20.4;Ceph-CSI v3.17.0;K8s v1.31–v1.36。CephFS/MDS 机制钉站内 ceph/13(Squid);本篇只写 CSI/Rook 编排面。


一、先有文件系统,再有 StorageClass

与 RBD「先有 BlockPool」对称,CephFS CSI 要求先有 CephFilesystem(元数据池、数据池、MDS active/standby)。Rook 文件系统存储文档示例语义:

apiVersion: ceph.rook.io/v1
kind: CephFilesystem
metadata:
  name: myfs
  namespace: rook-ceph
spec:
  metadataPool:
    replicated:
      size: 3
  dataPools:
    - name: replicated
      replicated:
        size: 3
  preserveFilesystemOnDelete: true
  metadataServer:
    activeCount: 1
    activeStandby: true

Operator 拉起 MDS Pod 后,再创建 StorageClass:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: rook-cephfs
provisioner: rook-ceph.cephfs.csi.ceph.com
parameters:
  clusterID: rook-ceph
  fsName: myfs
  pool: myfs-replicated
  csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner
  csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
  csi.storage.k8s.io/controller-expand-secret-name: rook-csi-cephfs-provisioner
  csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
  csi.storage.k8s.io/controller-publish-secret-name: rook-csi-cephfs-provisioner
  csi.storage.k8s.io/controller-publish-secret-namespace: rook-ceph
  csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node
  csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
reclaimPolicy: Delete

命名规则与 RBD 相同:前缀跟随 Operator 命名空间;VolumeSnapshotClass 的 driver 必须一致。Secret 对为 rook-csi-cephfs-provisioner / rook-csi-cephfs-node


二、CreateVolume 产物是 subvolume,不是「整个 CephFS」

动态供给时,Ceph-CSI 在指定 fsName 下创建 subvolume(常见名形如 csi-vol-...),并把 subvolumePath 等写入 PV volumeAttributes。应用 Pod 挂载的是该子树,不是文件系统根。

含义:

预期 实际
「共享整个 CephFS」 默认每个 PVC 一个隔离 subvolume
跨 Namespace 直接共用同一 PVC PVC 是命名空间对象;跨 NS 需静态 PV 配方(Rook 文档有 Retain + staticVolume 流程)
配额可有可无 CSI 用配额落实 PVC 声明大小;内核过旧时配额行为受限

Rook 文档:CephFS CSI 用配额强制 PVC 大小;内核至少约 4.17 才较好支持 CephFS 配额。更旧内核若必须强制配额,可改走 FUSE 客户端(v1.20 配置面在 Ceph-CSI Operator / cephFsClientType,历史键名 CSI_FORCE_CEPHFS_KERNEL_CLIENT)——并接受升级时 FUSE 挂载断开、需重启应用 Pod 的已知代价。


三、RWX 的编排承诺与 POSIX 账单

accessModes: [ReadWriteMany] 在 K8s 里只表示「多个写者被 API 允许」。真正的一致性由 CephFS capability 协议保证:谁缓存、谁缓冲写、谁必须在 revoke 时 flush——见 ceph/13 · Capability

编排侧因此付出的税(本篇只列「会在 K8s 事故里冒出来」的部分):

  1. MDS 可用性:active MDS 抖动 → 多副本 Deployment 同时卡住,比单 RBD 卷故障面更大。
  2. 元数据池延迟:大量小文件 create/unlink、目录 listing,把延迟推到 MDS journal,而不是数据池 OSD 平均延迟。
  3. 多 active MDSactiveCount > 1 只在元数据真成瓶颈且热点可空间切开时值得;否则先买到 subtree thrashing(ceph/13)。
  4. 频繁 fsync / 强同步库:机制结论是「别把这类负载直接放 CephFS」——与是否用了 CSI 无关。

把「RWX StorageClass」理解成「免费 NFS」会低估 caps 税。Rook 示例用 kube-registry 多副本挂同一 PVC,演示的是共享文件系统可行,不是「任意 POSIX 密集负载都合适」。


四、挂载客户端:kclient 与 fuse

客户端 配置入口(v1.20) 要点
内核客户端(kclient) 默认优先 POSIX/性能通常更好;能力随内核版本
ceph-fuse cephFsClientType 便携、易调试;多一层 FUSE;升级断开风险

多文件系统 + 过旧内核(文档举过 < 4.7)时,指定文件系统命名空间可能不一致——属于节点内核矩阵问题,不是改 SC 名字能修好的。

NodeStage/Publish 对 CephFS 是 mount 子树路径,不是 RBD 的 rbd map。排障时看 node plugin 日志与节点上的 CephFS 挂载选项;features/krbd 那套叙事不要硬套过来。


五、与 RBD CSI 的对照(编排视角)

维度 RBD CSI CephFS CSI
Provisioner *.rbd.csi.ceph.com *.cephfs.csi.ceph.com
后端对象 Format 2 image subvolume
典型 AccessMode RWO RWX
节点附着 map 块设备 + fs mount 文件系统路径
主要税 features/krbd、exclusive-lock MDS/caps、元数据池
快照语义 image 级(第 9 篇) subvolume 级 vs .snap 目录级(第 9 篇)

数据面在 Bound 之后仍归 RADOS:文件内容直访 OSD,元数据走 MDS——这是 OSDI 2006 以来的分叉,不因 CSI 改变。


六、常见编排失败模式

现象 优先检查
PVC Pending CephFilesystem 是否 Ready;fsName/pool 是否与 SC 一致;cephfs provisioner Secret
Bound 但 Pod MountFailed 节点内核;kclient vs fuse;MDS 是否 online
多 Pod 同时卡在同一目录 caps revoke / MDS;不要先扩 OSD
配额不生效 内核是否支持 CephFS quota
跨 NS「共享失败」 是否误以为 PVC 可跨 NS;应走静态 PV 文档路径

六、跨 Namespace 共享:静态 PV 的编排税

Rook 文件系统文档给出「同一 subvolume、多个 Namespace」的静态配方:原始动态 PVC/PV 改 Retain,再复制 PV 并加 staticVolume / rootPath,在目标 Namespace 建指向该 PV 的 PVC。这能工作,但代价是:

平台若把「跨 NS 共享目录」做成自助工单,应默认提供受控静态模板与回收 runbook,而不是让每个应用团队复制半份 PV YAML。更干净的产品化路径往往是:同 NS 内 RWX,或对象存储,而不是无限复制静态 PV。


七、配额、容量展示与「假满」

PVC 的 requests.storage 经 CSI 落到 CephFS 配额后,df 在 Pod 内看到的是配额视图,不一定等于数据池真实占用。运维若只盯池容量百分比,可能与租户「我的卷还有空间」观感冲突;反之,租户写满配额而池仍空,会表现为 ENOSPC 类错误但集群 HEALTH_OK

排障时同时看:PVC 容量、subvolume 配额、数据池 USED、元数据池延迟。把四者塌缩成「CephFS 满了」会误修。


八、谱系、争论与开放问题

谱系:Weil et al.(OSDI 2006)定义「MDS 权威元数据 + 客户端直访数据 + 动态 subtree」。CSI 只是把 subvolume 生命周期接到 PVC。站内深度在 ceph/13;本篇不重写 journal 结构与 Migrator。相对 GFS 单 master(Ghemawat et al., SOSP 2003),Ceph 选动态分区换扩展性,也把 thrashing 与跨 rank rename 税留在工程现实里——这些税在 K8s 多副本同时写同一 PVC 时更容易被业务感知。

争论:共享存储该不该在 K8s 里用「真正的 POSIX FS」?一派坚持 RWX+CephFS;一派用对象存储 + 应用级协调,或每个副本独立 RBD。争论焦点是 caps/fsync 税是否可接受,不是 provisioner 字符串好看不好看。另一争论是默认 kclient 还是 fuse:可移植与调试 vs 升级断开与性能——Rook 把选择收成 cephFsClientType,要求平台显式选边。

开放问题

  1. CSI 能否把 MDS 延迟与 cap 等待导出为与 kubelet Mount 失败同级的、可告警的稳定信号?(见第 12 篇观测方向。)
  2. VolumeSnapshot(subvolume 级)与用户在应用内使用 .snap 目录快照的语义教育,如何在平台层默认防呆?(第 9 篇展开。)
  3. 跨 NS 静态共享能否变成一等 CR,而不是文档级 YAML 复制,以降低误删面?

九、本篇收束

CephFS CSI 兑现的是「声明式 subvolume + RWX 挂载」,不是「免费消除 POSIX 分布式税」。选这条路径前,先用 ceph/13 的判据问清:是否频繁 fsync、元数据是否热点、编制是否看得懂 MDS。下一篇把快照语义差一次说清。


十、何时不该把 CephFS CSI 当默认 StorageClass

给出可执行的负向清单(机制来自 ceph/13 与本篇编排税,不是口味):

正向清单更短:多副本只读配置树、制品缓存、需要 POSIX 共享但不把同步写放在关键路径上的工作负载——并且接受元数据池与 MDS 的编制成本。

把 CephFS CSI 设成集群默认 SC「图省事」,会把不适合的负载一并吸进来,事故复盘时再争论「是不是 Ceph 不行」。排除应发生在 StorageClass 分层与准入,而不是发生在客户怒火里。

与 RBD 默认 SC 并存时,用命名与文档写清:块给有状态单写者,文件给共享读写;不要靠口头传统。

十一、编排侧如何「看见」MDS 税

K8s 仪表盘默认不显示 cap revoke、journal 积压或 subtree export。结果是:CephFS PVC 的用户按「磁盘满/网络差」开单,存储值班按「OSD 很好」结单,中间的 MDS 层无人认领。编排层至少要补三类信号入口(具体面板在第 12 篇):

  1. MDS Pod 就绪与 failover 次数;
  2. 元数据池 commit/apply 延迟;
  3. 与 cap 相关的驱逐或卡住客户端计数(名称以所用 Ceph 版本指标为准)。

没有这三类,RWX 工作负载的 SLO 只能写成「尽力而为」。把 CephFS 当默认共享盘的团队,等于在没有仪表的情况下承诺 POSIX。

另一常见编排失误是:为了「高可用」把 activeCount 调大,却不改业务目录布局。热点仍在单个目录树时,多 active 只增加 migration barrier 概率。决策顺序应是:先证明单 active + 更快元数据池不够,再证明热点可切开,再改 activeCount。Rook CR 里把数字改大很容易,回滚 thrashing 现场很难。

安全上,CephFS 的只读挂载与 POSIX 权限是另一层;CSI 供给的 Secret 是集群级客户端身份。租户隔离若只靠目录权限而不靠 subvolume/Namespace 边界,会在「某个 Pod 被攻破」时扩大爆炸半径。第 15 篇展开;本篇提醒:RWX 便利与隔离强度负相关。

与 NFS CSI(第 10 篇)比较:CephFS CSI 是成熟路径,NFS CSI 是实验路径。需要 NFS 协议本身(集群外客户端、特定锁行为)时才评估 NFS;只是要共享目录,优先 CephFS CSI。

十二、供给失败与 MDS 无关的那些坑

不是所有 CephFS PVC Pending 都值得去看 MDS。先排除:

这些是第 6 篇同构的编排错误。只有 Bound 成功、多客户端同时卡住或元数据操作超时,才把主战场切到 ceph/13 的 journal/caps/subtree。把顺序反了,会在健康的 MDS 上空转。

另:kube-registry 示例用三副本挂同一 PVC,适合演示 RWX,不适合当「所有有状态应用模板」。复制示例时删掉业务无关的 registry 环境变量很容易,复制「多写者共享一块盘」的架构假设却很难删——代码评审应盯后者。

写进架构决策时,建议附否证条件:若主业务开始把同步写数据库放在 CephFS PVC 上,或元数据创建速率使单目录 export 在观测窗口内反复发生,则本篇「可选用 CephFS CSI」的结论必须重开,而不是靠「我们已经 RWX 很久了」延用。机制允许长期正确,也允许负载变迁后突然错误——编制要能触发重评。

参考资料

官方文档(A)

论文(A)

站内

上一篇:挂载与 features · 系列目录 · 下一篇:快照与克隆

读完这篇,下一步读什么

优先读同系列或同问题的下一篇,把单篇消费变成主题集群。

2026-08-15 · storage / kubernetes

【Rook / CSI】编排全景:五轴坐标系与 16 篇路线

相对 ceph/ RADOS 内核与 storage/ 云块选型,钉清 Rook/CSI 编排层缺口;定义 CSI RPC、sidecar、Operator/CRD、数据面归属、升级闸门五条坐标系,给出 16 篇阅读路线与 PVC Bound 之后 I/O 仍走 krbd→PG→BlueStore 的边界。


By .