我进行日常的ceph健康检查的时候,发现报non-power-of-two pg_num警告,如下:
# ceph -s
cluster:
id: 52eabf04-b7ba-11ef-8287-bba5b8705822
health: HEALTH_WARN
1 pool(s) have non-power-of-two pg_num
services:
mon: 1 daemons, quorum ww209 (age 4M)
mgr: ww209.jkkdaw(active, since 8w), standbys: ww209.bduyjm
mds: 1/1 daemons up
osd: 6 osds: 6 up (since 8w), 6 in (since 8w)
rgw: 2 daemons active (1 hosts, 1 zones)
data:
volumes: 1/1 healthy
pools: 16 pools, 182 pgs
objects: 27.43k objects, 117 GiB
usage: 118 GiB used, 13 TiB / 13 TiB avail
pgs: 182 active+clean
请问我该怎么解决?

有 1 个 pool 的 PG 数不是 2 的幂(例如 300、500 这种),在 Ceph 中 不推荐,可能导致分布不均。
通过以下命令查看:
ceph osd pool ls detail | grep pg_numPG 推荐值:
power-of-two修复:
ceph osd pool set <poolname> pg_num 256 ceph osd pool set <poolname> pgp_num 256详细解释
PG 到 OSD 的映射是通过哈希(hash)和一致性映射计算出来的,Ceph 对 PG 的编号是按位(二进制位)运算优化的。如果 PG 数不是 2 的幂,PG 的哈希空间无法平均划分,从而导致某些 PG 映射到更多 OSD,某些更少,引起数据倾斜(PG 不均衡)。
为什么要 2 的幂?
因为 二进制世界里最容易等分的就是 2 的幂。
1)PG 映射本质是取哈希值的前几位
Ceph 用 CRUSH + 哈希把对象分配到 PG。
过程简化如下:
object -> hash -> % pg_num -> pg_id注意关键:
% pg_num(取模操作)决定对象落在哪个 PG%操作相当于 取哈希的低 n 位(二进制)例:
pg_num = 256 = 2^8 => object_hash % 256 = 取 hash 的最低 8 位这样可以做到:
因为哈希空间天然在二进制上是均匀的。
2)如果 pg_num 不是 2 的幂,就不能整齐切分哈希空间
例如:
pg_num = 300哈希空间不能平均分成 300 份:
举例:
hash % 300哈希空间范围:0 ~ 2^32-1
而 2^32 除以 300 会留下余数:
2^32 % 300 ≠ 0这意味着:
最终导致:OSD 空间、IO、PG 数量都不平衡。
3)CRUSH 映射也因为 PG 分布不均而无法完全平衡
CRUSH 的目标是:
但 CRUSH 的前提是:
PG 自己必须是均匀的。
如果 PG 数内部已经倾斜(因为不是 2 的幂),那么:
尤其OSD 数少时(比如你只有 6 个 OSD)这个不均匀放大特别明显。
4)举个超级直观的例子(最容易理解)
假设:
1024 / 10 = 102 余 4
所以:
看似差不大,但 Ceph 一个 PG 可能对应几十 GB 数据。
这个小差异会导致 OSD 最终负载明显不同。
如果使用:
pg_num = 8 (2^3)则:
每个 PG 完全一样 → 完美均匀。
5)真实案例(Ceph 官方报告)
官方统计表明:
所以直接在 health 警告里要求修复。
6)为什么 Ceph 允许不是 2 的幂?
历史原因 + 某些算法可以容忍,但最终都建议:
powers of 2尤其你这种 6 OSD 的小集群,影响更大。
总结(最简精华)
PG 是从哈希空间切分出来的,而哈希空间天然是 2^n 的二进制结构。
用 2 的幂作为 PG 数可以完美等分哈希空间,数据分布才会均匀。
如果 PG 不为 2 的幂,则哈希空间无法整除,PG 分布必然不均匀,导致 OSD 空间、IO 倾斜。
你的答案