CSI 解决「PVC 如何变成后端卷」;Rook 解决「Ceph
守护进程如何在 Kubernetes
里被声明式地养活」。把两者混成一句「Rook 就是 Ceph 的
CSI」,会在排障时找不到负责人:是 Operator 没调和出
OSD,还是 CSI CreateVolume 失败?
本文钉 Rook 作为 Operator 的工作方式、核心 CRD 分工、reconcile 所有权边界,以及 Rook 明确不做什么(RADOS 内核语义仍在 ceph/)。v1.20 的 Ceph-CSI Operator 专篇见下一篇之后的第 5 篇;本篇先把 Rook 自己的控制面说清。
本篇在系列中的位置
篇目 核心内容 第 2 篇 · CSI 规范与 K8s 接线 Controller/Node、sidecar、PVC→RPC 第 3 篇 · Rook Operator 与 CRD 核心 CRD、reconcile 边界、命名空间 第 4 篇 · CephCluster 生命周期 mon/mgr/osd、设备发现、健康闸门
版本锚定:Rook v1.20.4;文档树
rook.io/docs/rook/v1.20/。K8s v1.31–v1.36。Ceph 镜像线为 Squid / Tentacle(见 CephClustercephVersion)。
一、Rook 是什么:Operator,不是另一套 RADOS
Kubernetes Operator
模式的直觉是:用自定义资源表达期望状态,用控制器循环把集群调到该状态。
Rook 的 Ceph 运算符(rook-ceph-operator)监视
ceph.rook.io(及关联)CRD,创建并更新
Deployment/DaemonSet/Job、Service、ConfigMap/Secret、以及
Ceph 守护进程 Pod。
对运维的直接含义:
- 你主要编辑的是 CR YAML(以及少数
Operator 级 ConfigMap),不是在每个节点上手写
ceph.conf启停脚本。 - 「集群好不好」要同时看:CR 状态、Operator 日志、Ceph 守护进程 Pod、以及 toolbox 里的 Ceph 状态——缺任一层都会误判。
Rook 文档的 Quickstart 把最小安装拆成:CRD 与公共资源 →
csi-operator → Rook operator →
CephCluster。顺序本身就在强调:编排控制面与 CSI
控制面是两条线,只是常共置在 rook-ceph
命名空间。
二、核心 CRD 地图
下表按「你声明什么意图」组织。字段全集见官方 CRD 文档;此处只钉所有权与后续篇入口。
| CRD | 意图 | Operator 侧后果(直觉) | 后续 |
|---|---|---|---|
CephCluster |
要一个(或外部接入的)Ceph 集群 | mon/mgr/osd(及 crash/exporter 等)生命周期;设备发现;升级编排 | 第 4、11 篇 |
CephBlockPool |
块池(副本或 EC 等池参数) | 在 Ceph 中创建/更新 pool;供 RBD StorageClass 引用 | 第 6 篇 |
CephFilesystem |
CephFS(MDS + 数据/元数据池) | MDS 部署与 FS 管理 | 第 8 篇;语义 ceph/13 |
CephObjectStore |
RGW 对象网关入口 | RGW 部署与对象存储用户/桶相关资源 | 第 10 篇;语义 ceph/14 |
CephObjectStoreUser 等 |
对象用户/桶策略等 | 在 ObjectStore 之上的细粒度资源 | 第 10、15 篇 |
CephBlockPoolRadosNamespace 等 |
多租户命名空间等 | 隔离与连接信息 | 第 15 篇 |
CephClient / CephRBDMirror
等 |
客户端能力、镜像等 | 按文档启用的专项能力 | 按需;非本篇展开 |
CSI 侧另有 OperatorConfig /
Driver(csi.ceph.io):在
v1.20 上它们是 CSI 设置的权威入口,但所有权叙事属于
Ceph-CSI Operator(第 5 篇),不要再默认「改
rook-ceph-operator-config 就等于改 CSI」。
还有一批「周边
CR」会在生产清单里出现,但不改变本篇边界:例如监控相关的
ServiceMonitor 是否由
CephCluster.spec.monitoring 触发、是否单独
apply
monitoring/rbac.yaml。它们属于可观测面(第 12
篇),不应塞进「不会装 Rook」的焦虑里,但升级时漏掉 RBAC
更新会造成「集群好、指标无」的假象。
对象存储用户、桶通知、NFS 导出(experimental)等 CR
同样遵循「先有集群健康,再有高阶
CR」的依赖:CephObjectStore 依赖可用的 RADOS
与(通常)专用池;在 mon 都没 quorum 时 apply
这些资源,只会制造一长串 reconcile 错误。第 10
篇再展开对象与 NFS 边界。
静态示例结构(字段以你使用的 v1.20.4 示例为准,此处仅示意层级):
apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
name: rook-ceph
namespace: rook-ceph
spec:
cephVersion:
image: quay.io/ceph/ceph:v19.2.3
dataDirHostPath: /var/lib/rook
mon:
count: 3
mgr:
count: 2
storage:
useAllNodes: true
useAllDevices: false不要把上面的镜像标签当成你环境的已验证版本;生产应钉具体
vRELNUM.Y.Z(或带 build 日期的标签),避免浮动
v19 造成节点间异构——CephCluster CRD
文档明确警告一般主版本标签不适合生产。
三、reconcile 所有权边界
把「谁负责什么」写成可检验命题,避免事故复盘时互相甩锅。
3.1 Rook Operator 拥有
- 守护进程编排:根据
CephCluster创建/滚动 mon、mgr、osd(及文档启用的 MDS/RGW 等,常由对应 CR 触发)。 - 设备与存储选择:解释
storage.useAllDevices、deviceFilter、nodes、storageClassDeviceSets(PVC 模式)等,调度 prepare Job 与 OSD Pod。 - 集群级生命周期钩子:健康检查、升级编排、PDB/disruption
相关行为(字段见 CephCluster CRD 的
skipUpgradeChecks、disruptionManagement等)。 - 把 Ceph 连接信息提供给消费方:例如 mon endpoints、密钥相关 Secret——供 CSI 与 toolbox 使用(具体 Secret 名以部署为准)。
3.2 Ceph-CSI Operator 拥有(v1.20)
- CSI
驱动工作负载与调谐:
OperatorConfig的driverSpecDefaults、各Driver的覆盖项、镜像 ImageSet 等。 - 与 Rook 的接口:Driver 名必须与 StorageClass/VolumeSnapshotClass 一致;Rook 集群命名空间前缀是默认约定。
3.3 Ceph 守护进程拥有
- RADOS 真相:OSDMap epoch、PG 状态、BlueStore 延迟、peering——这些不会因为你改了 Kubernetes Deployment 注解就改变语义。排障到这一层必须用 ceph/ 坐标系。
3.4 用户 / GitOps 拥有
- CR 的期望字段、StorageClass 参数、是否安装
ceph-csi-driverschart /csi-operator.yaml、升级时是否先备份Driver/OperatorConfig。
reconcile 循环的失败模式值得单独点名:Operator 会持续重试把状态拉向期望。因此「临时手工改了 Deployment 环境变量」通常会被下一轮调和覆盖;反之,「CR 写错了设备过滤器」会表现为 prepare Job 反复失败,而不是一次性报错后停止。GitOps 与手工 hotfix 混用时,要以 CR 为权威,把热修回写进仓库,否则会出现「昨晚修好、今早又坏」的假故障。
另一个边界是 状态字段 vs 规范字段:看
CephCluster 的 status(条件、ceph
版本标签、消息)是观察,改 spec
才是意图。不要把 status 里的短暂消息理解成需要复制进 spec
的配置。升级观察时,官方示例用 Deployment 上的
rook-version / ceph-version
标签看滚动是否结束——那是状态观察技巧,仍不替代 toolbox
健康检查。
flowchart LR
user["User_GitOps"] --> cr["Ceph_CRs"]
user --> sc["StorageClass_PVC"]
cr --> rookop["rook_ceph_operator"]
rookop --> daemons["mon_mgr_osd_pods"]
daemons --> rados["RADOS_truth"]
user --> csiop["ceph_csi_operator"]
csiop --> drivers["CSI_ctrl_node"]
sc --> drivers
drivers --> rados
四、命名空间与多集群约束
默认示例把 Operator 与集群都放在
rook-ceph。这不是硬性唯一选择,但偏离时必须改:
- common 资源与示例 YAML 中的命名空间引用;
- CSI 驱动名前缀(默认常为
<operator-namespace>.rbd.csi.ceph.com); - Helm values 与
ceph-csi-drivers推荐 values 里所有rook-ceph字面量。
CephCluster CRD
写明:同一命名空间内通常不支持多个集群;多集群时必须避免设备与
hostPath 冲突。dataDirHostPath
必须每集群唯一,且不要使用
/etc/ceph、/rook、/var/log/ceph
及其子路径。
对「一个 K8s 集群接多个 Ceph」的场景,还有 external
mode:spec.external.enable: true 时 Rook
不管理该 Ceph 的 OSD
生命周期,只消费外部集群(并可能部署部分网关类守护进程,条件见文档)。那是另一条所有权边界:RADOS
健康在外部,Rook 只对接入与可选守护进程负责。
五、Rook 明确不做什么
写出否定句,是为了防止系列膨胀成「第二套 Ceph 内核教程」。
| Rook 不做 | 应去哪里 |
|---|---|
解释 PG peering / last_epoch_started |
ceph/05 |
| 解释 BlueStore deferred / WAL | ceph/07–09 |
| 解释 RBD 对象命名与 features 语义本体 | ceph/12;编排侧 features 错位见本系列第 7 篇 |
| 解释 CephFS caps / MDS 平衡 | ceph/13 |
| 云厂商块 API 教程 | storage/70 |
| 替代 Ceph「一次一个主版本」升级纪律 | 第 11 篇 + 官方 Ceph Upgrades |
一句话:Rook 编排的是「Ceph 在 K8s 上的生命周期与接线」;Ceph 仍对自己的一致性与本地存储负责。
这也解释了系列拆分:ceph/18 停在编排层,是因为再往下写
CRD 字段不会让 last_epoch_started
更好懂;本系列往上写 Operator,是因为只懂 RADOS 的人仍会在
PVC Pending 时空手。两边互相外链,而不是互相吞并。
若有人把 Rook 理解成「Ceph 的发行版」,会期待它内置一套与 cephadm 对等的 Day-2 百科。Rook 的 Day-2 重点其实是:声明式升级、PDB/disruption、与 K8s 节点生命周期对齐。磁盘更换、CRUSH 细则、深度 scrub 策略,仍要回到 Ceph 自身工具与站内 ceph/ 篇章。Toolbox 提供的是进入 Ceph CLI 的桥,不是把所有 Ceph 运维知识搬进 Kubernetes API。
六、谱系与争论:Operator 边界画在哪
CoreOS / CNCF Operator 模式(CRD + controller)
→ Rook:Ceph 的声明式生命周期
→ CSI 外置:驱动不进 kube 树
→ Rook 内部再拆:Ceph 运算符 vs Ceph-CSI 运算符(v1.20 强化)
Operator 模式没有单一「OSDI 论文」可替代全部工程经验,但其问题定义是清楚的:把人工 runbook 收成可调和的期望状态。Rook 的分叉点在于 Ceph 自身已是重型分布式系统——Operator 若既管 daemon 又细管每一处 CSI 键值,升级面与所有权会缠死。v1.20 把 CSI 设置权威交给 Ceph-CSI Operator,可以读成对这一缠死的工程回应。
| 争论 | A 侧 | B 侧 | 本系列态度 |
|---|---|---|---|
| 单一 Rook 入口 vs 拆出 CSI Operator | 安装步骤少、心智简单 | 配置所有权清晰、CSI 可独立演进 | 接受 v1.20 现实:拆出;用第 5 篇写清迁移 |
谁拥有 Driver CR |
Rook 自动生成/覆盖 | 管理员 / Helm ceph-csi-drivers 权威 |
升级前导出 CR;避免盲目 apply
默认清单冲掉定制 |
| 多 CephCluster 共用一套 CSI | 节省控制面 | provisioner 前缀与密钥/mon 路由易混 | 开放问题:多集群下前缀与 Secret 设计仍易踩坑 |
开放问题(可检验):在同一 K8s 上运行两个 Rook 命名空间、两套 CephCluster 时,CSI provisioner 前缀与 mon endpoint Secret 的组合是否能在「只看 PVC Events」的情况下唯一归因到正确集群?若不能,平台层是否需要额外的策略控制器?第 5、15 篇会回到相关约束,但不假装今天已有完美标准答案。
与 ceph/ 三不变量对照,有助于记住分工:ceph/ 的不变量约束数据面正确性;本篇的所有权边界约束控制面归因。两者同时成立,系统才既「存得对」又「坏得可查」。只满足前者,会出现「Ceph 很健康但谁也不知道 PVC 卡在哪」;只满足后者,会出现「K8s 对象都很绿但 PG 正在 incomplete」。系列交叉阅读不是客套,是排障必要条件。
七、实践注意(无集群也可先记住)
- 先看 Operator Ready,再看 CephCluster Ready,再看 CSI Driver Ready——三层任一失败,应用 PVC 故事都讲不完。
- 改 CR 期望,而不是手删 Pod 当长期手段;手删可能被 reconcile 立即拉回,或掩盖真正的设备/健康问题。
- v1.20 新装:确认
csi-operator.yaml(或 Helm 等价物)与 drivers 所需 RBAC/SA 已就位,再纠结 StorageClass。 - 文档与示例必须同 tag:Quickstart
明确要求示例 YAML 来自 tagged release(如
v1.20.4),不要混 master。
需真实集群才能粘贴的验证命令语义:kubectl -n rook-ceph get cephcluster、kubectl -n rook-ceph get pods、toolbox
内 ceph status。本篇不伪造输出。
把「所有权」写成事故复盘模板,会更有用:
- 现象落在哪一类对象(CR / Pod / PVC / Ceph 状态)?
- 该类对象的权威控制器是谁(Rook Operator / Ceph-CSI Operator / kubelet+CSI Node / Ceph 本身)?
- 最近一次变更是改了 spec、chart values,还是手工 hotfix?
- 若变更在错误的权威对象上,期望行为是「无效果」还是「短暂有效后被 reconcile 打回」?
能回答这四问,就不必在群里同时重启 Operator、重建 Pool 与重装节点。第 13 篇排障坐标系会把此模板展开成 Pending / MountFailed 等具体树;本篇只把所有权钉子钉牢。
八、小结
- Rook 是 Ceph 的 Kubernetes Operator:CR 表期望,reconcile 出 daemon 与接线。
- 核心 CRD 以
CephCluster为根,块/文件/对象分别由 BlockPool、Filesystem、ObjectStore 等表达。 - v1.20 起 CSI 调谐权威在 Ceph-CSI Operator;Rook 不再通过旧 ConfigMap 键值拥有 CSI 设置。
- Rook 不解释 RADOS 内核;数据面问题转 ceph/。
- 下一篇沿
CephCluster走完 mon/mgr/osd 生命周期、设备发现与健康闸门。
九、参考资料
规范 / 官方文档(A)
- Rook v1.20 Quickstart —
rook.io/docs/rook/v1.20/Getting-Started/quickstart/。 - Rook v1.20 CephCluster CRD —
rook.io/docs/rook/v1.20/CRDs/Cluster/ceph-cluster-crd/(dataDirHostPath、cephVersion、storage、升级相关字段)。 - Rook v1.20 CSI Configuration —
rook.io/docs/rook/v1.20/Storage-Configuration/Ceph-CSI/csi-configuration/。 - Rook v1.20.0 Release — Breaking Changes(Ceph-CSI Operator required)。
设计脉络(B)
- Kubernetes Operator pattern(官方文档 / CNCF 生态叙述)— 问题定义:CRD + 控制器调和;非性能结论来源。
站内对照
实验台账
- 本篇无集群输出;CR 示例为结构示意。
→ 上一篇:CSI 规范与 K8s 接线 · 系列目录 · 下一篇:CephCluster 生命周期
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
【Rook / CSI】编排全景:五轴坐标系与 16 篇路线
相对 ceph/ RADOS 内核与 storage/ 云块选型,钉清 Rook/CSI 编排层缺口;定义 CSI RPC、sidecar、Operator/CRD、数据面归属、升级闸门五条坐标系,给出 16 篇阅读路线与 PVC Bound 之后 I/O 仍走 krbd→PG→BlueStore 的边界。
Rook / CSI:K8s 上的 Ceph 编排内核
补齐站内 Ceph RADOS 内核之上的编排层:CSI 规范与 sidecar、Rook Operator/CRD、Ceph-CSI Operator、RBD/CephFS 供给与挂载、VolumeSnapshot 语义差、升级闸门,以及排障与选型收束。
【Rook / CSI】CSI 规范与 K8s 接线:Controller、Node 与 sidecar
拆解 CSI Identity/Controller/Node 服务与 CreateVolume、NodeStageVolume、NodePublishVolume;对照 K8s external-provisioner/attacher/resizer/snapshotter 与 node-driver-registrar;给出 PVC→PV→Pod 挂载调用链与 in-tree→CSI 谱系,并点名规范最小面与 CSI-Addons 争论。
【Rook / CSI】CephCluster 生命周期:从 CR 到 mon/mgr/osd
沿 CephCluster CR 追踪 mon/mgr/osd Pod 如何被调和出来;钉设备发现前置条件、dataDirHostPath、HEALTH_OK 验证与 toolbox;说明 Rook 在 HEALTH_ERR 时默认拒绝 Ceph 升级,并对照 host 设备与 PVC 模式争论。