Ceph Reef 冻结(第 1 部分):RBD 性能

摘要
Ceph 社区最近冻结了即将发布的 Reef 版本,今天我们来分析 Reef 的 RBD 性能,测试环境为 10 个节点、60 个 NVMe 驱动器的集群。在解决了一个小的硬件问题(通过 NVMe 固件更新修复)后,Reef 能够持续保持大约 71GB/s 的大块读取速度和 25GB/s 的大块写入速度(包括 75GB/s 的复制)。对于小随机 IO,Reef 提供了大约 4.4M 随机读取 IOPS 和 800K 随机写入 IOPS(包括 2.4M 的复制)。对于小 4K 顺序同步写入,Reef 实现了 小于 0.5ms 的平均延迟,小于 0.5ms 的 99% 延迟,以及小于 0.8ms 的 99.9% 延迟。即使在商品硬件上执行 3 倍同步复制,它也实现了小于 8ms 的最大延迟。虽然 Reef 通常与 Quincy 一样快或更快,但我们检测到一种小的潜在回归,被其他改进所掩盖。在 Reef 冻结期间,我们将调查像这样的回归,以帮助使 Reef 成为迄今为止最好的 Ceph 版本。
简介
在过去几个 Ceph 版本中,上游 Ceph 社区和 Red Hat 的性能和规模团队运行了各种性能测试,以比较以前的版本与我们新的预发布代码。我们希望确认我们期望看到的收益,并验证我们是否没有引入任何最后一刻的回归。这在 Pacific 和 Quincy 发布周期中对我们来说都是一个巨大的胜利。在两个版本发布之前,我们都能够定位回归并最终 修复问题,从而避免对性能产生负面影响。
不幸的是,捕获微妙的性能问题非常复杂,并且在尝试比较过去收集的结果与新鲜结果时会变得更加复杂。可能发生了什么变化?回归是由于代码的更改、硬件/软件堆栈的更改,还是其他原因造成的?Performance-CI 在尝试在问题发生时捕获问题时可能很有用,但它需要大量的资源,并且如果不小心,很容易误解。今天,我们将仅查看一套简单的测试,比较 Quincy 和 Reef,并尝试以相同的方式、在相同的硬件上进行测试,并尽可能减少差异。事实证明,这次有一个相当有趣的转折,但我们稍后会讨论。
致谢
首先,感谢我的朋友和同事们 Clyso GmbH 鼓励我继续担任上游 Ceph 性能负责人,并支持为社区利益创建像这样的文章。同时感谢 IBM / Red Hat 和 Samsung 向 Ceph 上游社区提供用于此测试的硬件。最后,感谢所有为我们带来另一个优秀的 Ceph 版本而不知疲倦地工作的 Ceph 开发人员!
集群设置
| 节点 | 10 x Dell PowerEdge R6515 |
|---|---|
| CPU | 1 x AMD EPYC 7742 64C/128T |
| 内存 | 128GiB DDR4 |
| 网络 | 1 x 100GbE Mellanox ConnectX-6 |
| NVMe | 6 x 4TB Samsung PM983 |
| 操作系统版本 | CentOS Stream release 8 |
| Ceph 版本 1 | Quincy v17.2.5 (从源代码构建) |
| Ceph 版本 2 | Reef 9d5a260e (从源代码构建) |
所有节点都位于同一 Juniper QFX5200 交换机上,并通过单个 100GbE QSFP28 链路连接。Ceph 使用 CBT 部署,并启动了 fio 测试。除非另有说明,否则每个节点配置为托管 6 个 OSD,并使用 librbd 引擎的 6 个协同 fio 进程。在 Intel 系统上一个重要的操作系统级别优化是将 tuned profile 设置为“latency-performance”或“network-latency”。这主要通过避免与 CPU C/P 状态转换相关的延迟峰值来帮助。基于 AMD Rome 的系统似乎不太敏感,并且我尚未确认 tuned 实际上是否限制了 C/P 状态转换,但是,tuned profile 仍然设置为“network-latency”用于这些测试。
测试设置
CBT 配置为使用一些修改后的设置来部署 Ceph。
主要,禁用了 rbd 缓存,每个 OSD 被赋予 8GB 的内存目标,并使用了 msgr V2,同时禁用了 cephx。fio 配置为首先用大写填充 RBD 卷,然后进行 3 次迭代的测试(如下表所示),iodepth=128,持续 5 分钟。使用了每个节点的 6 个 fio 进程,总共 60 个 fio 进程和 7680 的聚合 iodepth。某些后台进程,例如 scrub、deep scrub、pg autoscaling 和 pg balancing 被禁用。使用了具有静态 16384 PGs(高于通常建议的数量)和 3 倍复制的 RBD 存储池,以及每个 fio 进程的 1 个 RBD 镜像。
| IO 大小 | 读取 | 写入 | 随机读取 | 随机写入 |
|---|---|---|---|---|
| 4096 | X | X | X | X |
| 131072 | X | X | X | X |
| 4094304 | X | X | X | X |
最初具有误导性的结果
在任何大于单个 OSD 集群中,Ceph 使用 crush 以伪随机方式确定性地放置数据。虽然较高的 PG 计数和/或 PG 平衡化可以帮助提高这一点,但总会有时间热点,并且某些 OSD 最终比其他 OSD 花费更长的时间来完成其工作。因此,聚合的长期集群性能通常受限于任何给定时间最慢或最繁忙的 OSD。这是每个 Ceph 操作员都会学习并定期重新学习的教训,包括我自己。为什么我现在要提出这个问题?在 Reef 冻结之后,我恢复了之前用于 Quincy 测试的 CBT 配置,并开始运行一组新的测试。最初的结果看起来还不错。Quincy 的性能比预期略低,但并不太偏离我们之前看到的 结果。但是,当我到达 Reef 时,结果开始看起来有点出乎意料。
Reef 正在使用在 RocksDB Tuning Deep Dive 中测试的新 RocksDB 调整。我们在将这些调整与 Quincy 配对时看到了显著的改进,并期望看到 Reef 类似的收益。在这些测试中,Reef 的性能与 Quincy 相比并没有提高,实际上甚至不如 Pacific。我承认,我最终运行了许多测试,试图找出任何可能解释差异的模式或问题。在某个时候(比应该发生的要晚得多),我意识到我应该开始查看系统指标。CBT 为每个测试运行 collectl 的副本,并记录大量的系统指标数据。事实上,在 RBD 和 RGW 测试运行期间,CBT 记录了超过 20GB 的指标数据,历时数小时。我开始工作,并最终查看了系统中每个 NVMe 驱动器的底层设备行为。我开始注意到一种模式。nvme4 在第 10 个集群节点中,在许多写入测试中显示了很高的设备队列等待时间,但在读取测试中没有显示。当我查看 4KB 随机写入时,效果变得明显
哇!nvme4 上的这些延迟峰值非常强烈,几乎肯定与预期性能不佳有关。该驱动器是迄今为止最严重的罪魁祸首,但其他节点的某些驱动器也显示出高于预期的设备延迟。我的第一想法是简单地对每个驱动器执行完全安全擦除,假设碎片化可能是问题所在。但我记得,在 Quincy 发布期间,我从 Samsung 获得了一个新的固件镜像。它似乎没有帮助解决当时遇到的问题,但 Samsung 认为它可能有助于提高整体性能。我回去并在 Mako10 上安装了它,结果立竿见影。
固件升级后,设备队列中从未出现超过一个 IO 的等待,并且队列等待时间始终为 0ms。看来固件更新是一个胜利,但这是永久性的解决方案吗?我们需要随着时间的推移观察硬件状态以确保这一点。但是,对于此测试而言,我们似乎又回到了正轨。性能提高了多少?固件更新主要帮助了 4KB 和 128KB 随机写入测试。
性能现在恢复到去年秋季 RocksDB 调整测试中观察到的水平。更重要的是,小随机 IO 测试显示了非常一致的 NVMe 驱动器行为。足够好了,可以重新运行测试并进行比较。
4MB 顺序吞吐量

在大型吞吐量测试中,Quincy 和 Reef 实现了大致相同的性能水平。Reef 在大块写入方面可能略快,而在大块读取方面可能略慢。在两种情况下,底层集群都能够以大约 70-75GB/s 的速度执行,但由于我们正在执行 3 倍复制,因此客户端可见的写入吞吐量实际上约为 25GB/s。平均每个 OSD 的 CPU 消耗量在读取时约为 1-1.5 个核心,在写入时约为 3-4 个核心。这种差异非常典型,因为 Ceph 的写入路径比读取路径执行更多工作。
4KB 随机 IOPS

对我来说,每个版本中最令人兴奋的测试是小随机 IO 测试。这些测试真正地强调了 OSD,并展示了我们是否保持了 IO 管道的效率。在这种情况下,我们获得了总体上积极的结果,但有一些注意事项。在 4K 随机读取方面,Reef 略慢于 Quincy,但非常接近。另一方面,我们现在始终看到 4K 随机写入测试有所改善,这主要归功于新推出的 RocksDB 调整。有趣的是,我们没有看到基于去年秋季的结果所期望的那么大的性能提升。CPU 使用量在随机读取测试中每个 OSD 略高于 7 个核心,在 Reef 的随机写入测试中每个 OSD 接近 11 个核心。这似乎与更高的性能相比 Quincy 成比例。一个有趣的方面是,增加 Ceph 中的小随机写入性能,kv_sync_thread 经常是使用 NVMe 和无限 CPU 资源进行测试时的瓶颈,但 CPU 的消耗主要发生在 OSD 工作线程和 messenger 线程中,这些线程在 CPU 受限的场景中很容易成为瓶颈。因此,最大化写入性能是 OSD 数量、NVMe 速度、核心数量和核心速度之间的微妙平衡。
随机写入性能在 Reef 中高于 Quincy,这很好,但并不像我们希望的那么高。为什么?有两个额外的测试可能提供线索。在冻结 Reef 之前,我们升级到最新版本的 RocksDB,因为该版本修复了许多重要的错误和改进,而 Quincy 使用的版本要老得多。我们可以简单地还原该更改,看看 Reef 的表现如何。我们还可以使用 Reef 现在用作标准的 RocksDB 调整来运行 Quincy,看看这能提高 Quincy 的性能多少。
除了 v17.2.5 在使用 Reef 调整时运行的一次特别慢的测试外,数字非常接近。似乎有一个一致的,但很小的(约 2%)的性能提升,当 Reef 使用较旧的 Quincy 版本的 RocksDB 编译时。使用相同版本的 RocksDB 编译的 Quincy 和 Reef 不相上下。
在随机写入的情况下,我们看到了两个非常有趣的结果。一:当 Quincy 使用新的 RocksDB 调整默认值编译时,它实际上比 Reef 快,无论使用哪个版本的 RocksDB。二:还原到旧版本的 RocksDB 确实会带来性能提升,但同样也很小(约 1-2%)。它无法完全解释在使用新的 RocksDB 调整时看到的回归。最终结果是,Reef 中很可能存在一个小回归,影响小随机写入。
4KB 顺序同步写入延迟
在过去一年中,我收到了很多关于 Ceph 中写入延迟的问题。Ceph 能否实现亚毫秒级的写入?我们看到的尾部延迟是多少?我们过去已经测试过,但我也决定在这里包含一组快速的 4K 同步顺序写入测试。有一些注意事项。这是一个具有大量可用空间和几乎没有碎片化的全新集群。只有一个客户端正在执行写入,io_depth 为 1。这几乎是一个展示 Ceph 潜力 实现低延迟的理想案例。它并不一定反映在繁忙的集群上,在具有活动流量和现有碎片化的集群上,实际平均或尾部延迟会是什么样子。在给出该免责声明之后,我们表现如何?
| 指标 | O_DSYNC Quincy | O_SYNC Quincy | O_DSYNC Reef | O_SYNC Reef |
|---|---|---|---|---|
| 平均延迟 (ms) | 0.417 | 0.416 | 0.421 | 0.418 |
| 99% 延迟 (ms) | 0.465 | 0.461 | 0.465 | 0.469 |
| 99.9% 延迟 (ms) | 0.741 | 0.733 | 0.750 | 0.750 |
| 最大延迟 (ms) | 7.404 | 6.554 | 7.568 | 6.950 |
在两种情况下,Quincy 和 Reef 都能以小于 0.5ms 的延迟写入绝大多数 IO。CBT 保存了每个运行的 fio 延迟图,因此我们也可以查看这些图
总体而言,结果非常一致,只有几个异常值。一个注意事项是,在 librbd 中使用 fio 测试时,使用 O_SYNC 和 O_DSYNC 标志之间可能没有太大区别。我联系了 Ilya Dryomov(Ceph 的 RBD 负责人),以了解他的想法。他确认 librbd 和内核 RBD 都不关心这些标志,因为这些标志在 VFS 层处理。但是,我们应该仅在这些写入已完全持久化到所有参与的 OSD 上后才寻求确认。无论如何,性能似乎在所有运行中都是等效的。
在回顾这篇博文时,Dan van der Ster(感谢 Dan!)指出,突出在进行这些单客户端、io_depth=1 测试时涉及的网络延迟也将会很有用。我非常不科学地返回并运行了一些不同集群节点之间的 ping 测试。几点说明:ping 是 ICMP 而不是 TCP,ping 也是往返时间。
从 mako01 到 mako10 的 Ping(100GbE 接口)
| icmp_seq | 延迟 (ms) |
|---|---|
| 1 | 0.039 ms |
| 2 | 0.025 ms |
| 3 | 0.032 ms |
| 4 | 0.029 ms |
| 5 | 0.034 ms |
| 6 | 0.027 ms |
| 7 | 0.026 ms |
| 8 | 0.026 ms |
| 9 | 0.028 ms |
| 10 | 0.032 ms |
在读取情况下,使用复制,以及使用 RBD 进行测试时,Ceph 仅从客户端到主 OSD 执行往返操作。在写入情况下,Ceph 必须执行多次往返。一次在客户端和主节点之间,一次在主节点和每个辅助节点之间并行。在写入测试中,我们应该期望比贡献的开销平均网络延迟略差。因此,网络延迟可能在这些小的同步写入测试中发挥着重要(尽管可能不是主导)作用。然而,Ceph 本身在同步写入延迟方面仍有改进空间,但此时网络延迟是一个有效的问题,并且随着 Ceph 本身的改进,它将成为一个更大的因素。
结论
这篇博文最终与处理底层硬件性能和固件更新的冒险一样多,而不是关注 Reef。了解底层硬件的行为在基准测试时至关重要,如果我们没有首先升级所有 SSD 驱动器的固件,我们将错过一些有趣的行为(以及更高的写入 IOPS!)。这是一个友好的提醒,所有有志于进行基准测试的人员,在花一天时间运行测试之前,请确保您的固件是最新的,并且您的硬件运行良好。
一旦硬件状况良好,Quincy 和 Reef 显示出相当可比的性能。两者都实现了大约 71GB/s 的大容量读取和 25GB/s 的大容量写入,具有 3 倍复制。两者也实现了相似的 4KB 随机读取性能,约为 4.4-4.5M IOPS。由于新的 RocksDB 调整,Reef 在小随机写入方面比 Quincy 快约 6-7%,但我们预计它会快一点。似乎存在一个回归,限制了 Reef 实现更高的性能。我们将会在 Reef 冻结期间调查该潜在的回归,并继续努力使 Reef 成为最好的 Ceph 版本!
感谢您的阅读,如果您有任何问题或想进一步讨论 Ceph 性能,请随时 联系。