【Ceph RADOS】CRUSH 加深:rule/bucket/weight 机制与失败域语义

💡 原文中文,约8100字,阅读约需20分钟。
📝

内容提要

本文深入解析Ceph CRUSH机制细节:bucket类型影响迁移量,straw2最优;rule的step语法控制失败域,firstn用于副本、indep用于EC;weight三层体系(device weight、OSD reweight、primary_affinity)不可混用;CRUSH与一致性哈希根本差异在于显式失败域约束和中心化map传播。upmap作为二次修正,需权衡迁移字节与peering风暴。

🔎

延伸解读

bucket 类型是迁移量的第一检查项

扩容时迁移量远超理论下界,往往不是 straw2 随机性问题,而是 bucket 仍为 straw1 等旧算法。straw2 接近最优迁移量,straw1 可能显著超量。排障时应先确认 bucket alg,再考虑 upmap 或恢复限速,避免在错误的轴上用力。

失败域由 type 决定,而非 bucket 名字

CRUSH 的失败域由 chooseleaf 的 type 参数决定,如 type rack。若拓扑中多个 OSD 挂在同一 host bucket 下,即使 rule 指定 host 域,实际仍可能共命运。改名无效,需调整树结构或 type。排障时若 acting 出现同 rack 多 OSD,先怀疑树建模,而非随机性。

三层权重不可混用

device weight 影响 CRUSH 选择概率,OSD reweight 在结果后缩放,primary_affinity 仅影响 Primary 选取。想少写某盘却只改 affinity,它仍可能做副本;想避免 Primary 却只改 device weight,Primary 仍可能落在其上。三者作用点不同,需按需调整。

CRUSH 与一致性哈希的本质差异

CRUSH 通过 rule 显式编码失败域,而一致性哈希依赖虚拟节点隐式满足。CRUSH 的“去中心化”仅指放置计算本地化,map 仍由 MON 中心广播。每次树或 rule 变更都会抬升 epoch,触发 peering,因此优化放置需权衡 epoch 稳定性。

Q&A

Ceph CRUSH中bucket类型对数据迁移量有什么影响?

bucket类型影响数据迁移量,straw2接近最优迁移量,而straw1、list、uniform等类型可能导致超量迁移。新建bucket默认使用straw2,老集群可能仍为straw1,迁移量异常时应先检查bucket alg。

CRUSH rule中firstn和indep有什么区别?分别适用于什么场景?

firstn用于副本池,有序选取,尽量填满n个,失败时重试;indep用于EC池,位置稳定,某OSD缺失时其他位置编号不变,避免整条带重映射。

Ceph中device weight、OSD reweight和primary_affinity有什么区别?

device weight存在CRUSH device项,影响straw2选择概率和长期容量均衡;OSD reweight存在OSDMap,在CRUSH结果后做缩放,适合临时引流;primary_affinity影响Primary选取,可让读写序列化点靠近客户端。三者存储位置和作用点不同,不可混用。

CRUSH与一致性哈希的根本差异是什么?

CRUSH通过层级bucket树和rule显式编码失败域约束,而一致性哈希多靠虚拟节点隐式满足;CRUSH的放置计算是本地化的,但map仍由MON中心广播,一致性哈希的环状态是分布式的。

如何计算CRUSH迁移量的理论下界?

理论最小迁移份额M_min = (ΔW / W_total) × P_total,其中ΔW为权重变化,P_total为PG×副本(或EC分片)规模。straw2接近该下界,其他算法可能显著超过。

upmap在Ceph中起什么作用?有什么副作用?

upmap是Balancer在CRUSH输出上打的补丁,用于进一步压平利用率,但会使PG放置变成两层故事,增加排障复杂度,并可能增加epoch碎片和peering风暴。需要在迁移字节和peering风暴之间权衡。

CRUSH rule中take和chooseleaf的class和type分别控制什么?

take中的class用于设备类过滤,如hdd/ssd/nvme,解决混闪盘池问题;chooseleaf中的type指定失败域,如rack,确保每个结果叶子来自不同的type祖先。两者正交,缺一不可。

为什么说CRUSH的失败域是type而不是bucket名字?

因为chooseleaf的type参数指定了失败域,如type rack,它要求每个结果叶子来自不同的rack祖先,而不是根据bucket名字。如果拓扑中多个OSD挂在同一host bucket下,即使rule写type host,实际仍可能共命运。

🏷️

标签

➡️

继续阅读