有 1 个 pool 的 PG 数不是 2 的幂(例如 300、500 这种),在 Ceph 中 不推荐,可能导致分布不均。
通过以下命令查看:
ceph osd pool ls detail | grep pg_num
PG 推荐值:
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 的幂。
Ceph 用 CRUSH + 哈希把对象分配到 PG。
过程简化如下:
object -> hash -> % pg_num -> pg_id
注意关键:
% pg_num(取模操作)决定对象落在哪个 PG% 操作相当于 取哈希的低 n 位(二进制)例:
pg_num = 256 = 2^8
=> object_hash % 256 = 取 hash 的最低 8 位
这样可以做到:
因为哈希空间天然在二进制上是均匀的。
例如:
pg_num = 300
哈希空间不能平均分成 300 份:
举例:
hash % 300
哈希空间范围:0 ~ 2^32-1
而 2^32 除以 300 会留下余数:
2^32 % 300 ≠ 0
这意味着:
最终导致:OSD 空间、IO、PG 数量都不平衡。
CRUSH 的目标是:
但 CRUSH 的前提是:
PG 自己必须是均匀的。
如果 PG 数内部已经倾斜(因为不是 2 的幂),那么:
尤其OSD 数少时(比如你只有 6 个 OSD)这个不均匀放大特别明显。
假设:
1024 / 10 = 102 余 4
所以:
看似差不大,但 Ceph 一个 PG 可能对应几十 GB 数据。
这个小差异会导致 OSD 最终负载明显不同。
如果使用:
pg_num = 8 (2^3)
则:
1024 / 8 = 128(整除)
每个 PG 完全一样 → 完美均匀。
官方统计表明:
所以直接在 health 警告里要求修复。
历史原因 + 某些算法可以容忍,但最终都建议:
powers of 2
尤其你这种 6 OSD 的小集群,影响更大。
PG 是从哈希空间切分出来的,而哈希空间天然是 2^n 的二进制结构。
用 2 的幂作为 PG 数可以完美等分哈希空间,数据分布才会均匀。
如果 PG 不为 2 的幂,则哈希空间无法整除,PG 分布必然不均匀,导致 OSD 空间、IO 倾斜。
谢谢大佬,解决了我的问题!
kubectl get --raw /api/v1/nodes/k8s-node1/proxy/stats/summary | jq '.pods[] | "PodName: ", .podRef.name, "usedBytes:", .containers[].rootfs.usedBytes, "Logs:", .containers[].logs.usedBytes, "Volume:", .volume[].usedBytes'
列出在给定节点中运行的 pods 磁盘使用情况:
kubectl get --raw /api/v1/nodes/
/proxy/stats/summary | jq '.pods[0] | "PodName: ", .podRef.name, "usedBytes: ", .containers[].rootfs.usedBytes'
获取节点文件系统使用情况
kubectl get --raw /api/v1/nodes/<NODE_NAME>/proxy/stats/summary | jq '.node.fs.usedBytes'
获取节点 imageFs 使用情况
kubectl get --raw /api/v1/nodes/<NODE_NAME>/proxy/stats/summary | jq '.node.runtime.imageFs.usedBytes'
获取节点 iNodes 统计信息
kubectl get --raw /api/v1/nodes/<NODE_NAME>/proxy/stats/summary | jq '.node.fs.inodesFree'
kubectl get --raw /api/v1/nodes/<NODE_NAME>/proxy/stats/summary | jq '.node.runtime.imageFs.inodesFree'