- Pool(存储池):是管理层面的逻辑单元(你创建它来划分业务)。
- PG(归置组):是分布层面的逻辑单元(它是连接“数据”与“硬盘”的中间桥梁)。 是 Pool 内管理对象的最小数据单元
- OSD:是真正的物理存储单元。
Pool (存储池):逻辑分区
Pool 是 Ceph 中用于组织和管理数据的逻辑容器。你可以把它想象成一个虚拟的存储分区。
- 作用:
- 数据隔离:为不同的业务或用户创建独立的 Pool,实现数据和配置的隔离。
- 策略定义:每个 Pool 可以独立配置数据冗余方式(副本数或纠删码规则)、PG 数量、CRUSH 规则等。
- 关键属性:
pg_num:Pool 中包含的 PG 数量,决定了数据分布的粒度。size:副本数量,例如size=3表示每个对象会保存 3 个副本。crush_rule:定义数据如何在物理设备上分布,例如跨主机或跨机架分布。
PG (归置组):物理分布的中间层
PG 是 Ceph 架构中最精妙的设计之一。它的引入是为了解决一个核心难题:如何高效地管理集群中海量的对象(可能是数十亿级别)。
PG 存在的意义
想象一下,如果 Ceph 直接管理每一个对象,当集群扩容或有硬盘(OSD)故障时,系统需要遍历所有对象来计算新的位置,这将是巨大的性能开销。
PG 通过引入一个“间接层”解决了这个问题:
- 对象 → PG:客户端写入一个对象时,通过哈希算法(
hash(object_id) % pg_num)将其映射到一个固定的 PG 中。 - PG → OSD:Ceph 通过 CRUSH 算法,计算出这个 PG 应该由哪一组 OSD(例如
[osd.1, osd.5, osd.9])来存储。
这种设计的好处是,Ceph 只需要管理数量相对较少且稳定的 PG(例如几千个),而不是海量的对象(数十亿个)。当集群状态变化(如 OSD 故障)时,Ceph 只需要重新计算 PG 与 OSD 的映射关系,然后以 PG 为单位进行数据迁移和恢复,极大地降低了系统开销。
Pool 和 PG 的关系
Pool 和 PG 是包含关系。
- 一个 Pool 由多个 PG 组成。
- 当你创建一个 Pool 时,必须为其指定
pg_num参数。 - 这个 Pool 里的所有对象,都会被分散到这个 Pool 所包含的各个 PG 中。
- 每个 PG 再通过 CRUSH 算法被放置到一组 OSD 上。
数据流向可以概括为:
对象 (Object) → 归属到某个 Pool → 通过哈希映射到 Pool 内的某个 PG → 通过 CRUSH 算法映射到一组 OSD
如何设置 PG 数量 (pg_num)
PG 数量的设置对集群性能至关重要,需要在数据分布的均衡性和系统资源开销之间取得平衡。
- PG 数量过少:会导致数据分布不均,某些 OSD 负载过高,形成“热点”。
- PG 数量过多:会增加 OSD 的内存和 CPU 开销,因为每个 PG 都需要维护元数据。
计算公式
Ceph 官方推荐每个 OSD 承载 100 到 200 个 PG。你可以使用以下公式来计算一个 Pool 的初始 PG 数量:
总 PG 数 = (OSD 总数 * 100) / 池大小
- 池大小:对于副本池,就是副本数(如 3);对于纠删码池,则是
k+m的和。 - 计算结果:需要将计算结果向上取整到最接近的 2 的 n 次幂(如 64, 128, 256, 512, 1024...)。
示例:
一个拥有 100 个 OSD 的集群,要创建一个 3 副本的 Pool。
- 计算:
(100 * 100) / 3 = 3333 - 取 2 的 n 次幂:最接近且大于 3333 的 2 的幂是 4096。
- 因此,建议将
pg_num设置为 4096。
提示:在现代 Ceph 版本中,可以启用 PG 自动伸缩功能 (
pg_autoscale_mode = on),让 Ceph 根据集群状态自动调整 PG 数量,简化了运维工作。
