首次遥测结果
自 Mimic (13.2.x) 发布以来,Ceph 包含遥测模块。 此(选择加入)组件会将匿名、不可识别的集群指标发送回 Ceph 项目。 这些指标包括例如池配置的高级摘要、节点和 OSD 的数量,以及 Ceph、OS、内核版本、遇到的崩溃以及总集群容量。 更多详细信息请参阅 之前的博客文章。
该模块尚未被广泛启用,并且报告的数据仍在不断发展和完善。 作为存储系统,我们采取谨慎的方法,并高度重视隐私。
为了了解哪些报告对开发人员和整个社区有益,我们根据当前的工单,通过手动探索迈出了第一步。 令人惊喜的是,即使如此,数据也证明了它的用处!
早期发现 ¶
截至 2019 年 7 月撰写本文时,约 320 个集群在其生命周期中的某个时间点向我们的遥测服务报告了其状态。 这些集群总共托管了超过 40 PB 的数据,在超过 10000 个 OSD 上。 鉴于目前启用该模块的集群数量很少,并且其中许多可能是实验室或开发集群,因此现在就根据这些数据得出太多结论还为时过早。
然而,在探索过程中,注意到一个奇怪之处,即使考虑到这些限制,也令人惊讶——一些集群报告其某些池使用pg_num 设置,该设置不是 2 的幂。
虽然分布清楚地显示了对 2 的幂的预期偏差,但略多于 4% 的所有池未遵循此建议。 人们可能会推测,由于遥测需要显式启用,这些用户可能比平均水平更熟悉 Ceph,因此该百分比在整个领域中可能更高。
让我们看看为什么这很重要,以及这种见解触发了哪些操作。
Ceph 中的数据放置 ¶
快速回顾 ¶
最终,存储在 Ceph 集群上的所有数据——无论是通过 RBD、iSCSI、CephFS、Samba、NFS、S3、Swift 还是低级 librados 协议——都被映射到池中的低级 RADOS 对象。 大型实体被切分成许多较小的对象;默认情况下为 4 MiB。 例如,一个 1 TB 的 RBD 将在 RADOS 集群中产生 262144 个 4 兆字节的对象。 由于 4 MiB 与现代存储设备尺寸相比很小,因此粒度相当细。
这些对象标识符被哈希,然后分布到放置组 (PG)。 Ceph 使用 CRUSH 根据规则算法地映射和伪随机地平衡 PG 到 Ceph 对象存储守护程序 (OSD),以确保适当的冗余和容错能力。
平衡数据放置的好处 ¶
相对于其容量,均匀平衡 OSD 上的数据对于两个特定原因非常重要。 首先,也是最重要的一点,这优化了集群可以存储的数据量。 当新数据(确定性地,但伪随机地)被定向到已经满的 OSD 时,它无法写入。 因此,第一个填满的 OSD 是整个集群的瓶颈。(这就是为什么 Ceph 不从 OSD 的平均利用率推断集群中剩余的可用空间,而是从最满的 OSD 推断。)
第二个是每个容量的性能——假设 IO 模式大致均匀,那么 OSD 持有的数据越多,它接收到的 IO 也就越多。 由于 IOPS 和带宽受到存储设备和网络的限制,过度利用意味着某些 IO 会比必要的速度慢,而未充分利用的 OSD 会留下一些性能。
简化:不平衡的集群存储的数据更少,性能更低。
在 OSD 之间平衡 PG ¶
由于 Ceph 使用伪随机算法数据分布,数据放置很少是完美的。 您可能熟悉使用“ceph osd reweight”或“reweight-by-utilization”来调整 OSD 权重,以便 OSD 接收更多或更少的 PG。
自 Luminous 以来,Ceph 包含 均衡器模块,该模块支持自动或辅助处理此问题。 该模块默认在新的 Nautilus 及更高版本的集群中启用。 “crush-compat”模式以前的方式修改权重,但更智能。 新的“upmap”模式添加了 PG 到 OSD 的显式映射作为例外,从而能够完美平衡每个 OSD 的 PG 数量(相对于 OSD 的容量)。
因此,在我们的理想世界中(假设 OSD 大小相同),每个 OSD 现在都分配了相同数量的 PG。
介绍每个池的 PG 数量 ¶
现在我们需要退后两步——从配置池上的 PG 数量开始。 每个 PG 理想情况下将接收相同比例的总数据。 例如,如果pg_num 设置为20,则每个 PG 将持有 5%。
经验法则是在每个 OSD 上定位大约 100 个 PG。 但是,这必须考虑到池的“size”,因为为了处理 Ceph 所需的冗余——复制池的总副本数,或编码池的k+m——会创建影子 PG。
如果假设一个包含 10 个 OSD 的 10 节点集群,并且采用三路复制,并且此 PG/OSD 目标,我们将pg_num 设置为4096。 如果我们想使用具有类似容错能力但空间效率更高的擦除编码,我们可能会选择8+2 作为k+m 值——现在我们的 EC 池的size 为10,我们的目标pg_num 将为1024。 我们已经可以看到,使用 EC,每个 PG 代表总数据的更大比例。(在本例中,是四倍。)
虽然 Ceph 文档已经建议总池 PG 数量应四舍五入到 2 的幂,但并没有强烈建议这样做。 当我们研究用户选择这些值的原因时,我们发现我们的文档的其他部分甚至在示例中使用了它们。 一些用户专注于每个 OSD 的 PG 数量,有时也倾向于降低成本,努力降低 PG 的成本。
现在,我们终于准备好查看问题发生在哪里——对象如何根据其名称映射到 PG。
将对象映射到 PG ¶
对象的名称不直接用于将其映射到 PG。 由于它可以是任何随机字符串,RADOS 会计算对象名称的标准长度 32 位哈希值。 使用此哈希值来确定对象将放置在池中的哪个 PG。 为此,RADOS 应用一个位掩码,该掩码速度非常快——使用最低 n 位来确定对象进入哪个 PG。 但是,至关重要的是,它只能在位边界处进行决策——这就是 2 的幂发挥作用的地方。 进一步简化,这意味着 PG 可以将持有的对象数量加倍或减半。
如果pg_num 不是 2 的幂,将被映射到 PG 的对象将再次映射到前几个 PG。
现在让我们看两个简单的场景:一个包含 1000 个 PG 或 1024 个 PG 的池。
使用 1024 (210) PG,一切都很容易——我们有一个简单的位掩码0b1111111111,可以一致且均匀地应用,从而产生从 0 到 1023 的 PG 编号。
仅使用 1000 个 PG(这是一个非常接近的数字,可能吸引了认为以指标为单位的人),只有前 1000 个 PG 可以通过位掩码直接映射;剩余的“假设”24 个 PG(1000 到 1023)将使用少一个位的掩码(就像池仅配置了 512 个 PG),以确保数字适合pg_num。 这会将它们映射回 PG 488 到 511——这些 24 个 PG 因此会接收两倍的数据。
(快捷方式:给定低于 2 的幂的pg_num,只有一个 PG 会“大”;对于略高于 2 的幂的pg_num,异常 PG 将是半大小的 PG。 如果选择pg_num 恰好位于2n 和2(n+1) 之间,则三分之一的 PG 将被加倍。)
这些异常 PG 无法完美地分布到 OSD(除非它们乘以池的大小是 OSD 数量的整数倍)。 由于哈希值很少是完美的,并且伪随机分布在选择方面受到进一步的约束——例如,副本必须放置在不同的节点上——OSD 很有可能被分配到其中几个(或没有)。
数学概率很复杂,超出了本文的范围,但我们已经观察到,由于此原因,Ceph 集群中的数据不平衡(在两位数百分比范围内),尤其是在 PG 数量少或大小值大的池中(如上述擦除编码,这会增加影响)。
为什么 Ceph 允许这个问题? ¶
在此阶段,您可能会想知道为什么 Ceph 允许将pg_num 设置为不是 2 的幂的值。 原因是我们希望能够响应实际集群利用率从一个推荐的pg_num 值过渡到另一个值。 (在 Nautilus 之前,这意味着只能增加pg_num,但从那时起,我们也可以处理减少。)
如果通过立即将 pg_num 设置为新的2x 或0.5x 值来完成,每个 PG 都会立即受到影响;要么被减半,要么被加倍。 通过以较小的增量调整pg_num,可以限制集群因拆分或合并造成的负载,并且不平衡只是过渡性的。
并且如果 Ceph 只是完美均匀地分布对象,每个 PG 中的对象都会移动。 同样,这将影响集群中的每个 OSD。
然而,假设这确实是临时的;我们的遥测数据分析表明,这显然是某些集群和池的永久状态!
我们采取的步骤 ¶
我们清楚地需要更强烈地劝阻使用这些值,并引导现有的集群转向最佳值,以改善用户的体验。
文档完善 ¶
我们的文档正在更新,明确指出pg_num 必须是 2 的幂,并且其他值只能是临时的。 纠正了使用不同值的示例。
完全删除手动设置 ¶
手动设置pg_num 暴露了 Ceph 算法的实现细节。 它取决于集群构建后将存储多少数据以及将有多少 OSD。 在以前的版本中,由于pg_num 只能增加,Ceph 无法动态适应集群的使用情况,需要诸如pg_calc 之类的辅助工具,并提前手动设置基于预期工作负载。
有了Ceph 的 Nautilus 版本,添加了一个新的管理器模块“pg_autoscaler”,它可以警告pg_num 选择不佳,并完全自动地按池为基础调整设置。 此新模块将在下一个主要版本中默认启用,但我们强烈建议至少以警告模式启用它,以便了解问题。
仪表板池管理 ¶
在 Ceph 的仪表板中,我们自动调整用户提供的pg_num 为最接近的 2 的幂值。 如果我们启用其他值,我们将建议仅将其用于过渡,以防用户希望手动执行此操作。 我们还将致力于建议用户启用balancer 和pg_autoscaler 模块。
结论 ¶
尽管 Ceph 的遥测功能还处于非常早期的阶段,但这些关于 Ceph 如何部署和配置的见解已经直接促成了我们文档的改进,提出了新功能,并为默认设置的开发决策提供了信息。
随着我们不断完善遥测功能,这些数据将使我们能够回答越来越复杂的问题——从新 Ceph 版本的采用率,到理解某些集群可能延迟升级的原因,哪些平台和功能特别值得测试,以及最终甚至可以发现我们自己测试中可能没有发现,但在生产部署中出现的细微性能回归。
最后但并非最不重要的一点,是向 Ceph 贡献者社区展示我们的工作有助于解决用户在现实世界中的需求。
后续步骤 ¶
如果您正在运行支持该功能的 Ceph 集群,请考虑 启用遥测模块 并为我们的数据贡献!如果您对我们应该调查的内容或共享的数据有任何建议或问题,请 加入讨论。