Ceph 生产环境搭建 | 第 9 天:副本与纠删码存储池策略对比实战

第 9/20 天

引言:存储池策略——副本与纠删码的抉择

在上一篇中,我们完成了存储池(Pool)的创建与 PG 数量规划,集群已经能够以默认的副本模式对外提供存储服务。然而,在生产环境中,并非所有数据都需要相同级别的冗余策略。副本池(Replicated Pool) 简单可靠但存储开销大,纠删码池(Erasure Coded Pool) 以计算换空间、大幅提升存储效率但牺牲了部分延迟性能。

这一选择直接影响着集群的存储成本、读写性能和容灾能力。一个典型的生产集群往往同时部署两种策略:热数据走副本池以获得最低延迟,温冷数据走纠删码池以最大化存储利用率。本篇将深入剖析两种策略的工作原理、数据流向和设计考量,并在 Ubuntu 24.04 LTS + Ceph Squid v19 环境下完成完整的部署实战。

Ceph 存储架构

一、副本池架构与工作原理

1.1 数据分布机制

副本池是 Ceph 最传统、最成熟的存储策略。每个写入的对象会被完整复制到 N 个 OSD 上(默认 3 副本),每个副本位于不同的故障域中。其核心流程如下:

阶段 操作 参与组件
客户端写入 计算对象所属 PG 的主 OSD Client、Monitor(CRUSH Map)
主 OSD 分发 将数据转发到其余副本 OSD Primary OSD → Replica OSDs
副本确认 所有副本写入完成后 ack Replica OSDs → Primary OSD
客户端确认 主 OSD 向客户端返回成功 Primary OSD → Client

1.2 读写一致性保证

Ceph 采用 Primary-Replica 模型保证强一致性:

  • 写入路径:客户端只与 Primary OSD 通信,Primary 负责将数据并行分发到所有 Replica OSD。只有当所有副本都返回 ack 后,Primary 才向客户端确认写入完成。这确保了任何成功写入的数据在所有副本上都有一致拷贝。
  • 读取路径:客户端默认从 Primary OSD 读取数据。虽然 Ceph 支持从副本读取(rbd_balance_snap_reads、osd_read_op_preference),但为保证强一致性,生产环境通常仍从 Primary 读取。

1.3 存储开销分析

3 副本意味着有效存储容量仅为原始容量的 1/3(33.3%)。对于 TB 级别的集群,这是巨大的硬件成本。2 副本可将效率提升至 50%,但容错能力下降为仅能丢失 1 个 OSD。

二、纠删码池架构与工作原理

2.1 纠删编码基本原理

纠删码(Erasure Code, EC)借鉴了 RAID 5/6 的思想,但将其扩展到分布式层面。一个对象被拆分为 k 个数据块(data chunks) 和 m 个编码块(coding chunks),这 k+m 个块分散存储在不同的 OSD 上。

以最常见的 k=4, m=2 配置为例:

  • 一个 4MB 的对象被拆分为 4 个 1MB 数据块 + 2 个 1MB 编码块
  • 总共占用 6MB 原始空间,有效存储效率为 4/6 ≈ 66.7%
  • 可容忍 2 个块丢失(即 2 个 OSD 故障)仍能完整恢复数据
💻 代码示例

对象 (4MB)

├── data chunk 0 (1MB) → OSD-1

├── data chunk 1 (1MB) → OSD-2

├── data chunk 2 (1MB) → OSD-3

├── data chunk 3 (1MB) → OSD-4

├── coding chunk 0 (1MB) → OSD-5 ← Reed-Solomon 编码

└── coding chunk 1 (1MB) → OSD-6 ← Reed-Solomon 编码

 

存储效率: 4/(4+2) = 66.7% 容错: 可丢失 2 个块

对比 3 副本: 效率 33.3% 容错: 可丢失 2 个副本

2.2 Reed-Solomon 编码

Ceph 默认使用 Reed-Solomon 纠删算法。其数学基础是伽罗华域 GF(2^n) 上的多项式运算,能够从任意 k 个存活的块中完整恢复原始数据。编码块是数据块的线性组合:

💻 代码示例

# Reed-Solomon 编码原理示意(伪代码)

# 编码矩阵 C 将 k 个数据块变换为 m 个编码块

coding_chunk[i] = sum(data_chunk[j] * C[i][j] for j in range(k)) mod GF(2^8)

 

# 解码:当部分块丢失时,从存活的 k 个块重建

# 存活块构成新方程组,求逆矩阵即可恢复原始数据

2.3 数据流向差异

维度 副本池 纠删码池
写入路径 Primary → 所有 Replica(全量复制) Primary → 数据/编码块 OSD(分块分发)
读取路径 Primary 返回完整对象 Primary 需读取 k 个数据块并重组
网络开销 写 N 份完整数据 写 k+m 份分块数据(总量更少)
CPU 开销 极低(仅复制) 编码/解码计算开销显著
故障恢复 从任意存活副本完整拷贝 从 k 个存活块数学重建

2.4 纠删码池的局限性

EC 池虽然存储效率高,但存在重要限制:

  • 不支持 omap:EC 池无法存储对象映射(omap)数据,因此不能直接用于 RBD 元数据池、CephFS 元数据池或 RGW index 池
  • 写入放大:部分写入(覆盖写)需要读取-修改-写回整个对象,性能极差
  • 延迟更高:读取需从多个 OSD 聚合 k 个块,网络往返延迟叠加
  • 典型适用场景:对象存储 RGW 的数据池、归档冷数据、备份存储

Ceph 存储策略对比

三、部署实战:副本池创建与验证

3.1 环境准备

确保集群已正常运行,OSD 数量满足故障域要求:

💻 代码示例

# 检查集群健康状态

ceph -s

 

# 查看 OSD 数量与分布

ceph osd tree | head -30

 

# 确认可用磁盘空间

ceph df

 

# 查看当前存储池列表

ceph osd pool ls detail

3.2 创建生产级副本池

以下命令创建一个用于 RBD 块存储的 3 副本生产池:

💻 代码示例

# 创建副本池,指定 PG 数量(基于第 8 天的 PG 规划)

# pool名称: rbd-ssd-pool,目标 ~100 个 PG

ceph osd pool create rbd-ssd-pool 128 128 replicated

 

# 设置副本数为 3(默认值,显式声明)

ceph osd pool set rbd-ssd-pool size 3

 

# 设置 min_size,低于此值停止写入(生产建议 >= 2)

ceph osd pool set rbd-ssd-pool min_size 2

 

# 启用 RBD 应用(标记池用途)

ceph osd pool application enable rbd-ssd-pool rbd

 

# 初始化 RBD 池

rbd pool init rbd-ssd-pool

3.3 关键配置参数详解

💻 代码示例

# pg_num / pgp_num:PG 数量与放置组数量(应保持一致)

ceph osd pool set rbd-ssd-pool pg_num 128

ceph osd pool set rbd-ssd-pool pgp_num 128

 

# crush_rule:指定使用的 CRUSH 规则(故障域控制)

# 使用第 7 天定义的 host 级别故障域规则

ceph osd pool set rbd-ssd-pool crush_rule replicated_rule

 

# noscrub / nodeep-scrub:临时禁用清理(维护期间使用)

# 生产环境不建议长期禁用

ceph osd pool set rbd-ssd-pool noscrub false

ceph osd pool set rbd-ssd-pool nodeep-scrub false

 

# recovery_priority:恢复优先级(0-63,值越大优先级越高)

ceph osd pool set rbd-ssd-pool recovery_priority 5

 

# 查看池完整配置

ceph osd pool get rbd-ssd-pool all

3.4 验证副本池状态

💻 代码示例

# 查看池详细状态

ceph osd pool ls detail | grep rbd-ssd-pool

 

# 查看池的 PG 分布

ceph pg ls-by-pool rbd-ssd-pool | head -20

 

# 查看副本完整性统计

ceph osd pool stats rbd-ssd-pool

 

# 查看实际存储效率(已用/可用)

ceph df | grep -A2 rbd-ssd-pool

四、部署实战:纠删码池创建与验证

4.1 创建纠删码配置文件

EC 池使用独立的 erasure-code-profile 定义编码参数。生产环境通常自定义 profile:

💻 代码示例

# 查看默认 EC profile

ceph osd erasure-code-profile ls

ceph osd erasure-code-profile get default

 

# 创建生产级 EC profile:k=4, m=2, host 故障域

# 含义:4 数据块 + 2 编码块,分布在不同 host

ceph osd erasure-code-profile set ec-profile-prod

k=4

m=2

crush-failure-domain=host

crush-device-class=ssd

plugin=jerasure

technique=reed_sol_van

 

# 验证 profile 内容

ceph osd erasure-code-profile get ec-profile-prod

4.2 创建纠删码存储池

💻 代码示例

# 创建 EC 池

# 注意:EC 池的 PG 数量计算与副本池不同

# k+m=6 个块需要分布在至少 6 个不同 host 上

ceph osd pool create ec-data-pool 128 128 erasure ec-profile-prod

 

# 设置 PG autoscaler 为 on(推荐 EC 池使用自动伸缩)

ceph osd pool set ec-data-pool pg_autoscale_mode on

 

# 启用 RGW 应用(EC 池典型用于对象存储数据池)

ceph osd pool application enable ec-data-pool rgw

4.3 为 EC 池配置元数据池(RGW 场景)

EC 池不支持 omap,RGW 需要一个副本池作为元数据池:

💻 代码示例

# 创建 RGW 元数据池(副本池)

ceph osd pool create rgw-meta-pool 64 64 replicated

ceph osd pool set rgw-meta-pool size 3

ceph osd pool application enable rgw-meta-pool rgw

 

# 创建 RGW index 池(副本池,用于 bucket index)

ceph osd pool create rgw-index-pool 64 64 replicated

ceph osd pool set rgw-index-pool size 3

ceph osd pool application enable rgw-index-pool rgw

 

# 创建 RGW 控制池

ceph osd pool create rgw-control-pool 32 32 replicated

ceph osd pool application enable rgw-control-pool rgw

 

# 在 zone 配置中将 ec-data-pool 设为数据池

# 后续 RGW 章节会详细展开

4.4 验证纠删码池状态

💻 代码示例

# 查看 EC 池编码信息

ceph osd pool ls detail | grep ec-data-pool

 

# 查看 EC profile 生效情况

ceph osd dump | grep ec-data-pool

 

# 查看块分布(确认 k+m 块在不同 host)

ceph pg ls-by-pool ec-data-pool | head -10

 

# 验证存储效率

ceph df

# STORED 栏显示原始存储量,USED 栏显示实际占用量

# EC 池 USED/STORED 比值应接近 (k+m)/k = 1.5

五、性能基准测试对比

使用 Ceph 内置基准工具对比两种池的读写性能:

💻 代码示例

# 副本池写入基准测试(10秒,4MB块大小,16并发)

rados bench -p rbd-ssd-pool 10 write –no-cleanup -b 4194304 -c 16

 

# 纠删码池写入基准测试(同样参数)

rados bench -p ec-data-pool 10 write –no-cleanup -b 4194304 -c 16

 

# 顺序读取测试

rados bench -p rbd-ssd-pool 10 seq

rados bench -p ec-data-pool 10 seq

 

# 清理基准测试数据

rados -p rbd-ssd-pool cleanup

rados -p ec-data-pool cleanup

典型结果对比(12 节点集群,SSD 介质):

💻 代码示例

{

"replicated_pool_write": {

"bandwidth": "850 MB/s",

"iops": 212,

"latency_avg": "75ms"

},

"erasure_coded_pool_write": {

"bandwidth": "520 MB/s",

"iops": 130,

"latency_avg": "123ms"

},

"storage_efficiency": {

"replicated_3x": "33.3%",

"ec_4_2": "66.7%"

},

"conclusion": "EC 写入带宽约为副本池的 61%,但存储效率提升 100%"

}

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

6.1 纠删码池踩坑提示

踩坑一:EC 池覆盖写性能灾难

EC 池对覆盖写(overwrite)支持不佳。每次部分写入需要先读取完整对象、解码、修改、重新编码并写回所有 k+m 个块,导致严重的写放大。

💻 代码示例

# 生产建议:EC 池仅用于 append-only 或一次性写入场景

# RGW 对象存储天然是 append-only 模型,与 EC 池完美匹配

# RBD 块存储默认不支持 EC(除非使用 cache tiering)

踩坑二:EC 池 PG 数量需要更多 OSD

k=4, m=2 的 EC 池需要至少 6 个位于不同故障域的 OSD。如果 host 数量不足 6,CRUSH 将无法放置所有块,PG 会处于 incomplete 状态。

💻 代码示例

# 检查 host 数量是否满足 EC profile 要求

ceph osd tree | grep host | wc -l

# 至少需要 k+m 个 host(如 k=4,m=2 则至少 6 个 host)

6.2 副本数与 min_size 调优

💻 代码示例

# 生产环境 min_size 调优建议:

# size=3, min_size=2 → 允许 1 个 OSD 故障时继续写入(推荐)

# size=3, min_size=3 → 严格模式,任何 OSD 故障即停止写入(数据更安全但可用性低)

# size=2, min_size=1 → 高风险,仅用于测试环境

 

# 查看当前 min_size

ceph osd pool get rbd-ssd-pool min_size

 

# 紧急降级场景(多 OSD 故障时保可用性)

# 仅在确认数据一致性风险后执行

ceph osd pool set rbd-ssd-pool min_size 1

6.3 存储效率与容错的平衡选择

场景 推荐策略 理由
RBD 块存储(虚拟机/容器盘) 3 副本 低延迟、支持覆盖写
RBD 元数据池 3 副本 需要 omap 支持
RGW 对象数据池 EC k=4,m=2 对象 append-only,存储效率优先
RGW index/control 池 3 副本 需要 omap 支持
CephFS 数据池 3 副本或 EC 冷数据可用 EC,热数据用副本
CephFS 元数据池 3 副本 必须,需 omap + 低延迟
归档备份存储 EC k=8,m=4 极致存储效率(66.7%→更高)

6.4 安全与容灾考量

  • 故障域隔离:EC 池的 m 值决定了可容忍的故障数。如果 m=2 但所有编码块在同一机柜,机柜故障将导致数据丢失。务必在 EC profile 中设置 crush-failure-domain=host 或 rack
  • 数据校验:定期执行 deep-scrub 确保块完整性。EC 池的 scrub 会校验所有 k+m 块的数学一致性
  • 恢复时间:EC 池 OSD 故障后重建需要从 k 个存活块读取并计算,恢复时间显著长于副本池的完整拷贝

Ceph 生产部署

七、常见问题

Q1:纠删码池能否直接用于 RBD 块存储?

EC 池不能直接作为 RBD 的数据池,因为 RBD 需要覆盖写和 omap 支持。生产方案是使用 Cache Tiering:前端放置一个副本池作为缓存层,后端为 EC 池。热数据在副本缓存中低延迟读写,冷数据被 flush 到 EC 池节省空间。但 Cache Tiering 配置复杂、运维成本高,需谨慎评估。在 Ceph Squid v19 中,推荐对块存储场景直接使用副本池,EC 池保留给对象存储。

Q2:如何从副本池迁移数据到纠删码池?

Ceph 不支持在线将现有池从副本模式转换为 EC 模式。迁移方案有两种:(1)创建新的 EC 池,使用 rados cppool 命令批量拷贝对象;(2)在 RGW 层面配置多站点同步,将新数据写入 EC 池。迁移前务必做完整备份,并在低峰期执行,避免影响生产 I/O。

Q3:纠删码的 k 和 m 值如何选择?

k 值决定存储效率,m 值决定容错能力。常见组合:k=4,m=2(效率 66.7%,容 2 故障)适合中等规模;k=8,m=4(效率 66.7%,容 4 故障)适合大规模归档;k=6,m=3(效率 66.7%,容 3 故障)是均衡选择。注意 k+m 必须小于等于集群中故障域(host/rack)的数量。增大 k 值虽可提升效率,但写入延迟随之增加(需等待更多 OSD ack)。

八、总结

本篇深入对比了 Ceph 的两种核心存储池策略。副本池 以全量复制保证最低延迟和最强一致性,适合 RBD 块存储和元数据池;纠删码池 以 Reed-Solomon 编码换取最高存储效率,适合对象存储数据池和归档场景。在 Ceph Squid v19 生产环境中,典型的部署模式是:副本池承载热数据和元数据,EC 池承载温冷数据和对象存储。选择时需要综合考量存储成本、性能需求、故障域规模和运维复杂度,切忌盲目追求存储效率而忽略延迟和覆盖写场景的适用性。

九、下期预告

明天我们将进入 第 10 天:Ceph 块存储 RBD 配置与生产实践。RBD(RADOS Block Device)是 Ceph 最常用的存储接口之一,广泛用于虚拟机磁盘、容器持久卷和数据库存储。我们将深入 RBD 的分层快照、镜像克隆、QoS 限速等高级特性,并完成一个完整的 RBD 生产部署流程。

十、系列目录

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

昵称

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

    暂无评论内容