口头说明 Ceph 的整个过程:假设客户端需要向 Ceph 写入一段数据,从应用层一直讲到磁盘。
1. 上层数据先转换成 RADOS 对象
用户看到的接口可能是:
- RBD 块设备
- CephFS 文件系统
- RGW 提供的 S3 对象接口
- 直接调用 librados
无论入口是什么,最终都要转换为底层的 RADOS 对象。
例如,一个较大的 RBD image 不会作为单个对象保存,而会被切分成多个固定大小的 RADOS 对象。每个对象至少可以用下面的信息定位:
1 | Pool + Namespace + Object ID |
为了简化,后面只使用:
1 | Pool + Object ID |
2. 客户端先联系 MON
客户端启动后,首先需要知道:
- 集群中有哪些 OSD
- 哪些 OSD 是
up、哪些是down - Pool 使用什么副本策略
- 集群的 CRUSH 拓扑和规则
- 当前的数据映射状态
这些信息来自 MON 维护的 Cluster Map,包括:
- Monitor Map
- OSD Map
- CRUSH Map
- MDS Map 等
因此客户端先联系一个 MON,完成 CephX 身份认证,并获取最新的 Cluster Map。
这里最重要的一点是:MON 告诉客户端集群当前是什么样子,但不会代理客户端的数据读写。
客户端获得 Map 后,就可以自己计算数据位置,不需要每次都询问 MON。
3. Object 映射到 PG
现在客户端知道:
1 | Pool = rbd |
客户端先对 Object ID 做哈希计算,再结合这个 Pool 的 PG 数量,计算对象属于哪个 PG。可以简化理解成:
1 | hash(Object ID) → PG 编号 |
假设计算结果是 PG 17,而这个 Pool 的 ID 是 4,那么最终 PG ID 可能表示为:
1 | 4.11 |
这里的 11 通常是十六进制显示,概念上相当于我们假设的 PG 17。因此得到:
1 | 对象 rbd_data.1234 → PG 4.11 |
因为对象可能有数十亿个。如果 Ceph 为每个对象单独维护完整的位置和迁移历史,元数据成本会非常高。
PG 把一批对象组合起来,让 Ceph 以 PG 为单位进行:
- 数据放置
- 副本管理
- Peering
- Recovery
- Backfill
- Scrub
PG 是对象和 OSD 之间的一层间接映射。
4. PG 通过 CRUSH 映射到 OSD
客户端已经知道对象属于 PG 4.11,接下来需要确定这个 PG 应该由哪些 OSD 保存。
客户端结合:
1 | PG ID |
在本地运行 CRUSH 算法。假设 Pool 配置为:
1 | size = 3 |
这表示:
- 每个对象正常保存三份
- 三份副本应尽量位于不同主机
- 只选择 HDD 类型的 OSD
CRUSH 可能计算出:
1 | PG 4.11 → [osd.2, osd.7, osd.12] |
这组 OSD 称为这个 PG 的集合。第一个 OSD 通常是 Primary:
1 | Primary = osd.2 |
CRUSH 不是从中央数据库查询“对象在哪块盘”,而是根据确定性的算法计算期望位置。客户端和 OSD 使用相同的 Map 和算法,会得到相同结果。
5. Up Set 与 Acting Set
Up Set
CRUSH 根据当前 OSD Map 计算出来的、理论上应该负责这个 PG 的 OSD:
1 | Up Set = [osd.2, osd.7, osd.12] |
Acting Set
当前实际负责处理这个 PG 请求的 OSD:
1 | Acting Set = [osd.2, osd.7, osd.12] |
集群正常时,两者通常相同。如果 OSD 故障、PG 正在迁移或者发生临时映射,两者可能不同。例如:
1 | Up Set = [osd.2, osd.7, osd.15] |
这可能表示 CRUSH 认为以后应该由 osd.15 负责,但迁移还没完成,当前实际数据仍由 osd.12 提供。客户端真正发送请求时,要依据当前生效的映射联系 Acting Set 的 Primary。
6. 客户端联系 Primary OSD
假设 Acting Set 是:
1 | [osd.2, osd.7, osd.12] |
那么 osd.2 是 Primary OSD。
客户端不会分别向三个 OSD 写三次,而是把写请求发送给 Primary:
1 | 客户端 → osd.2 |
Primary 负责协调这个 PG 的操作顺序和副本写入。这样可以避免多个副本分别接收客户端请求,产生并发顺序不一致的问题。
7. Primary 将数据复制给其他 OSD
osd.2 收到写请求后:
- 检查客户端的 CephX 权限。
- 确认请求属于自己负责的 PG。
- 在本地执行写入。
- 向
osd.7和osd.12发送副本写请求。 - 等待所需副本完成。
- 向客户端返回成功。
数据流可以表示为:
1 | ┌→ osd.7 |
客户端只直接联系 Primary,但 Primary 会协调其他副本。
如果这是纠删码池,Primary 的工作不是简单复制完整对象,而是将数据编码成 K 个数据分片和 M 个校验分片,再分发到 Acting Set 中的多个 OSD。
8. OSD 通过 BlueStore 写入磁盘
每个 OSD 收到数据后,交给自己的 BlueStore 后端。BlueStore 主要涉及:
1 | block |
如果单独配置了高速设备,还可能有:
1 | block → 主要对象数据,通常在 HDD |
BlueStore 不需要在 OSD 数据盘上再创建 XFS 或 ext4,而是直接管理块设备。它还负责:
- 磁盘空间分配
- 对象元数据
- 校验和
- 压缩
- RocksDB/BlueFS 管理
当需要的副本完成持久化后,Primary 才按照相应写入规则向客户端确认。
9. 读取过程
读取过程的前半段与写入基本一致:
1 | 客户端获取 Cluster Map |
正常情况下,客户端向 Primary 读取:
1 | 客户端 ← osd.2 |
Primary 从本地 BlueStore 读取对象并返回。如果 Primary 已经故障,MON 和 OSD 会更新集群状态,并为 PG 形成新的 Acting Set。例如:
1 | 原 Acting Set = [osd.2, osd.7, osd.12] |
此时 osd.7 可以成为新的 Primary。客户端收到更新的 OSD Map 后,重新计算并向 osd.7 请求。客户端发现 Map 过期时,OSD也可以提示它刷新 Map 并重试。
10. OSD 故障后的恢复
假设 osd.12 故障:
1 | [osd.2, osd.7, osd.12] |
大致会发生:
- 其他 OSD 通过 heartbeat 发现
osd.12无响应。 - OSD 向 MON 报告。
- MON 根据报告更新 OSD Map,将其标记为
down。 - 相关 PG 可能变成
active+undersized+degraded。 - 等待相应策略或管理员操作后,故障 OSD可能被标记为
out。 - CRUSH 为 PG 选择新的 OSD,例如
osd.15。 - 剩余副本与新 OSD进行 peering 和 recovery/backfill。
- 恢复完成后,PG 回到
active+clean。
新的副本集合可能变为:
1 | [osd.2, osd.7, osd.15] |
需要注意:
- Peering:相关 OSD 确认 PG 状态、日志和权威历史。
- Recovery:恢复缺失或过期的对象。
- Backfill:向新 OSD 批量迁移该 PG 所需的数据。
active:PG 可以处理客户端 I/O。clean:PG 的目标副本全部完整并处于正确位置。
Peering 完成不等于数据已经恢复完成,因此可能出现:
1 | active+degraded |
表示 PG 已经能够提供服务,但副本还不完整。
各组件在数据路径中的位置
| 组件 | 作用 | 是否持续经过用户数据 |
|---|---|---|
| MON | 认证、维护 Cluster Map、形成 quorum | 否 |
| MGR | 监控、指标、Dashboard、管理模块 | 否 |
| OSD | 存储对象、复制、恢复、Scrub | 是 |
| BlueStore | OSD 的本地存储后端 | 是 |
| MDS | 管理 CephFS 元数据 | 文件元数据经过,文件内容通常不经过 |
| RGW | 将 S3/Swift 请求转换为 RADOS 操作 | RGW 请求经过 |
| RBD | 将块 I/O 转换为 RADOS 对象操作 | 是 |
| CRUSH | 计算 PG/OSD 数据位置 | 它是算法,不是守护进程 |
一句话总结整个过程:
上层接口把数据转换为 RADOS 对象;客户端从 MON 获取 Cluster Map,利用对象 ID 计算 PG,再通过 CRUSH 计算 Acting Set,联系其中的 Primary OSD;Primary 协调副本或纠删码分片写入,最后由各 OSD 的 BlueStore 将数据持久化到磁盘。
本文作者:jujimeizuo
本文地址: https://blog.jujimeizuo.cn/2026/08/06/ceph-in-a-word/
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0 协议。转载请注明出处!