PG 是数据管理的逻辑单元,解决了海量对象的管理难题;
CRUSH 规则是数据分布的物理蓝图,决定了数据具体落在哪些硬盘上。
一、PG (归置组) 详解
PG 是 Ceph 中位于“对象(Object)”和“OSD(物理存储守护进程)”之间的一个抽象层。本身不存储数据,只记录对象的归属关系和映射信息。
为什么需要 PG?
Ceph 集群可能存储数十亿个对象。如果每个对象都独立追踪其位置、状态和副本信息,对 Monitor(集群监控器)和 OSD 的元数据管理将是巨大的负担,导致性能急剧下降。PG 的引入解决了这个问题:
- 降低元数据开销:直接管理海量对象会导致元数据爆炸,通过 PG 分组后,集群只需管理 PG 与 OSD 的映射关系,元数据规模大幅缩减。
- 提升运维效率:数据复制、故障恢复、负载均衡、数据校验(Scrub)均以 PG 为单位,粒度适中且高效。
- 保证数据均衡:哈希算法确保对象均匀分布到 PG,CRUSH 算法确保 PG 均匀分布到 OSD。
PG 的工作流程
用户数据 → 切分为 Object(默认4MB) → 哈希映射到 PG → CRUSH 映射到 OSD 集群
当一个客户端写入一个对象时,会经过两步映射:
- 对象 → PG:客户端通过哈希算法(
hash(object_id) % pg_num)计算出该对象属于哪个 PG。 - PG → OSD:客户端根据 CRUSH 算法 和集群地图,计算出这个 PG 应该由哪一组 OSD(一个主副本和多个副副本)来存储。
- PG 与 Pool:一个 Pool 包含
pg_num个 PG,所有 PG 均分 Pool 内的对象。
PG 状态速查
PG 的状态直接反映集群健康度,运维需重点关注以下状态:
| PG 状态 | 含义 | 正常 / 异常 | 处理建议 |
|---|---|---|---|
| active+clean | 主从副本齐全、数据一致,可正常读写 | 正常 | 无需处理 |
| peering | PG 内 OSD 正在同步元数据(如 OSD 上线 / 故障后) | 临时正常 | 等待完成,若长时间卡住需检查网络 / OSD 状态 |
| degraded | 部分副本 OSD 故障,数据副本不足,但仍有可用副本 | 异常(可读写) | 尽快恢复故障 OSD,避免进一步故障导致数据丢失 |
| backfilling | 新增 OSD 后,PG 正在向新 OSD 迁移数据 | 临时正常 | 等待数据均衡完成,期间集群性能可能下降 |
| recovering | OSD 故障恢复后,PG 正在重建缺失的副本数据 | 临时正常 | 等待恢复完成,避免中断 |
| down | PG 所有副本 OSD 均故障,无法提供读写服务 | 严重异常 | 立即恢复故障 OSD,否则数据永久丢失 |
| undersized | PG 副本数低于 min_size,拒绝读写请求 |
严重异常 | 紧急恢复故障 OSD 或临时降低 min_size(不推荐) |
| unkown | 表示数据不知道 |
二、CRUSH 规则生成
CRUSH(可控、可靠、去中心化)规则定义了 PG 如何映射到物理 OSD 上。它通过伪随机算法,确保数据均匀且智能地分布。
CRUSH 规则的核心步骤
一条规则通常包含以下指令:
take:指定遍历的起点(通常是根节点default或特定的根节点)。chooseleaf:核心指令。它会选择叶子节点(OSD),并确保选出的 OSD 位于不同的故障域(如不同的主机、机架),这是实现高可用的关键。emit:输出最终选定的 OSD 集合。
CRUSH 分层拓扑结构(Bucket 层级)
CRUSH 规则基于集群拓扑结构生效,Ceph 拓扑是分层的 Bucket 树,常见层级如下:
root(根) → datacenter(机房) → rack(机架) → host(主机) → osd(磁盘)
叶子 Bucket:osd,对应物理磁盘,是数据的最终存储载体。
非叶子 Bucket:host/rack/datacenter/root,用于故障域隔离。
自定义 Bucket:可根据需求添加层级,如 zone(区域)、type(介质类型:ssd/hdd)。
CRUSH 规则语法结构
CRUSH 规则是一个策略脚本,定义了 PG 选择 OSD 的步骤,核心语法如下:
rule <rule-name> {type <replicated/erasure> # 规则类型:副本/纠删码min_size <2> # 最小副本数,低于此值不生效max_size <10> # 最大副本数,高于此值不生效step take <root-name> # 选择根 Bucket(如 default)step chooseleaf firstn <N> type <bucket-type> # 选择叶子节点的父Bucketstep emit # 输出映射结果
}
关键指令解释:
step take:指定规则生效的根 Bucket,如default代表整个集群。- step chooseleaf firstn
: N:取值为 Pool 的副本数size,表示选择N个不同的 Bucket。type <bucket-type>:指定隔离级别,如host表示副本分布在不同主机,rack表示分布在不同机架。
CRUSH 规则生成实战(命令行 + 自定义)
(1)快速创建内置规则(推荐生产使用)
Ceph 提供命令行工具快速生成常用规则,无需手动编写语法。
| 规则需求 | 命令 | 适用场景 |
|---|---|---|
| 跨主机隔离(最常用) | ceph osd crush rule create-replicated host-rule default host |
中小型集群,避免单主机故障丢失数据 |
| 跨机架隔离 | ceph osd crush rule create-replicated rack-rule default rack |
大规模集群,避免单机架断电故障 |
| SSD 介质专属规则 | ceph osd crush rule create-replicated ssd-rule default host ssd |
热点数据存储,指定 SSD 介质 |
| HDD 介质专属规则 | ceph osd crush rule create-replicated hdd-rule default host hdd |
冷数据存储,指定 HDD 介质 |
(2)自定义 CRUSH 规则(高级场景)
适用于多机房、混合介质等复杂拓扑,步骤如下:
1、导出当前 CRUSH 规则
ceph osd crush rule dump > crush-rules.json
2、编辑规则文件(以跨机房 + 跨主机为例)
{"rule_id": 10,"rule_name": "dc-host-rule","type": "replicated","min_size": 2,"max_size": 5,"steps": [{"op": "take", "item": -1, "item_name": "default"},{"op": "choose", "type": "datacenter", "number": 3},{"op": "chooseleaf", "type": "host", "number": 1},{"op": "emit"}]
}
3、导入自定义规则
ceph osd crush rule import -i crush-rules.json
(3)CRUSH 规则与 Pool 绑定
创建 Pool 时绑定规则,或为已有 Pool 修改规则:
# 1. 创建 Pool 时绑定
ceph osd pool create mypool 512 512 replicated --rule host-rule# 2. 为已有 Pool 修改规则
ceph osd pool set mypool crush_rule host-rule
CRUSH 规则最佳实践
- 核心业务优先跨机架:关键数据的 CRUSH 规则设为
rack级别,提升容灾能力。 - 介质分层存储:创建 SSD/HDD 专属规则,将热点数据 Pool 绑定 SSD 规则,冷数据绑定 HDD 规则。
- 避免过度分层:拓扑层级过多会增加 CRUSH 计算开销
- 规则变更需谨慎:修改 CRUSH 规则会触发 PG 重映射,需在业务低峰期操作,并监控集群负载。
三、PG 与 CRUSH 协同工作流程
- 客户端写入数据:将数据切分为 Object,生成唯一 Object ID。
- Object 映射到 PG:通过
hash(Object ID) % PG_NUM计算出所属 PG。 - PG 映射到 OSD:CRUSH 算法根据 Pool 绑定的规则,结合集群拓扑,计算出该 PG 对应的 OSD 列表(主 + 副本)。
- 数据写入 OSD:客户端直接将数据写入主 OSD,主 OSD 同步数据到副本 OSD。
- 状态同步:所有 OSD 写入完成后,PG 状态变为
active+clean,主 OSD 向客户端返回写入成功。
