2. Ceph核心架构与数据分布
Ceph 之所以能在无中心节点的前提下提供统一的对象、块与文件存储,关键在于它把“数据放在哪里”这件事从查表变成了可计算。理解 Ceph,本质上要理解三层:底层负责可靠存储的 RADOS,中间负责把对象映射到具体设备的 CRUSH 与 PG,上层负责对外提供接口的 RBD、RGW、CephFS。本节围绕这条主线,把 MON、OSD、MDS、MGR 的职责和 Pool、PG、CRUSH 的协作关系讲清楚。
一、RADOS:一切存储能力的底座
RADOS(Reliable Autonomic Distributed Object Store,可靠自治分布式对象存储)是 Ceph 的存储内核。它对外暴露的并不是文件或块,而是“对象”:每个对象由对象名(oid)、命名空间(namespace)和所属 Pool 唯一确定,数据以对象为单位被复制、校验和恢复。RBD 的块设备、RGW 的 S3/Swift 对象、CephFS 的文件数据,最终都会被拆解成 RADOS 对象落到 OSD 上。
RADOS 由两类核心守护进程支撑:OSD 负责实际的数据存取,MON 负责维护集群的权威状态。RADOS 的“自治”体现在:客户端不需要向中心节点询问数据位置,而是自己用 CRUSH 算出位置;OSD 之间通过心跳和 PG 日志互相监督,发现故障后自动触发数据恢复。
二、MON、OSD、MDS、MGR 的分工
MON(Monitor)维护集群的 Cluster Map,包括 Monitor Map、OSD Map、PG Map、CRUSH Map 和 MDS Map。它使用 Paxos 在多个 MON 之间达成一致,通常部署 3 或 5 个,保证多数派可用。MON 不存用户数据,但它是集群的“宪法”:客户端必须先拿到 Map,才能计算数据位置。
OSD(Object Storage Daemon)是真正存放数据的进程,通常一块盘对应一个 OSD。它负责对象的读写、副本复制、数据校验、故障恢复和向 MON 上报状态。OSD 的数量和权重直接决定集群容量与数据分布。
MDS(Metadata Server)只服务于 CephFS,负责文件系统的目录树、inode、权限等元数据。对象存储和块存储不需要 MDS。MDS 可以多活,元数据被切分成子树由不同 MDS 承担。
MGR(Manager)负责监控指标、Dashboard、Prometheus 导出、编排模块等管理面功能。它不参与数据路径,但为运维提供可观测性。
三、Pool 与 PG:数据分布的中间层
Pool 是管理员划分的逻辑存储池,它规定了副本数(size)、最小可用副本数(min_size)、PG 数量、CRUSH 规则等策略。客户端写入对象时,先确定它属于哪个 Pool,再在 Pool 内计算它属于哪个 PG。PG(Placement Group,归置组)是对象到 OSD 之间的“中间聚合层”:一个 PG 包含若干对象,一个 PG 整体被映射到一组 OSD 上。
为什么需要 PG?如果每个对象都单独计算 OSD 位置,元数据量和迁移粒度都会爆炸。把对象先聚合成 PG,再以 PG 为单位做复制、迁移和恢复,可以大幅降低管理开销。PG 数量需要提前规划,经验公式是:PG总数 ≈ (OSD总数 × 100) / 副本数,再向上取到 2 的幂。例如 5 个 OSD、副本数 3,则约需 167 个 PG,取 256。PG 太少会导致数据分布不均,太多则增加 MON 和 OSD 的元数据负担。
四、CRUSH:把位置变成计算
CRUSH(Controlled Replication Under Scalable Hashing)是 Ceph 数据分布的核心算法。它接收三个输入:对象所属 PG 的 ID、CRUSH Map、以及一个随机种子(通常是 rjenkins 哈希)。输出是一组 OSD 编号,即该 PG 的主副本和从副本位置。
CRUSH Map 是一棵层次树,典型结构为:root → rack → host → osd。每个节点有类型和权重,OSD 权重通常与磁盘容量成正比。CRUSH 通过“选择桶”算法在树中逐层挑选,并遵循故障域隔离规则:同一个 PG 的多个副本不能落在同一 host 或同一 rack 下。这样即使整机架断电,数据仍然可用。
CRUSH 的最大价值在于“确定性”:只要 Map 不变,任何客户端对同一 PG 计算出的 OSD 集合完全一致,因此不需要中心索引。当 OSD 增减时,只有受影响的 PG 需要迁移,迁移量约为总数据的 1/N,而不是全量重分布。
五、一次写入的完整路径
假设客户端向 Pool rbd 写入对象 rbd_data.abc123,副本数为 3,集群有 5 个 OSD。过程如下:
- 客户端从 MON 获取最新的 OSD Map 和 CRUSH Map。
- 用对象名哈希得到 PG ID,例如
2.1f。 - 用 CRUSH 计算 PG
2.1f对应的 OSD 集合,例如[OSD.2, OSD.0, OSD.4],其中 OSD.2 为主副本。 - 客户端直接向主 OSD.2 发送写请求。
- 主 OSD 写入本地后,并行转发给 OSD.0 和 OSD.4。
- 两个从副本确认后,主 OSD 向客户端返回写入成功。
整个过程客户端只与主 OSD 通信,MON 不参与数据路径。如果某个从 OSD 超时未确认,主 OSD 会将其标记为 degraded,并在后台启动恢复,把缺失的副本补齐到其他 OSD 上。
ceph -s 中的 HEALTH_OK 表示所有 PG 处于 active+clean;若出现 active+degraded,说明有副本缺失但数据仍可读写;若出现 undersized,说明可用副本数低于 min_size,写入可能被阻塞。六、关键参数与观察点
| 对象 | 关键参数 | 作用 |
|---|---|---|
| Pool | size / min_size | 副本数与最小可用副本数 |
| Pool | pg_num / pgp_num | PG 数量与用于放置的 PG 数量 |
| CRUSH | weight | OSD 权重,影响数据分配比例 |
| CRUSH | rule | 故障域隔离规则,如 rack 级隔离 |
| OSD | up / in | 进程是否运行、是否参与数据分配 |
理解这组关系后,再看 Ceph 的扩容、故障恢复和性能调优,就能落到具体对象上:扩容改的是 CRUSH Map 和 OSD 权重,恢复看的是 PG 状态,性能瓶颈则要区分是客户端到主 OSD 的网络、主 OSD 的磁盘 IO,还是副本同步的带宽。RADOS 提供可靠存储,CRUSH 和 PG 决定数据落在哪里,MON、MDS、MGR 分别守住状态、元数据和管理面,这就是 Ceph 核心架构的完整图景。