Ceph 生产环境搭建 | 第 8 天:存储池(Pool)创建与 PG 数量规划

第 8/20 天

引言:存储池——Ceph 数据组织的核心抽象

在前面的章节中,我们已经完成了 Monitor、Manager 和 OSD 节点的部署,并深入解析了 CRUSH Map 的故障域规划。此时集群已经具备了存储数据的硬件基础,但数据究竟如何被组织、分发和管理?这就引出了 Ceph 架构中最关键的逻辑抽象层——存储池(Pool)。

存储池是 Ceph 对外提供存储服务的逻辑分区。每一个 Pool 拥有独立的副本策略、纠删码策略、PG 数量、CRUSH 规则集和 QoS 配置。RBD 镜像、RGW 对象、CephFS 文件系统都建立在 Pool 之上。而 Placement Group(PG) 则是 Pool 内部的数据分片单元,是 CRUSH 算法进行数据映射的粒度——对象先被哈希到某个 PG,再由 CRUSH 将 PG 映射到一组 OSD。

PG 数量的规划直接影响集群的均衡度、恢复速度和资源开销。PG 太少会导致数据倾斜和单 OSD 压力过大;PG 太多则会增加 Monitor 和 OSD 的内存占用及 Peering 开销。本篇将系统讲解 Pool 与 PG 的架构原理,并在 Ubuntu 24.04 LTS 上基于 Ceph Squid v19 进行完整的实战部署。

架构与原理:Pool、PG 与数据映射机制

存储池的分层架构

Ceph 的数据组织采用三级抽象:Pool → PG → OSD,整个映射流程如下:

💻 代码示例

客户端写入对象

│

▼

Pool(逻辑分区,绑定 CRUSH Rule + 副本/EC 策略)

│

▼

PG(Placement Group,数据分片,CRUSH 映射的最小粒度)

│

▼

OSD Set(Primary + Replicas,实际存储节点)

│

▼

BlueStore(底层存储引擎,写 RocksDB + WAL)

关键概念解析

概念 说明 生产意义
Pool 逻辑存储分区,绑定副本策略和 CRUSH 规则 数据隔离、多租户、不同 SLA
PG (Placement Group) 对象的分组容器,CRUSH 映射粒度 决定数据分布的均衡度
PGP 用于 Placement 的 PG 数(PG 的上限) 控制实际数据分布的广度
PG Num Pool 配置的 PG 总数 影响 Peering 速度和内存占用
CRUSH Rule 定义数据如何选择故障域 跨机架/机房分布
Replicated Pool 多副本存储(通常 3 副本) 高 IOPS、低延迟场景
Erasure Coded Pool 纠删码存储(k+m 数据块) 冷数据、大对象存储

PG 映射的完整流程

当客户端写入一个对象时,Ceph 的映射过程分为以下步骤:

  1. 对象 → PG:通过 hash(对象名) & mask = pgid 计算对象所属的 PG,其中 mask 为 pg_num - 1
  2. PG → Up Set:CRUSH 算法根据 PG ID 和 CRUSH Rule 计算出理论上应该承载该 PG 的 OSD 列表
  3. Up Set → Acting Set:考虑 OSD 的状态(up/down),确定实际写入的 OSD 集合
  4. Primary OSD 接收写入:Acting Set 中的第一个 OSD 为主 OSD,负责接收客户端写入并同步给副本 OSD

PG 数量的黄金公式

Ceph 官方推荐的 PG 数量计算公式为:

💻 代码示例

PG总数 = (OSD数量 × 每OSD目标PG数) / 副本数

 

每OSD目标PG数通常为 100~200(Squid 版本推荐 100 左右)

例如:30 个 OSD、3 副本,则每个 Pool 建议的 PG 数为 (30 × 100) / 3 = 1000。再根据 Pool 存储的数据量占比进行分配。

PG 自动调优机制

从 Ceph Nautilus(v14)起引入了 PG Auto-scaling 机制,Manager 的 pg_autoscaler 模块会根据每个 Pool 的实际数据量、OSD 数量和目标 PG 数自动调整 pg_num。Squid v19 中这一机制默认开启,极大减轻了运维负担。

K8s Logo

部署实战:创建存储池与 PG 规划

环境准备

假设我们已完成前 7 天的部署,当前集群状态如下:

💻 代码示例

# 查看集群整体健康状态

ceph -s

 

# 查看当前 OSD 数量和分布

ceph osd tree

 

# 查看 Manager 模块状态

ceph mgr module ls

预期输出中集群状态为 HEALTH_OK,且已有多个 OSD 处于 up/in 状态。

检查 PG 自动调优模块

💻 代码示例

# 启用 pg_autoscaler 模块(Squid 默认已启用)

ceph mgr module enable pg_autoscaler

 

# 查看当前所有 Pool 的 PG 调优建议

ceph osd pool autoscale-status

输出示例:

💻 代码示例

POOL SIZE TARGET SIZE RATE RAW CAPACITY BIAS PG_NUM NEW PG_NUM AUTOSCALE

.mgr 0.5G 3.0 4560G 1.0 8 8 on

cephfs_data 0 3.0 4560G 1.0 32 32 on

rbd-pool 100G 3.0 4560G 1.0 64 64 on

手动创建副本存储池

在生产环境中,很多场景需要精确控制 PG 数量(如禁用自动调优或进行初始规划):

💻 代码示例

# 语法:ceph osd pool create <pool_name> <pg_num> [<pgp_num>] [replicated|erasure]

# 创建 RBD 专用存储池,3 副本,PG=128

ceph osd pool create rbd-pool 128 128 replicated

 

# 设置副本数为 3(生产环境最低要求)

ceph osd pool set rbd-pool size 3

 

# 设置最小副本数(低于此值拒绝写入)

ceph osd pool set rbd-pool min_size 2

 

# 关联应用类型(Squid 强制要求,否则告警)

ceph osd pool application enable rbd-pool rbd

PG 数量计算脚本

在创建 Pool 前,使用以下脚本计算合理的 PG 数量:

💻 代码示例

#!/usr/bin/env python3

"""Ceph PG 数量计算器 – 生产环境 PG 规划工具"""

 

import math

 

def calculate_pg_num(osd_count, replica_count, pool_data_ratio=1.0, target_pg_per_osd=100):

"""

计算 Pool 的推荐 PG 数量

 

参数:

osd_count: 集群 OSD 总数

replica_count: 副本数(replicated pool 为副本数,EC pool 为 k+m)

pool_data_ratio: 该 Pool 预计存储数据占总数据量的比例 (0.0~1.0)

target_pg_per_osd: 每个 OSD 的目标 PG 数 (Squid 推荐 100)

 

返回:

推荐的 PG 数(2 的幂次)

"""

raw_pgs = (osd_count * target_pg_per_osd * pool_data_ratio) / replica_count

 

# 向上取最近的 2 的幂次

power = math.ceil(math.log2(max(raw_pgs, 1)))

recommended = 2 ** power

 

# Squid 限制单个 Pool 最大 pg_num

recommended = min(recommended, 32768)

recommended = max(recommended, 8)

 

print(f"OSD 数量: {osd_count}")

print(f"副本数: {replica_count}")

print(f"数据占比: {pool_data_ratio * 100:.0f}%")

print(f"目标 PG/OSD: {target_pg_per_osd}")

print(f"原始计算 PG 数: {raw_pgs:.1f}")

print(f"推荐 PG 数 (2^n): {recommended}")

print(f"建议命令: ceph osd pool create <pool> {recommended} {recommended}")

return recommended

 

# 示例:30 个 OSD,3 副本,该 Pool 占 40% 数据量

calculate_pg_num(osd_count=30, replica_count=3, pool_data_ratio=0.4)

运行结果:

💻 代码示例

OSD 数量: 30

副本数: 3

数据占比: 40%

目标 PG/OSD: 100

原始计算 PG 数: 400.0

推荐 PG 数 (2^n): 512

建议命令: ceph osd pool create <pool> 512 512

创建并配置 CephFS 数据池

CephFS 需要 metadata 池和数据池,metadata 池建议使用低延迟、高 IOPS 配置:

💻 代码示例

# 创建 CephFS 元数据池(PG 较少,延迟优先)

ceph osd pool create cephfs_metadata 32 32

ceph osd pool set cephfs_metadata size 3

 

# 创建 CephFS 数据池(PG 较多,吞吐优先)

ceph osd pool create cephfs_data 128 128

ceph osd pool set cephfs_data size 3

 

# 创建 CephFS 文件系统

ceph fs new stellardata cephfs_metadata cephfs_data

 

# 为 CephFS 池关联应用类型

ceph osd pool application enable cephfs_metadata cephfs

ceph osd pool application enable cephfs_data cephfs

验证 Pool 状态

💻 代码示例

# 查看所有 Pool 的详细信息

ceph osd pool ls detail

 

# 查看 PG 映射与分布状态

ceph pg dump | head -20

 

# 检查 PG 分布是否均衡(每个 OSD 上的 PG 数)

ceph osd df

 

# 查看特定 Pool 的 PG 状态

ceph pg ls-by-pool rbd-pool

ceph osd df 输出示例:

💻 代码示例

ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE PGS

0 hdd 1.00000 1.00000 1000G 120G 100G 256M 1.2G 880G 12.0 64

1 hdd 1.00000 1.00000 1000G 122G 101G 256M 1.3G 878G 12.2 64

2 ssd 1.00000 1.00000 1000G 118G 98G 256M 1.1G 882G 11.8 64

…

K8s Logo

关键配置参数详解

💻 代码示例

# ceph.conf 中的 Pool 相关参数(通常通过 ceph tell 动态设置)

# 注意:Squid 版本推荐使用 ceph config set 命令而非编辑 ceph.conf

 

# — PG 相关参数 —

# osd_pool_default_pg_num: 新建 Pool 的默认 PG 数

ceph config set global osd_pool_default_pg_num 32

 

# osd_pool_default_pgp_num: 新建 Pool 的默认 PGP 数(通常与 pg_num 相同)

ceph config set global osd_pool_default_pgp_num 32

 

# osd_pool_default_size: 默认副本数

ceph config set global osd_pool_default_size 3

 

# osd_pool_default_min_size: 默认最小副本数(低于此值写操作被拒绝)

ceph config set global osd_pool_default_min_size 2

 

# — PG 自动调优参数 —

# mon_max_pg_per_osd: 每个 OSD 承载的最大 PG 数(Squid 默认 250)

ceph config set mon mon_max_pg_per_osd 250

 

# — 恢复参数 —

# osd_max_backfills: 同时进行 Recovery 的 PG 数上限

ceph config set osd osd_max_backfills 4

 

# osd_recovery_max_active: 每个 OSD 同时活跃的恢复操作数

ceph config set osd osd_recovery_max_active 8

存储池配额与 QoS 限制

生产环境中多租户隔离需要设置 Pool 级别的配额:

💻 代码示例

# 设置 Pool 最大存储容量为 500GB

ceph osd pool set-quota rbd-pool max_bytes 536870912000

 

# 设置 Pool 最大对象数为 100 万

ceph osd pool set-quota rbd-pool max_objects 1000000

 

# 取消配额限制

ceph osd pool set-quota rbd-pool max_bytes 0

ceph osd pool set-quota rbd-pool max_objects 0

 

# 查看当前配额设置

ceph osd pool get-quota rbd-pool

生产环境注意事项与踩坑提示

1. PG 数量不可随意缩减

PG 数量只能增加,不能随意减少。ceph osd pool set <pool> pg_num <new> 增大 PG 数时会触发数据重平衡(split),但减小 PG 数会导致数据不可逆迁移,生产环境中应避免此操作。如果确实需要调整,必须通过新建 Pool + 数据迁移的方式完成。

2. PGP Num 必须与 PG Num 同步

pgp_num 控制实际进行数据分布的 PG 数。增大 pg_num 后必须同步增大 pgp_num,否则新 PG 不会接收数据。正确做法是分步操作:

💻 代码示例

# 先增大 pg_num(创建新 PG,但数据暂不迁移)

ceph osd pool set rbd-pool pg_num 256

# 再增大 pgp_num(触发数据实际迁移到新 PG)

ceph osd pool set rbd-pool pgp_num 256

3. 警惕 PG Peering 风暴

大量 OSD 同时重启或网络抖动会导致大量 PG 进入 degraded 或 peering 状态。Squid 版本引入了 PG peering 限流机制,但仍建议在批量重启前设置:

💻 代码示例

# 降低恢复并发度,减少 Peering 压力

ceph config set osd osd_max_backfills 1

ceph config set osd osd_recovery_max_active 3

4. SSD 与 HDD 混合部署的 PG 差异

当集群中同时存在 SSD 和 HDD 时,不同设备的 PG 负载差异巨大。SSD 设备能承受更高 PG 数(因为 Peering 速度快),而 HDD 设备建议减少 PG 数以避免磁盘抖动。建议使用 CRUSH Device Class 将不同类型设备分配到不同 Pool。

5. PG 自动调优的局限性

pg_autoscaler 虽然方便,但在大规模集群(500+ OSD)中自动调优可能反应迟缓。建议在大规模生产环境中将关键 Pool 的 pg_autoscale 设为 off 并手动管理 PG 数量,避免自动调优在业务高峰期触发大规模数据迁移。

6. Erasure Coded Pool 的 PG 规划特殊考量

EC Pool 的 PG 计算公式中”副本数”应替换为 k + m(数据块+校验块)。例如 8+3 EC 策略,计算时使用 11 作为除数,而非 3。这会导致同样数据量下 EC Pool 的 PG 数远低于 Replicated Pool。

常见问题

Q: 新建 Pool 后 ceph -s 报 HEALTH_WARN “application not enabled on 1 pool(s)”,如何处理?

A: Squid 版本要求每个 Pool 必须关联应用类型(rbd、cephfs、rgw 或自定义)。执行 ceph osd pool application enable <pool_name> <app_type> 即可消除告警。例如 RBD 池用 rbd,CephFS 池用 cephfs,RGW 池用 rgw。

Q: PG 增加后集群一直在 rebalancing,业务卡顿严重怎么办?

A: 这是正常的 Recovery 过程,但可以通过参数控制恢复速率。使用 ceph config set osd osd_max_backfills 1 降低并发,设置 osd_recovery_op_priority 1 降低恢复线程优先级让业务 I/O 优先。也可通过 ceph osd set norebalance 暂时停止重平衡,业务低峰期用 ceph osd unset norebalance 恢复。

Q: autoscale-status 显示 NEW_PG_NUM 比 PG_NUM 大很多,是否应该手动增加?

A: 不建议手动增加。pg_autoscaler 会自动分批增加 PG 数(每次翻倍),避免一次性迁移大量数据。如果急需调整,可以手动设置 ceph osd pool set <pool> pg_num <new> 并同步设置 pgp_num,但需确保在业务低峰期执行。

总结

本篇系统讲解了 Ceph 存储池与 PG 的核心架构:Pool 是逻辑分区,PG 是 CRUSH 映射的最小粒度,二者共同决定了数据的分布策略。我们掌握了 PG 数量的黄金计算公式 (OSD × target_pg) / replica,了解了 PG 自动调优的工作机制,并通过实战完成了副本池、CephFS 数据池的创建与配额配置。

生产环境中最关键的认知是:PG 数量是集群健康度的核心调节器——过多增加内存和 Peering 开销,过少导致数据倾斜。理解了 Pool 和 PG,我们才能进入下一篇更深入的话题——副本策略与纠删码策略的深度对比。

下期预告

明天我们将发布第 9 天:副本与纠删码存储池策略对比实战。将深入对比 Replicated Pool 和 Erasure Coded Pool 在存储效率、读写性能、恢复速度上的差异,并通过实际部署 EC Pool 来演示如何在保证数据可靠性的前提下将存储成本降低 50% 以上。

系列目录

微信公众号二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像 - 恒星
欢迎您留下宝贵的见解!
提交
头像 - 恒星

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容