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

【Rook / CSI】快照与克隆:VolumeSnapshot 语义、扩容与 CRD 错位

文章导航

分类入口
storagekubernetes
标签入口
#rook#csi#volumesnapshot#clone#expand#cephfs#rbd#external-snapshotter#v1.20.4

目录

备份工具报告「快照 Ready」并不等于「你以为的那一层时间点」。在 Rook 上,K8s VolumeSnapshot API、RBD image snap、CephFS subvolume snap,以及用户在目录里看到的 .snap,共享「快照」一词,却不共享同一套保证。再叠上 external-snapshotter sidecar 与集群 CRD 的版本错位,会出现「普通单卷快照也不 ready」的编排级故障——与 Ceph 数据面无关。

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

篇目 核心内容
第 8 篇 · CephFS CSI subvolume / RWX
第 9 篇 · 快照与克隆 VolumeSnapshot 语义;expand;CRD 错位
第 10 篇 · 对象与 NFS RGW / NFS 边界

版本锚定:Rook v1.20.4;Ceph-CSI v3.17.0;K8s v1.31–v1.36。RBD/CephFS 快照机制外链 ceph/12ceph/13ceph/18 点名的「目录级 snap vs VolumeSnapshot 卷级语义」在此展开。


一、三件套与驱动名

K8s 快照控制面(需安装 snapshot CRD + snapshot-controller):

对象 角色
VolumeSnapshotClass 类比 StorageClass:指定 driver、删除策略、Secret
VolumeSnapshot 命名空间内的快照声明,指向 PVC
VolumeSnapshotContent 集群级实体,承载快照句柄

RBD 示例语义(驱动名必须与 StorageClass provisioner 一致):

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: rook-ceph-block-vsc
driver: rook-ceph.rbd.csi.ceph.com
deletionPolicy: Delete
parameters:
  # 按 Rook/Ceph-CSI 示例填写 clusterID 与 snapshot Secret

CephFS 则把 driver 换成 rook-ceph.cephfs.csi.ceph.com。前缀随 Operator 命名空间变化时,SC 与 SnapshotClass 必须一起改

动态供给链路:

flowchart LR
  vs["VolumeSnapshot"] --> vsc["VolumeSnapshotClass"]
  vs --> pvc["源 PVC"]
  vsc --> snapctl["snapshot-controller"]
  snapctl --> side["csi-snapshotter sidecar"]
  side --> csi["CSI CreateSnapshot"]
  csi --> back["RBD snap / CephFS subvolume snap"]

任一层 CRD/控制器缺失或版本错位,CSI 驱动可能根本收不到 CreateSnapshot——表现为 VolumeSnapshot 长期不 Ready,Events 含 reflector / rate limit 一类错误。


二、三种「快照」各保证什么

这是本篇的核心对照表,也是 ceph/18 停损线的展开:

机制 粒度 谁协作 典型用途 常见误解
RBD VolumeSnapshot 整 image 应用/fsfreeze/qemu-ga 决定是否 crash-consistent PVC 备份、整卷还原 以为等于文件系统一致快照
CephFS CSI VolumeSnapshot 整 subvolume(该 PVC 对应子树) MDS 协调持 cap 客户端 flush(实现依赖 CSI/Ceph 路径) 卷级备份/还原 以为等于任意目录的 .snap
CephFS .snap 目录快照 目录子树(用户在 FS 内创建) 客户端 flush 协作;硬链接跨 snap 有已知限制 用户自助目录时间点 以为 Velero/VolumeSnapshot 做了同一件事

补充:

平台若把「目录级恢复」写进 SLA,却只提供 VolumeSnapshot API,会在事故复盘时发现语义空窗——这是编排与内核交接处的真实摩擦,不是文档笔误。


三、从快照恢复与克隆

3.1 从 VolumeSnapshot 建卷

常见模式:新 PVC 的 dataSource 指向已有 VolumeSnapshot(或兼容的快照内容)。CSI 侧对 RBD 走 clone/从 snap 建 image 一类路径;对 CephFS 走 subvolume 快照克隆语义。父子依赖、protect/flatten、COW 放大等 RBD 内核账单仍适用(ceph/12);CSI 只负责 RPC 与 PV 绑定。

3.2 PVC clone

dataSource 指向另一 PVC(同 StorageClass/驱动支持时)可做卷克隆。注意:

3.3 静态 PV

RBD 与 CephFS 均支持把已有 image/subvolume 做成静态 PV(Rook「Static Provisioning」)。用于迁入存量数据或跨集群挂载句柄。静态路径下,动态快照/扩容能力以驱动与文档边界为准;不要假设「有 PV 就有全套 CSI 控制器操作」。


四、扩容(allowVolumeExpansion)

StorageClass 需:

操作是调大 PVC spec.resources.requests.storage。控制器走 ControllerExpandVolume,后端扩大 image/subvolume,再视文件系统做 online resize。前提(Rook 文档):

扩容失败时分层看:SC 未开 expand → Secret → CSI expand RPC → 后端配额/池容量 → 文件系统 resize。不要把「PVC 事件里容量未变」直接写成「OSD 满」而不看 expand 日志。


五、external-snapshotter 与 group snapshot CRD 错位

这是编排失败模式,值得单独成节。

5.1 现象

5.2 机制梗概

kubernetes-csi/external-snapshotter 在较新发行线(社区讨论集中在 8.4+ sidecar)对 Volume Group Snapshot API 的预期收紧:需要匹配的 v1beta2 group snapshot CRD(及控制器/feature gate 配置)。若集群只装了旧的 v1beta1 group CRD、或 CRD 与 sidecar/controller 版本错位,监视失败会变成全局性快照功能障碍。

Rook 侧默认会跟随较新的 sidecar 镜像标签;集群里的 CRD 往往由发行版/其它 chart 安装,不一定与 Rook 捆绑升级。结果是:升 Rook/CSI 后「Ceph 很健康,快照全坏」。

5.3 处置原则(不写逐步黑客操作)

  1. 核对:snapshot CRD 版本、snapshot-controller 版本、CSI Pod 内 csi-snapshotter 镜像标签是否属于同一支持组合(以上游 external-snapshotter 发布说明为准)。
  2. 若启用或残留 group snapshot CRD,确保 served 版本满足当前 sidecar 要求(社区常见修复是补齐上游 v1beta2 CRD,或暂时对齐较旧 sidecar——以官方兼容说明为准)。
  3. 把「快照 CRD/控制器」列入 Rook 升级检查单(第 11 篇),与 Ceph 镜像升级同等对待。

这不是 CephFS 或 RBD 的 COW bug;用 ceph -s 查不出来。


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

谱系:卷快照 API 是 SIG Storage 把「厂商快照」收成声明式资源的结果;CSI CreateSnapshot/DeleteSnapshot 是最小面。Ceph 侧则早有 RBD snap 与 CephFS 目录 snap 两套用户故事。三者在「时间点」口语下合流,在「粒度与协作」上从未合流。

争论:备份该不该默认挂 VolumeSnapshot?一派认为编排一致、可进 GitOps;一派指出语义教育成本高,逻辑备份更可控。对数据库类负载,机制上更稳的是:VolumeSnapshot 当 crash-consistent 底线 + 应用一致策略,而不是单押 Ready 条件。

开放问题

  1. 平台能否在 VolumeSnapshotClass 注解层强制区分「image/subvolume」与「禁止暗示目录级恢复」?
  2. Rook/CSI 默认镜像与发行版自带 snapshot CRD 的兼容矩阵,能否变成安装时的准入检查,而不是事故后读 issue?

七、备份链路里的责任切割

一套常见生产链路是:Velero / 自研控制器创建 VolumeSnapshot → 等 Ready → 另存或复制快照内容。责任切割应写成:

角色 负责 不负责
快照控制器 + CSI 卷级时间点对象创建成功 应用事务一致
Ceph 按 RBD/CephFS 语义保留 snap 可见性 解释业务含义
应用所有者 quiesce / 逻辑备份 / 恢复演练 假装 Ready 即一致
平台 CRD/sidecar 版本对齐、容量与保留策略 替每个应用定义 RPO 语义

缺少「应用所有者」一行时,所有 Ready 快照都会在恢复演练中暴露缺口。平台可以用策略强制「数据库命名空间必须有逻辑备份注解」,但不能用 VolumeSnapshot 代替那一行。

保留策略也要切清:deletionPolicy: Delete 在删 VolumeSnapshot 时回收后端 snap,可能影响仍依赖该 snap 的 clone 链;Retain 则留下需垃圾回收的后端对象。RBD 的 protect/flatten 纪律(ceph/12)在 CSI 克隆大量涌现时更容易被忘记——模板盘删不掉,往往是子 clone 未清理,不是 Ceph「坏了」。

八、扩容与快照叠加时的顺序问题

生产上常见组合操作:先快照,再扩容,再从快照恢复到新大小,或在已有 snap 的 image 上反复扩缩。RBD 层对「有 snap 时的容量边界与 OID 生命周期」更敏感(ceph/12 提醒生产少做有 snap 缩容再扩容)。CSI 扩容 API 不会自动替你教育这些内核约束。

建议操作纪律:

CephFS 侧,subvolume 配额随扩容调整后,应用是否立即看见新大小取决于客户端与配额实现;不要在自动化里假设「patch PVC 后下一秒 df 已变」而不加等待与校验步骤。静态跨 NS 卷更是明确不支持在静态句柄上 resize——自动化若对所有 PVC 盲目 expand,会在静态副本上持续失败并产生噪音告警。

关于 group snapshot:即便你「不用」组快照功能,只要 CRD 与 sidecar 版本错位,仍可能伤到单卷快照。因此升级检查单不能写「我们未启用 group snapshot故跳过 CRD 检查」——第 11 篇把该项列为必填,原因在此。

开放问题补一句:在混合 RBD 与 CephFS 的命名空间里,同一套 Velero 配置能否安全默认?机制上两者 Ready 的含义不同,平台或许应按 StorageClass 拆备份策略,而不是一套注解打天下。

九、把语义差写进恢复演练脚本的标题

恢复演练名称若叫「Ceph 快照恢复」,参与者会对齐到不同对象。建议标题直接写机制:

三种演练的前置、成功标准、数据校验方法都不同。例如 RBD 恢复后要校验文件系统 journal;CephFS .snap 要校验目录子树与硬链接预期。用同一份检查清单只会得到虚假通过。

平台文档若只能维护一种,优先维护 VolumeSnapshot 卷级,并显式写「不覆盖目录级 .snap」。这比假装三者等价更负责任,也直接回应 ceph/18 的停损点名。

工程间隙再补一句:论文与规范里的「快照」常假设单一实现者与清晰粒度;K8s 生态把厂商快照、CSI、组快照、应用备份控制器叠在同一集群后,失败模式转向版本组合。Ceph 数据面再健康,也救不了 CRD 错位。把「存储升级」与「快照控制面升级」拆成两行风险登记,是便宜的流程改进。

对 clone 链的成本沟通,应用负责人常只看见「秒级创建新 PVC」。平台应在自助文档写明:创建快、第一次写与 flatten 可能很慢,池容量与父盘删除受限。没有这句,CSI 的便利会变成容量事故的伪装。

参考资料

规范 / 官方 / issue(A/B)

站内

上一篇:CephFS CSI · 系列目录 · 下一篇:对象与 NFS

读完这篇,下一步读什么

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

2026-08-15 · storage / kubernetes

Rook / CSI:K8s 上的 Ceph 编排内核

补齐站内 Ceph RADOS 内核之上的编排层:CSI 规范与 sidecar、Rook Operator/CRD、Ceph-CSI Operator、RBD/CephFS 供给与挂载、VolumeSnapshot 语义差、升级闸门,以及排障与选型收束。

2026-08-15 · storage / kubernetes

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

拆解 Rook 上 CephFS CSI 如何用 subvolume 兑现 ReadWriteMany;钉死 provisioner 命名、StorageClass 与配额边界,并说明编排侧为 MDS/caps 付出的税——外链 ceph/13,不重写 journal 内核。


By .