- 存储
- 分布式文件系统
- 对象存储
- 后端
- 高可用
【免费下载链接】ceph
Ceph is a distributed object, block, and file storage platform
本指南系统讲解 Ceph 的pg-upmap机制:它通过在 OSDMap 中维护一张"PG → OSD"的显式映射异常表,允许集群把特定 PG 精确放置到特定 OSD 上,从而在大多数场景下把 PG 均匀分布到各 OSD,解决 CRUSH 算法天然存在的分布偏差。文章既覆盖在线(ceph-mgrbalancer 模块)与离线(osdmaptool)两种优化路径的完整操作步骤,也结合仓库源码(osdmaptool.cc、OSDMonitor.cc、balancer/module.py)剖析其实现原理与参数默认值。读完本文,你将掌握启用 pg-upmap 的前置条件、两种平衡策略的完整命令流程,以及如何自定义、调优和排查 upmap 条目。
pg-upmap 是什么:CRUSH 分布偏差的"修正带"
Ceph 默认依靠 CRUSH 算法把 PG 映射到 OSD。CRUSH 基于哈希和权重计算,本身无法感知 OSD 上已有的 PG 数量,因此即便 OSD 权重完全相同,各 OSD 上的 PG 数也会有明显偏差——数据分布不够均匀,某些 OSD 负载偏高。
在 Luminous v12.2.z 及之后的版本中,OSDMap 增加了一张pg-upmap 异常表(exception table)。这张表允许集群把特定的 PG 显式映射到特定的 OSD,绕过 CRUSH 的计算结果,从而"精修"数据分布,在大多数情况下让 PG 在 OSD 之间均匀分布。它在 OSDMap 中是独立于 CRUSH 映射规则之外的一层覆盖(override),优先级高于 CRUSH 的自动计算结果。
使用该特性有一个重要前提(caveat):它要求所有客户端都能理解 OSDMap 中新的 pg-upmap 结构。换句话说,只要集群中还存在不理解该结构的旧客户端,就不能使用 pg-upmap,否则旧客户端会计算出与实际不一致的映射,导致数据不可达。这也是启用该特性前必须先提升require-min-compat-client的原因。
在线优化:启用 pg-upmap 与 balancer 模块
在线优化指由ceph-mgr中的balancer 模块自动完成平衡:它周期性评估各 OSD 的 PG 数分布,计算出最优的 upmap 条目并自动应用。
启用前的准备
第一步:确认没有 pre-Luminous 客户端。
新集群默认启用 balancer 模块并直接使用 pg-upmap;而老集群要使用该特性,必须先把集群的兼容性下限提升到 Luminous:
ceph osd set-require-min-compat-client luminous如果当前仍有 pre-Luminous 的客户端或守护进程连接着 monitor,这条命令会执行失败。此时可以用以下命令查看当前集群中所有客户端与守护进程使用的版本:
ceph features关于set-require-min-compat-client命令的具体行为以及如何选择合适的 release 参数,参见 require-min-compat-client.rst。从源码角度看,balancer 模块在切换到 upmap 模式时也会主动检查这一前提:balancer/module.py 中set_mode会读取 OSDMap 的require_min_compat_client,若低于luminous则直接返回错误并提示先执行ceph osd set-require-min-compat-client luminous。
第二步:按需关闭 balancer。
新集群默认启用 balancer 模块,且默认模式即为upmap(见下文源码证据)。如果你打算使用其他 balancer,或者想手工编写自定义的 pg-upmap 条目,为避免与自动优化冲突,应当先关闭它:
ceph balancer offbalancer 模块的工作方式与关键参数
balancer 模块的完整文档见 balancer.rst。从源码看,它支持五种模式(module.py 中定义的Mode枚举):
| 模式 | 说明 |
|---|---|
none | 不进行任何自动平衡 |
crush-compat | 通过调整 CRUSH weight-set 兼容权重实现平衡(适用于不支持 pg-upmap 的旧客户端) |
upmap | 通过 pg-upmap 条目精确重映射 PG(默认模式,需要 luminous+ 客户端) |
read | 优化 PG 的 primary 分布,改善读性能 |
upmap-read | 同时进行 upmap 与 read 优化 |
模块相关配置项同样定义在源码中(module.py),与本文主题强相关的有:
mode:默认upmap,即新集群默认就通过 pg-upmap 平衡分布;upmap_max_optimizations:默认10,每次优化尝试生成的最大 upmap 条目数;upmap_max_deviation:默认5(最小值1),当某 OSD 的 PG 数与目标值的偏差不超过该值时即视为"完美",不再优化;sleep_interval:默认60秒,模块周期性醒来评估并优化的间隔;pool_ids:为空字符串表示对所有池进行自动平衡,可限制为指定池;min_score:默认0,当评估得分低于该值时不进行优化。
在do_upmap的实现中(module.py)可以看到实际执行逻辑:模块会读取upmap_max_optimizations与upmap_max_deviation两个选项,随机打乱池列表使各池获得均等的优化机会,跳过有 PG 合并(pg_num大于pg_num_target)的池,只统计处于active+clean状态的 PG,然后调用 OSDMap 的calc_pg_upmaps计算出不超过预算条数的调整方案。若分布已完美或找不到进一步优化空间,会返回Unable to find further optimization ... or distribution is already perfect。这也印证了文档中"如果找不到任何可做的调整(即池分布已经完美),会提前停止"的描述。
离线优化:用 osdmaptool 手工计算并应用 upmap
离线优化是把优化计算从集群中剥离出来、在本地手工完成的方式。内置优化器位于osdmaptool工具中(实现见 osdmaptool.cc)。完整流程分为三步:
第 1 步:抓取最新的 osdmap
ceph osd getmap -o om这会从 monitor 拉取当前最新的 OSDMap,并保存到本地文件om,作为后续优化的输入。
第 2 步:运行离线优化器
osdmaptool om --upmap out.txt [--upmap-pool <pool>] \ [--upmap-max <max-optimizations>] \ [--upmap-deviation <max-deviation>] \ [--upmap-active]各参数说明如下:
| 参数 | 含义 | 默认值 |
|---|---|---|
--upmap <file> | 计算用于平衡 PG 布局的 upmap 条目并写入指定文件 | 输出文件必需 |
--upmap-pool <poolname> | 将 upmap 平衡限制在指定的一个或多个池(可多次指定) | 所有池 |
--upmap-max <max-count> | 最多识别/生成的 upmap 条目数 | 10 |
--upmap-deviation <max-deviation> | 某 OSD 的 PG 数与目标值偏差不超过该值即视为完美 | 5 |
--upmap-active | 模拟 active balancer 在 upmap 模式下的行为,持续循环直至 OSD 平衡,并报告轮数与每轮耗时 | 关闭 |
以上默认值(upmap_max = 10、upmap_deviation = 5)均可在 osdmaptool.cc 的变量初始化处得到源码级印证,与 balancer 模块的默认值保持一致。
关于池选择的建议:文档强烈建议为每个池单独做优化,或为一组"利用率相似"的池做优化。所谓"利用率相似的池",是指映射到相同设备、存储同类数据的池。例如:RBD 镜像池之间可以视为相似;而 RGW 的 index 池与 data 池不能视为相似(它们承载的数据类型与访问模式差异很大,混在一起优化效果不佳)。可以多次指定--upmap-pool来覆盖多个池。
关于--upmap-max:该值决定最多识别多少条 upmap 条目。默认10(与ceph-mgrbalancer 模块一致),但做离线优化时应使用更大的值,因为离线场景没有在线模块每轮 10 条的限制压力。如果池分布已经完美、找不到任何可做的调整,优化器会提前停止。
关于--upmap-deviation:默认5。只要某 OSD 的 PG 数与计算出的目标值偏差不超过该值,就认为该 OSD"完美",不再为其生成调整条目。调小它可获得更严格的均衡,但会显著增加优化器的工作量。
关于--upmap-active:它模拟 active balancer 在 upmap 模式下的运行行为:持续循环执行优化,直到所有 OSD 都平衡为止,并报告一共进行了多少轮、每轮耗时多少。每轮的耗时直接反映了ceph-mgr在计算下一轮优化计划时消耗的 CPU 负载——如果你关心在线模块对 CPU 的占用,可以用这个参数在离线环境中提前评估。
第 3 步:应用变更
source out.txtout.txt中写入的并非晦涩的内部格式,而是一系列普通的 Ceph CLI 命令,逐条执行即可把优化结果应用到集群。从 osdmaptool.cc 的print_inc_upmaps实现可以看到,生成的命令形如:
ceph osd pg-upmap <pgid> <osd> [<osd> ...] # 新增 upmap 映射 ceph osd rm-pg-upmap <pgid> # 删除 upmap 映射 ceph osd pg-upmap-items <pgid> <from> <to> ... # 使用 swap/替换语义调整映射 ceph osd rm-pg-upmap-items <pgid>因此source out.txt本质上等价于手工顺序执行这些ceph osd pg-upmap*命令。若配合--vstart参数,输出命令会带./bin/前缀,便于在 vstart 开发集群中直接执行。
重复迭代与调试
以上三步可以按需反复执行,直到每组池的 PG 分布达到完美(每个 OSD 的 PG 数与目标值的偏差都在--upmap-deviation范围内)。
如果希望了解优化器内部在做什么,可以给osdmaptool传调试参数:
osdmaptool om --upmap out.txt --debug-osd 10想看到更详细的细节,可以进一步开启 CRUSH 调试:
osdmaptool om --upmap out.txt --debug-crush 10源码视角:pg-upmap 的底层命令与限制
OSDMonitor 中的命令实现
pg-upmap 的增删改查在 monitor 侧由 OSDMonitor.cc 实现。从源码看,monitor 支持以下命令族(OSDMonitor.cc):
osd pg-upmap <pgid> <osd> .../osd rm-pg-upmap <pgid>:设置/移除 PG 的完整 upmap 映射;osd pg-upmap-items <pgid> <from> <to> .../osd rm-pg-upmap-items <pgid>:设置/移除"条目级"的增量替换映射,可同时指定多组 from→to 对;osd pg-upmap-primary <pgid> <osd>/osd rm-pg-upmap-primary <pgid>/osd rm-pg-upmap-primary-all:设置/移除 PG 的 primary OSD 映射(用于读平衡)。
这些命令在执行时会做完整性校验,例如检查pg-upmap条目引用的 OSD 是否在 OSDMap 中存在、是否重复、是否与挂起中的变更冲突等(见 OSDMonitor.cc)。特别值得注意的是:pg-upmap-primary仅支持副本池(replicated pools),若对纠删码池执行会直接报错(OSDMonitor.cc)。
此外,monitor 后台还会持续清理不合适的 pg-upmap / pg-upmap-items 条目:当 PG 数发生变化或 OSD 拓扑调整后,部分 upmap 条目可能失效,monitor 会按mon_clean_pg_upmaps_per_chunk配置分批清理(OSDMonitor.cc),避免异常表无限膨胀。
手工管理 upmap 条目的注意事项
如果你选择关闭 balancer 并完全手工管理 upmap:
- 务必保证客户端兼容性:再次强调,集群所有客户端必须支持 pg-upmap(Luminous+),否则不能使用。
- 条目要"落地":
ceph osd pg-upmap系列命令会被持久化到 OSDMap 中并随之传播,移除时使用对应的rm-pg-upmap*命令即可。 - 关注 monitor 的自动清理:当池的
pg_num缩减或 OSD 被移除后,旧 upmap 条目可能指向不存在的 OSD 或与目标分布冲突,monitor 会自动清理,但这意味着你手工维护的条目也可能被回收,需要定期复核balancer status与 PG 分布状态。
其他相关工具能力
除了--upmap之外,osdmaptool 还提供--upmap-cleanup <file>(清理冗余的 pg_upmap / pg_upmap_items 条目并输出对应命令)和--read <file>(计算用于平衡 primary 分布的条目,对应pg-upmap-primary),它们与 upmap 体系一脉相承,可配合使用。完整参数清单见 osdmaptool.cc。
总结:何时用在线、何时用离线
- 在线优化(balancer 模块):适合常规运维场景。新集群默认开启且模式为
upmap,模块每 60 秒评估一次,每轮最多生成 10 条 upmap 调整,持续渐进式地把分布推向均衡。它的计算在ceph-mgr内完成,无需人工干预,缺点是一轮调整量受upmap_max_optimizations限制,收敛到完美分布需要多轮。 - 离线优化(osdmaptool):适合需要"一步到位"或需要精细控制池选择、偏差阈值的场景。通过
--upmap-max放宽条目数量上限、按池分组优化,可以一次性产出近乎完美的分布方案;--upmap-active还可以帮你预估在线模块的 CPU 开销。 - 两者共用同一套底层机制:无论在线还是离线,最终都是写入 OSDMap 的 pg-upmap 异常表,生成的都是
ceph osd pg-upmap*命令,并且都要求集群客户端为 Luminous 及以上版本。
如果只记住三件事:先ceph osd set-require-min-compat-client luminous提升兼容性下限;再决定是信任默认的 balancer 模块还是ceph balancer off后手工管理;最后无论是自动还是手动,所有调整都通过 OSDMap 中的 pg-upmap 异常表生效,可用ceph osd getmap+osdmaptool随时离线模拟和验证。
- 存储
- 分布式文件系统
- 对象存储
- 后端
- 高可用
【免费下载链接】ceph
Ceph is a distributed object, block, and file storage platform
相关推荐
Predis集群负载均衡:Distributor实现请求均匀分布
Predis集群负载均衡:Distributor实现请求均匀分布 在Redis集群应用中,请求的均匀分布直接影响系统性能和稳定性。Predis作为PHP生态中灵
数据库后端Ceph 集群平衡设计解析:容量平衡(Upmap)与读平衡(Read Balancer)的机制与实战
Ceph 集群平衡设计解析:容量平衡(Upmap)与读平衡(Read Balancer)的机制与实战 在分布式存储系统 Ceph 中,请求的均衡分布直接决定了集
存储分布式文件系统对象存储后端高可用Rook Ceph 集群配置实战:从 PG/PGP 规划到 ceph.conf 高级覆盖
Rook Ceph 集群配置实战:从 PG/PGP 规划到 ceph.conf 高级覆盖 导读 本文基于 Rook 官方文档 Documentation/Sto
云原生存储容器编排运维
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考