第 17/20 天
在 Ceph 生产环境的生命周期中,集群扩容是最常见的运维操作之一。随着业务数据量持续增长,初始规划的存储容量终将面临瓶颈,需要通过动态添加 OSD 节点来扩展存储空间。然而,扩容并非简单地把磁盘加进去——OSD 的加入会触发 CRUSH Map 的重新计算,导致大量 PG(Placement Group)在 OSD 之间迁移重平衡。如果不加以控制,重平衡产生的数据迁移流量可能挤占正常业务 I/O,造成客户端延迟飙升甚至服务降级。本篇将深入讲解 Ceph 集群扩容的架构原理、完整实战步骤、参数调优方法以及生产环境踩坑经验。
一、架构与原理:CRUSH 重平衡机制
1.1 OSD 添加对 CRUSH Map 的影响
Ceph 的数据分布依赖于 CRUSH(Controlled Replication Under Scalable Hashing)算法。CRUSH Map 定义了集群的层次化拓扑结构(Root → Row → Rack → Host → OSD),每个 OSD 都有权重值(weight),CRUSH 根据权重将 PG 映射到对应的 OSD 上。
当新 OSD 加入集群时,CRUSH Map 会自动更新该 OSD 所在层级的总权重。由于 CRUSH 算法是确定性哈希,权重变化会导致部分 PG 的映射结果发生偏移,这些 PG 需要从源 OSD 迁移到新 OSD 上——这就是 重平衡(Rebalancing) 过程。

1.2 重平衡的数据流向
扩容时的数据迁移涉及以下状态机转换:
| PG 状态 | 含义 | 说明 |
|---|---|---|
creating |
PG 正在创建 | 新 PG 初始化阶段 |
activating |
激活中 | PG 即将进入活跃状态 |
backfilling |
全量回填 | 新 OSD 需要完整副本数据 |
backfill_wait |
等待回填 | 排队中的回填任务 |
recovering |
增量恢复 | 基于日志的差量同步 |
recover_wait |
等待恢复 | 排队中的恢复任务 |
active+clean |
正常状态 | 迁移完成 |
Backfill 是最重的操作——它将 PG 的完整数据复制到新 OSD 上,产生大量磁盘读和网络传输。Recovery 则是基于 PG Log 的增量同步,数据量较小但仍会消耗 I/O。
1.3 CRUSH 权重模型
每个 OSD 有两个关键权重参数:
weight(crush weight):基于磁盘实际容量计算,决定数据分布比例。一个 4TB 磁盘的 weight ≈ 4.0。reweight(reweight):运维手动调整的负载权重,用于临时平衡不均匀的 OSD。范围 0.0~1.0,默认 1.0。
扩容时,新 OSD 的 crush weight 由 BlueStore 自动根据磁盘容量设置,但可以通过手动调整来控制数据流入速度。
1.4 扩容策略设计考量
在生产环境中,扩容策略需要考虑以下维度:
- 批量 vs 逐台添加:一次性加入大量 OSD 会引发峰值迁移流量;逐台添加更安全但耗时长。
- 故障域完整性:新节点必须纳入正确的 CRUSH 故障域(rack/row),避免副本集中。
- 重平衡节奏控制:通过
osd_max_backfills、osd_recovery_max_active等参数限制并发度。 - 业务窗口选择:在低峰期执行扩容,减少对前端 I/O 的影响。
二、部署实战:OSD 动态添加与重平衡
2.1 环境准备
假设当前集群有 3 台 OSD 节点(osd-host-01/02/03),每节点 2 块 OSD,共 6 个 OSD。现在需要扩容到 4 台节点,新增 osd-host-04,配备 2 块 NVMe SSD。
# 查看当前集群状态
ceph -s
# 查看现有 OSD 树拓扑
ceph osd tree
# 确认新节点已加入集群并安装基础软件
# 新节点 osd-host-04 已通过 cephadm 加入集群(参考第 3 天 cephadm 引导)
ceph orch host ls
2.2 新节点纳入 CRUSH 拓扑
新 OSD 节点加入前,需要先在 CRUSH Map 中规划好其所属的故障域。假设集群使用 rack 级别作为副本隔离域,新节点位于 rack-04。
# 创建 CRUSH rack bucket(如果尚未存在)
ceph osd crush add-bucket rack-04 rack
# 将 rack-04 挂载到默认 root 下
ceph osd crush move rack-04 root=default
# 在 rack-04 下创建 host bucket
ceph osd crush add-bucket osd-host-04 host
# 将 osd-host-04 移入 rack-04
ceph osd crush move osd-host-04 rack=rack-04
# 验证 CRUSH 拓扑结构
ceph osd tree
执行后 CRUSH 树应显示 rack-04/osd-host-04 节点,此时尚无 OSD 挂入。
2.3 添加新 OSD
使用 cephadm 自动发现并添加 OSD。Cephadm 会扫描节点上的可用裸盘,自动创建 BlueStore OSD 并纳入 CRUSH Map。
# 方式一:cephadm 自动发现并添加所有可用磁盘
ceph orch daemon add osd osd-host-04:
# 方式二:指定具体磁盘路径(更精确)
ceph orch daemon add osd osd-host-04:/dev/nvme0n1
ceph orch daemon add osd osd-host-04:/dev/nvme1n1
# 查看 OSD 添加进度
ceph orch daemon status
# 确认新 OSD 已加入并处于 up 状态
ceph osd tree
新 OSD 加入后,Ceph 会自动为其设置 crush weight(基于磁盘容量),并立即开始 backfill 过程。
2.4 控制重平衡速率
扩容触发的重平衡是 I/O 密集型操作。在生产环境中,必须限制并发度以保护正常业务。以下参数可在运行时动态调整:
# 限制每个 OSD 的最大 backfill 并发数(默认 1,生产建议 1-2)
ceph tell osd.* injectargs '–osd_max_backfills=2'
ceph tell osd.* injectargs '–osd_recovery_max_backfills=2'
# 限制恢复操作的最大并发活跃数(默认 3,扩容时可提升至 5-6)
ceph tell osd.* injectargs '–osd_recovery_max_active=5'
# 调整恢复操作的 I/O 优先级(默认 recovery_op_priority=3,客户端=63)
# 值越大优先级越高,扩容时保持低优先级让客户端 I/O 优先
ceph tell osd.* injectargs '–osd_recovery_op_priority=3'
# 设置恢复睡眠时间(微秒),增加延迟以降低 I/O 占用
ceph tell osd.* injectargs '–osd_recovery_sleep=0.2'
# 查看当前 PG 迁移进度
ceph -w
ceph pg dump pgs_brief | grep -E 'backfill|recover'
2.5 CRUSH 权重微调
如果新 OSD 数据流入过快导致前端延迟波动,可以临时降低其 crush weight,让数据以更平滑的速度迁入:
# 查看所有 OSD 的当前权重
ceph osd tree | grep -E 'osd.|weight'
# 临时降低新 OSD 的 reweight(从默认 1.0 降到 0.5)
ceph osd reweight osd.6 0.5
ceph osd reweight osd.7 0.5
# 使用 reweight-by-utilization 自动平衡(基于 PG 分布)
ceph osd reweight-by-utilization
# 使用 test-reweight-by-utilization 先预览(不实际修改)
ceph osd test-reweight-by-utilization
# 重平衡完成后恢复 reweight 到 1.0
ceph osd reweight osd.6 1.0
ceph osd reweight osd.7 1.0
2.6 监控重平衡进度
# 实时监控集群整体状态和 PG 迁移
ceph -w
# 查看 PG 分布均匀度
ceph pg dump pgs_brief | awk '{print $2}' | sort | uniq -c | sort -rn
# 查看每个 OSD 的 PG 数量
ceph osd df | head -20
# 查看恢复进度统计
ceph df
# 查看具体某个 PG 的状态详情
ceph pg ls | grep backfill
ceph pg ls | grep recover
2.7 扩容后集群验证
重平衡完成后(所有 PG 回到 active+clean),执行完整验证:
# 集群健康状态应为 HEALTH_OK
ceph health detail
# 确认所有 PG 均为 active+clean
ceph pg stat
# 验证 OSD 权重分布均匀
ceph osd df tree
# 检查集群总容量已增长
ceph df
# 运行 RBD 性能基准测试验证新节点正常工作
rbd bench-write test-pool/test-image –io-size 4M –io-total 1G –io-threads 4
三、配置参数详解
3.1 重平衡核心参数
| 参数 | 默认值 | 生产建议 | 说明 |
|---|---|---|---|
osd_max_backfills |
1 | 1-2 | 单个 OSD 同时接受的 backfill 数 |
osd_recovery_max_backfills |
1 | 2-3 | 单个 OSD 同时发起的 backfill 数 |
osd_recovery_max_active |
3 | 5-6 | 每个 OSD 的活跃恢复请求数 |
osd_recovery_op_priority |
3 | 3 | 恢复操作优先级(客户端=63) |
osd_recovery_sleep |
0 | 0.1-0.5 | 恢复操作间隔睡眠时间(秒) |
osd_recovery_max_chunk |
8MB | 8-16MB | 单次恢复数据块大小 |
osd_backfill_full_ratio |
0.85 | 0.85 | OSD 使用率超过此值时拒绝 backfill |
3.2 持久化配置
通过 injectargs 修改的参数是临时的(OSD 重启后失效),生产环境需要写入配置文件持久化:
# ceph.conf 或 cephadm 配置覆盖
# 使用 ceph config set 持久化(推荐)
# 语法:ceph config set <class> <parameter> <value>
ceph config set osd osd_max_backfills 2
ceph config set osd osd_recovery_max_active 5
ceph config set osd osd_recovery_sleep 0.2
# 验证配置已持久化
ceph config dump | grep -E 'max_backfill|max_active|recovery_sleep'
# 查看特定 OSD 的生效配置
ceph config dump | grep osd.6
四、生产环境注意事项与踩坑提示
4.1 分批次添加 OSD
生产环境切忌一次性添加大量 OSD。假设集群有 30 个 OSD,一次性加入 10 个会导致近 25% 的 PG 需要迁移,产生巨大的网络和磁盘 I/O 压力。
推荐做法:每次添加 1-2 个 OSD,等待重平衡完成(active+clean)后再添加下一批。使用脚本自动化批次添加:
#!/bin/bash
# batch_add_osd.sh — 分批添加 OSD 脚本
HOST="osd-host-04"
DISKS=("/dev/nvme0n1" "/dev/nvme1n1")
for disk in "${DISKS[@]}"; do
echo ">>> Adding OSD: $HOST:$disk"
ceph orch daemon add osd "$HOST:$disk"
echo ">>> Waiting for backfill to complete…"
while true; do
status=$(ceph health | head -1)
if [[ "$status" == "HEALTH_OK" ]]; then
echo ">>> Cluster healthy, proceeding to next OSD"
break
fi
echo ">>> Current status: $status, waiting 60s…"
sleep 60
done
done
echo ">>> All OSDs added successfully"
4.2 CRUSH 故障域验证
新 OSD 必须正确归属到预期的故障域中。如果 rack 信息错误,可能导致同一副本的多个 PG 落在同一 rack 上,丧失容灾能力。
# 验证某个 PG 的副本分布在不同的 rack/host
ceph pg map 1.0
# 输出应显示 osd 位于不同 host 或 rack
# 使用 crushtool 检查 CRUSH 映射规则
ceph osd getcrushmap -o /tmp/crushmap.bin
crushtool -d /tmp/crushmap.bin -o /tmp/crushmap.txt
# 检查 /tmp/crushmap.txt 中的 ruleset 确保选择策略正确
4.3 踩坑:reweight 忘记恢复
使用 ceph osd reweight 临时降低新 OSD 权重后,必须在重平衡完成后恢复到 1.0。否则该 OSD 长期处于低权重状态,导致数据分布不均,其他 OSD 提前达到 full ratio。
检查方法:
# 查看是否有 OSD 的 reweight 不为 1.0
ceph osd tree | awk '$1 ~ /osd./ {print $0}'
# 确认所有 OSD 的 REWEIGHT 列均为 1.00000
4.4 踩坑:full ratio 与扩容冲突
如果集群在接近 osd_full_ratio(默认 0.85)时才扩容,新 OSD 加入后 backfill 操作需要从满载 OSD 读取数据,但满载 OSD 可能因 osd_backfill_full_ratio(默认 0.85)拒绝 backfill 请求,导致迁移卡住。
解决方案:
# 临时提高 backfill full ratio
ceph tell osd.* injectargs '–osd_backfill_full_ratio=0.90'
ceph tell osd.* injectargs '–osd_failsafe_full_ratio=0.97'
# 扩容完成后恢复默认值
ceph tell osd.* injectargs '–osd_backfill_full_ratio=0.85'
ceph tell osd.* injectargs '–osd_failsafe_full_ratio=0.95'
最佳实践:集群使用率达到 70% 时就应启动扩容,不要等到 85%+ 才行动。
4.5 网络带宽控制
扩容时 backfill 流量走集群网络(cluster network)。如果集群网络带宽有限(如 10Gbps),大量并发 backfill 可能打满网络带宽。建议在低峰期执行扩容,或通过 osd_recovery_sleep 增加延迟来降低网络压力。
# 监控集群网络带宽(在 OSD 节点上执行)
iftop -i <cluster_nic>
# 或使用 sar 监控
sar -n DEV 5 | grep <cluster_nic>
五、常见问题
Q1: 新 OSD 加入后一直是 down 状态,怎么办?
A: 首先检查新节点的磁盘是否为裸盘(无分区、无文件系统)。BlueStore 要求独占整块裸盘。如果磁盘已有分区表,需要先清除:
# 在新节点上检查磁盘
lsblk -f
# 如果磁盘有分区,用 wipefs 清除(注意确认磁盘正确!)
wipefs -a /dev/nvme0n1
sgdisk –zap-all /dev/nvme0n1
# 重新添加
ceph orch daemon add osd osd-host-04:/dev/nvme0n1
同时检查 cephadm 是否能 SSH 到新节点:ceph orch host ls 确认节点状态。
Q2: 重平衡进度很慢,正常吗?
A: 重平衡速度取决于磁盘性能和网络带宽。HDD OSD 的 backfill 速度通常为 20-50MB/s,NVMe SSD 可达 200-500MB/s。如果感觉异常慢,检查以下几点:
osd_max_backfills和osd_recovery_max_active是否被设置过低- 集群网络带宽是否被打满
- OSD 磁盘是否有其他高 I/O 负载(如同时在进行 scrub)
- 暂停 scrub 操作:
ceph osd set noscrub; ceph osd set nodeep-scrub,重平衡完成后再解除
Q3: 扩容后 PG 分布不均匀,部分 OSD 的 PG 数明显偏多怎么办?
A: 使用 ceph osd reweight-by-utilization 命令自动根据 PG 分布和磁盘使用率重新调整 OSD 的 reweight。该命令会自动降低过载 OSD 的权重、提高轻载 OSD 的权重。可以多次执行直到分布均匀。如果仍然不均,检查 CRUSH Map 的权重是否与实际磁盘容量匹配。
六、总结
本篇深入讲解了 Ceph 集群扩容的全流程:从 CRUSH 重平衡的架构原理到 OSD 动态添加的完整实战操作,再到重平衡速率控制和权重微调。核心要点回顾:
- 理解 CRUSH 机制:扩容本质是权重变化触发 PG 重新映射,backfill 是最重的迁移操作。
- 分批添加 OSD:每次 1-2 个,等待
active+clean后再加下一批。 - 控制重平衡节奏:通过
osd_max_backfills、osd_recovery_max_active、osd_recovery_sleep限制并发度。 - 及时恢复 reweight:临时降低的权重必须在重平衡完成后恢复为 1.0。
- 提前规划扩容:集群使用率达到 70% 就应启动扩容,不要等到接近 full ratio。
- 验证故障域:新 OSD 必须正确归入 CRUSH 拓扑的对应 rack/host,确保副本隔离。
集群扩容是 Ceph 运维中风险较高的操作,但只要遵循分批添加、控制速率、验证故障域三大原则,就能在业务无感知的前提下平滑完成容量扩展。
下期预告
明天(第 18 天)我们将探讨 「Ceph 高可用与容灾设计:多副本、跨机房与异地灾备」——从单集群高可用到跨数据中心容灾架构的完整设计方案,包括 stretch cluster、多活 RGW、Ceph 的 stretched mode 等企业级容灾技术。
系列目录
- ✅ 第 1 天:Ceph 架构概述与生产环境选型指南
- ✅ 第 2 天:Ubuntu 系统准备:内核调优与磁盘规划
- ✅ 第 3 天:Cephadm 部署工具详解与集群引导初始化
- ✅ 第 4 天:Monitor 节点部署与高可用配置
- ✅ 第 5 天:Manager 节点部署与模块启用
- ✅ 第 6 天:OSD 存储节点部署:BlueStore 配置与磁盘管理
- ✅ 第 7 天:CRUSH Map 架构解析与故障域规划
- ✅ 第 8 天:存储池(Pool)创建与 PG 数量规划
- ✅ 第 9 天:副本与纠删码存储池策略对比实战
- ✅ 第 10 天:Ceph 块存储 RBD 配置与生产实践
- ✅ 第 11 天:Ceph 对象存储 RGW 网关部署与 S3 兼容
- ✅ 第 12 天:CephFS 分布式文件系统部署与挂载
- ✅ 第 13 天:Ceph 网络架构:集群网络与公共网络分离
- ✅ 第 14 天:Ceph 认证体系 cephx 与用户权限管理
- ✅ 第 15 天:Ceph 集群监控:Prometheus + Grafana + 内置仪表盘
- ✅ 第 16 天:Ceph 性能调优:OSD 参数与缓存分层
- 📌 第 17 天:Ceph 集群扩容实战:OSD 动态添加与 CRUSH 重平衡(本文)
- 🔜 第 18 天:Ceph 高可用与容灾设计:多副本、跨机房与异地灾备
- 🔜 第 19 天:Ceph 故障排查与数据恢复实战
- 🔜 第 20 天:Ceph 生产环境升级维护与版本迭代策略

















暂无评论内容