Luminous 中的新增功能:RADOS 改进

sage

RADOS 是 Ceph 的可靠自治分布式对象存储,为其他组件提供可靠、高可用和可扩展的存储服务。 与每个 Ceph 版本一样,Luminous 包含一系列对 RADOS 核心代码(主要在 OSD 和监控器中)的改进,这些改进使所有对象、块和文件用户受益。

并行监控器查找

Ceph 监控器集群构建用于在大多数监控器守护进程正在运行时发挥作用。 连接到集群的客户端——无论是进行 I/O 还是通过 CLI 执行一些管理命令——都必须首先与监控器进行身份验证,然后才能执行其功能。 客户端代码构建为具有极强的容错能力

  • 可以通过 -m 命令行选项、ceph.conf 中的 mon host 选项、MON_HOST 环境变量,甚至 SRV DNS 记录来列出监控器
  • 监控器可以通过 IP 地址或 DNS 名称来标识。 如果使用 DNS 名称,则所有 A 或 AAAA 记录都会添加到要探测的监控器列表中。
  • 一旦到达任何一个监控器,客户端就会立即了解当前所有监控器的集合。 如果客户端连接时监控器集群的成员发生更改,它也会了解这些更改。 这意味着即使配置过时,仅了解部分监控器的客户端通常仍然可以工作,只要它了解的其中一个监控器可访问即可。
  • 如果客户端断开连接,它将经历一个“查找”序列,探测它知道的随机监控器,直到它可以重新连接

以前的问题是,客户端只会尝试一个监控器,并且在尝试另一个监控器之前会等待 2-3 秒。 如果您的 5 个监控器中有 1 个宕机,那么通过 CLI 发出的每第 5 个命令将从探测宕机的监控器开始,并在尝试一个活动的监控器之前花费 2-3 秒。

Luminous 通过使客户端并行探测多个监控器并使用能够最快连接的会话来解决此问题。 默认情况下,mon_client_hunt_parallel 设置为 2,但可以更改它以控制我们在寻找连接时启动的会话数。

自动 HDD 与 SSD 调整

有数十篇文档在讨论大量的 Ceph 可配置项,这些可配置项针对特定硬件或特定工作负载进行了优化。 在大多数情况下,这些 ceph.conf 片段往往会引起开发人员奇怪的目光,因为正在调整的设置似乎与系统的性能无关,甚至直接危险。 我们的目标是让 Ceph 开箱即用地尽可能地工作,而无需任何调整,因此我们始终致力于选择合理的默认值。 通常,我们不鼓励用户进行调整。 在 Luminous 中,我们采取了措施来注释和记录可用的大量配置旋钮,并清楚地将应调整的设置标记为“仅供开发人员使用”。 (请期待另一篇关于配置选项以及我们在此方面的计划的博客文章。)

无论如何,为了让 Luminous 开箱即用地工作,我们在 BlueStore 和 OSD 代码中添加了功能,以自动检测底层设备是旋转硬盘 (HDD) 还是固态硬盘 (SSD),以便 Ceph 可以自动使用适当的默认值,而无需任何额外的配置。 BlueStore 有相当多的设备特定默认值,但有趣的是,我们只确定了有意义的几个 OSD 选项需要调整。

如果您是 Ceph 的高级用户,并且认为您需要更改环境中的某些设置以获得最佳性能,请告诉我们——我们希望调整我们的默认值,以便您的更改不再必要,或者尝试说服您不应调整该选项。

客户端回退

OSD 会小心地限制从网络读取并排队到内存中的传入客户端请求的数量,以控制内存使用量(默认情况下为 500 MB 或 100 条消息)。 这确保了我们有准备好的工作来使 OSD 保持繁忙,但不会浪费太多内存。 但是,在 Luminous 之前,当 PG 繁忙地进行对等连接、恢复或对象由于某种原因被阻止(例如,如果它“未找到”,因为最新版本仅存储在当前未启动的 OSD 上)时,我们可能会遇到问题。 通常,Ceph 会将阻塞的请求放在等待列表中,直到它准备好处理它们。 但是,如果 PG 或对象不可用时间过长,则有可能累积足够的阻塞客户端消息而耗尽内存限制,从而阻止 OSD 处理任何请求。

这显然不好。 对于未找到的对象,这个问题尤其让管理员感到沮丧,因为需要撤销或删除未找到对象的命令需要向 OSD 发送请求……这通常不会被 OSD 读取或处理,因为内存限制已达到。 唯一的解决方法是重新启动 OSD 并快速重新发出管理命令,然后再让其他客户端重新发送其消息。

Luminous 通过扩展 RADOS 客户端/OSD 协议来解决此问题,该协议包括一种“回退”功能,OSD 可以指示客户端停止发送单个 PG 或对象的请求。 稍后,当 OSD 准备好处理工作时,客户端将被取消阻止,并且可以流式传输请求。 OSD 在几种不同的情况下发出回退(某些对等状态和未找到的对象是主要的),预计在这些情况下在能够处理请求之前会有一些延迟。 这使 OSD 资源可以自由处理其他 PG 和对象的请求,并允许管理员与 OSD 通信以解决任何问题。

异步对等删除

在大多数情况下,RADOS 会竭尽全力以有条不紊的延迟方式处理任何无界工作。 例如,当 OSD 短时间下线并重新上线时,在“对等”过程中,它会构建一个过时或缺失对象的列表(也称为 缺失集合),并在后台将它们更新到最新状态,同时仍然服务于其他对象的请求。

但是,我们错过了一个案例:删除。 如果最近操作的日志包含对象删除,则这些更改将由对等代码同步处理,这意味着在对等连接完成并激活之前必须立即删除对象。 OSD 恢复和删除繁重的负载的组合并不常见,以至于我们花了几年时间才注意到这实际上是一个问题,但最近在几个不同的工作负载下出现了这个问题。

Luminous 最终调整了对等和恢复代码,以异步处理待处理的删除,就像处理其他对象更新一样。 如果您不幸遇到此问题(通常只是表现为 非常 慢的对等连接),那么在升级并运行“ceph osd require-osd-release luminous”后,它应该消失了。

大型 ping 消息

巨型帧通常是实现高端网络设备和大型高性能集群中高吞吐量的关键。 它们也是 Ceph 支持工程师的祸根,因为他们被要求解释为什么在高负载下请求会神秘地挂起。 我无法统计有多少次我花了半天时间来研究日志,以识别单个阻塞的 TCP 流,并不得不说服网络工程师团队重新检查他们的交换机配置。 我不知道为什么似乎有这么多方法可以配置错误巨型帧,但不可避免的是,在这些情况下关闭它们可以解决问题。

历史上很难捕获此类错误配置的原因是,OSD 实际上在每个守护进程之间都有两个 TCP 连接:一个用于实际工作,另一个用于心跳“ping”消息。 当我们开始加载集群并且实际 TCP 连接上的大型数据包挂起时,心跳流会继续愉快地传递消息,并且 OSD 无法意识到它们无法通信。

在 Luminous 中,我们将“ping”消息更改为默认情况下较大——大约 8 KB——以便如果交换机在处理大型数据包时遇到问题,它们更有可能失败。 希望这能使这些网络配置问题更容易识别!

节流和睡眠改进

在过去的几个版本中,我们添加了各种选项,以将简单的延迟或睡眠注入到后台工作活动中,以限制其对系统响应能力的影响。 这始终被视为短期解决方案——我们真正希望系统尽快处理后台工作,但始终(或大部分时间)优先处理任何传入的客户端请求。 因此,注意力集中在改进 QoS 上,并且我们大多忽略了基于睡眠的解决方法。

与此同时,其他 OSD 重构活动将大部分后台工作移动到主工作队列中(以便更好地降低其优先级,以应对客户端工作),而旧的睡眠解决方法实际上会使情况变得更糟而不是更好。 在 Luminous 中,这些设置都已重新实现以适当的行为。 我们还为其中许多设置设置了默认值(基于 OSD 是基于 SSD 还是 HDD),以限制恢复对客户端性能的影响。 此外,某些活动(例如快照修剪)具有新的选项,用于优先处理其活动与客户端 I/O(我们首选的解决方案)。 其中许多都非常重要,我们也将其回溯到 Jewel 点版本。

恢复抢占

如果 OSD 下线一段时间后重新上线,对等过程将确定最近更新的哪些对象已过时,或者(如果 PG 日志不够长)是否需要进行完全扫描(也称为“回填”)才能使恢复的 OSD 重新同步。 由于 OSD 通常有许多需要恢复的 PG,因此每个 PG 的优先级都基于其恢复对数据安全的重要性。 例如,如果 PG 只有 1 个完全完成的副本,它将获得比具有 2 个完整副本的 PG 更高的优先级,并且基于日志的最近对象恢复通常优先于回填,因为它可以更快地完成。

但是,在 Luminous 之前,一旦恢复或回填开始,它就会运行到完成,即使出现另一个具有更高恢复优先级的 PG。 这可能导致仅需要少量(高优先级)工作的 PG 必须等待很长时间才能进行另一个 PG 的回填。 它甚至可能导致过度内存使用,因为阻塞的 PG 无法修剪旧的日志条目(因为日志条目需要用于基于日志的恢复)。

这在 Luminous 中通过恢复抢占得到解决,这意味着 OSD 将始终致力于恢复优先级最高的 PG。 这项更改的一个副作用是,诸如 osd max backfills(控制每个 OSD 并行恢复多少个 PG)之类的可调参数可以调低,并且 OSD 将立即响应,通过推迟某些 PG 的恢复来遵守限制。

EIO 恢复

新的 BlueStore 后端的全数据校验和的一个副作用是,介质错误可能导致校验和失败,现在这些失败会向上传播到 OSD,成为 IO 错误 (EIO)。 在使用 FileStore 时,这种情况并不经常发生,因为我们没有校验和来验证--只有当设备本身报告错误时,我们才会收到此类错误。 然而,将错误返回给客户端并不是一种礼貌的做法--毕竟,我们是一个具有内置冗余的分布式存储系统。 Luminous 包含一系列请求处理方面的改进,以便在遇到这些错误时,通过利用其他副本或额外的纠删码分片来自动修复这些错误,从而确保问题得到纠正,并且客户端获得正确的结果。 无法纠正的错误将导致 OSD 将对象标记为未找到,需要管理员干预。

RocksDB 代替 LevelDB

监控守护进程和旧的 FileStore OSD 后端都使用 LevelDB 来存储各种键/值数据。 总体而言,它为我们服务得很好,但对于非常大的 leveldb 实例--无论是具有大量 OSDMap 的监控器,还是具有大量键/值对象数据的 RGW 索引的 OSD--leveldb 的压缩已成为一个严重的问题。 在某些情况下,压缩无法跟上注入的更新,并且 OSD 或监控守护进程陷入了崩溃。

BlueStore 是基于 RocksDB 构建的,RocksDB 是 LevelDB 的一个分支,具有广泛的改进,并且被 Facebook 和其他公司广泛使用。 在对其整体稳定性感到满意后,我们也在监控器和 FileStore 中用 RocksDB 替换了 LevelDB,并且已经看到这些问题大多消失了。 事实上,它改进得如此之大,以至于我们也在将 RocksDB 的更改回移植到 Jewel,以便新的 Jewel OSD 将默认使用它。

总结

像 Ceph 这样复杂系统的整体用户体验和感知鲁棒性,很大程度上取决于所有没有出错的事情,以及所有正确发生的事情。 当一个微妙的问题被修复时,对于开发人员来说,这有点令人沮丧,因为--如果我们做得好,很可能没有人会注意到。 即使是那些在早期版本中不幸遇到该问题的少数操作员,在相同问题以后没有再次出现时,也可能不会注意到。 我们希望这些改进能够引起用户的共鸣,并让他们了解正在进行的重要但有些不那么光鲜的工作。