Ceph Bobtail JBOD 性能调优
目录
简介 ¶
Ceph 强大的地方之一在于它提供的众多可调参数。您可以在管道的几乎每个阶段控制缓冲的数据量和操作数量。您可以引入不同的刷新行为,或者更改用于文件存储操作的线程数量。缺点是,深入研究所有这些内容并甚至知道从哪里开始可能会让人望而却步。在 Inktank,我们收到了很多关于这些选项如何影响性能的问题。答案通常是这取决于具体情况。不同的硬件和软件配置会倾向于不同的 Ceph 选项。为了至少给人们一个大致的想法,哪些事情可能值得关注,我们决定深入研究并梳理一些最有可能影响性能的选项。具体来说,在本文中,我们将研究在使用 JBOD 配置的磁盘时不同的 Ceph 参数。
由于 Inktank 愿意付钱给我画网络漫画(大家好!),这里有一张我完成所有这些工作后的近似图像

在继续之前,如果您还不熟悉 Ceph 的配置,可以在 Ceph 文档中找到一个很好的介绍,网址为 此处。一旦掌握了这些知识,您将需要查看可调参数列表及其描述,网址为 此处。
系统设置 ¶
我们将使用 SAS2208 控制器进行这些测试。它支持 JBOD、多个单驱动 RAID0 LUN 和单个 LUN RAID0 配置。不幸的是,不同的控制器行为不同,因此这些结果可能不代表其他控制器。希望它们至少能提供一个初始起点,并可能推测出类似配置的性能如何。
此设置中使用的硬件包括
- Chassis: Supermicro 4U 36-drive SC847A
- Motherboard: Supermicro X9DRH-7F
- 磁盘控制器:板载 SAS2208
- CPUS: 2 X Intel XEON E5-2630L (2.0GHz, 6-core)
- RAM: 8 X 4GB Supermicro ECC Registered DDR1333 (32GB total)
- Disks: 8 X 7200RPM Seagate Constellation ES 1TB Enterprise SATA
- NIC: Intel X520-DA2 10GBE
As far as software goes, these tests will use
- OS: Ubuntu 12.04
- 内核:来自 Ceph 的 GitBuilder 归档的 3.6.3
- Tools: blktrace, collectl, perf
- Ceph:在 0.56 bobtail 版本发布之前,Ceph “next” 分支。
测试设置 ¶
编写了一个小的 Python 工具,该工具读取 YAML 配置文件并自动生成具有不同参数设置的多个 ceph.conf 文件。然后,这些文件与我们的基准测试工具一起用于对每种配置运行一系列测试。一些配置参数已被分组,以减少需要测试的排列总数。以下 YAML 片段显示了默认设置以及要迭代的设置
default: global: log_to_syslog: "false" log_file: "/var/log/ceph/$name.log" auth_cluster_required: "none" auth_service_required: "none" auth_client_required: "none" filestore_xattr_use_omap: "true"
mon: mon_osd_data: "/srv/mon.$id" mon.a: host: "burnupiX" mon_addr: "127.0.0.1:6789"
parametric: debugging_off: debug_lockdep: "0/0" debug_context: "0/0" debug_crush: "0/0" debug_mds: "0/0" debug_mds_balancer: "0/0" debug_mds_locker: "0/0" debug_mds_log: "0/0" debug_mds_log_expire: "0/0" debug_mds_migrator: "0/0" debug_buffer: "0/0" debug_timer: "0/0" debug_filer: "0/0" debug_objecter: "0/0" debug_rados: "0/0" debug_rbd: "0/0" debug_journaler: "0/0" debug_objectcacher: "0/0" debug_client: "0/0" debug_osd: "0/0" debug_optracker: "0/0" debug_objclass: "0/0" debug_filestore: "0/0" debug_journal: "0/0" debug_ms: "0/0" debug_mon: "0/0" debug_monc: "0/0" debug_paxos: "0/0" debug_tp: "0/0" debug_auth: "0/0" debug_finisher: "0/0" debug_heartbeatmap: "0/0" debug_perfcounter: "0/0" debug_rgw: "0/0" debug_hadoop: "0/0" debug_asok: "0/0" debug_throttle: "0/0"
osd_op_threads: [1, 4, 8] osd_disk_threads: [2, 4, 8] filestore_op_threads: [1, 4, 8]
flush_true: filestore_flush_min: 0 filestore_flusher: "true"
flush_false: filestore_flush_min: 0 filestore_flusher: "false"
journal_aio: ["true"] ms_nocrc: ["true"]
big_bytes: filestore_queue_max_bytes: 1048576000 filestore_queue_committing_max_bytes: 1048576000 journal_max_write_bytes: 1048576000 journal_queue_max_bytes: 1048576000 ms_dispatch_throttle_bytes: 1048576000 objecter_infilght_op_bytes: 1048576000
big_ops: filestore_queue_max_ops: 5000 filestore_queue_committing_max_ops: 5000 journal_max_write_entries: 1000 journal_queue_max_ops: 5000 objecter_inflight_ops: 8192
small_bytes: filestore_queue_max_bytes: 10485760 filestore_queue_committing_max_bytes: 10485760 journal_max_write_bytes: 10485760 journal_queue_max_bytes: 10485760 ms_dispatch_throttle_bytes: 10485760 objecter_infilght_op_bytes: 10485760
small_ops: filestore_queue_max_ops: 50 filestore_queue_committing_max_ops: 50 journal_max_write_entries: 10 journal_queue_max_ops: 50 objecter_inflight_ops: 128
与之前的文章类似,我们直接在 SC847a 上使用 localhost TCP 套接字连接运行测试。我们执行读和写测试。在每个设备的开头设置了一个 10G 日志分区。对于本文,仅测试了 SAS2208 的 JBOD 模式,该模式不使用板载缓存。其他模式可能在后续文章中进行测试。CFQ 用作所有测试的 IO 调度器。
为了生成结果,我们使用 Ceph 内置的基准测试命令“RADOS bench”,该命令为要写入的每个数据块写入新对象(总有一天我会写上承诺的小 io 性能基准测试文章!)。RADOS bench 具有一定的优点和缺点。一方面,它可以清楚地了解 OSD 以各种大小读写对象的速度有多快。它不能测试的是执行大型对象的小 IO 的速度有多快。出于这个原因和其他原因,这些结果不一定能反映 RBD 的最终性能。
与我们之前的文章一样,我们运行 8 个并发的 RADOS bench 实例并将结果汇总,以确保它不会成为瓶颈。我们指示每个 RADOS bench 实例写入自己的池,每个池有 2048 个 PG。这样做是为了确保在后续的读测试中,每个 RADOS bench 实例读取的是其他实例先前未读入页面缓存的唯一对象。您可能还会注意到,我们正在使用池每 PG 的 2 的幂次方。由于 Ceph 实现 PG 分裂行为的方式,使用 2 的幂次方数量的 PG(尤其是在 PG 数量较低的情况下!)可以提高数据在 OSD 上的均匀分布。在较大的 PG 数量下,这可能不太重要。
RADOS bench 提供了关于对象大小、并发运行的数量以及测试运行时间的一些灵活性。我们选择了 5 分钟的测试,并使用以下排列
- 4KB Objects, 16 Concurrent Operations (2 per rados bench instance)
- 4KB Objects, 256 Concurrent Operations (32 per rados bench instance)
- 128KB Objects, 16 Concurrent Operations (2 per rados bench instance)
- 128KB Objects, 256 Concurrent Operations (32 per rados bench instance)
- 4M Objects, 16 Concurrent Operations (2 per rados bench instance)
- 4M Objects, 256 Concurrent Operations (32 per rados bench instance)
对于每种排列,我们使用 BTRFS、XFS 或 EXT4 作为底层 OSD 文件系统运行相同的测试。在每个测试之间重新格式化文件系统并重新运行 mkcephfs,以确保先前测试的碎片不会影响结果。请记住,如果尝试使用这些结果来确定生产集群的性能,这可能会产生误导。每个文件系统似乎以不同的方式老化,并且可能随着时间的推移表现出非常不同的性能。尽管如此,在每个测试之间重新格式化对于确保比较的公平性是必要的。每个文件系统都传递了 mkfs 和挂载选项
- mkfs.btfs options: -l 16k -n 16k
- btrfs mount options: -o noatime
- mkfs.xfs 选项:-f -i size=2048
- xfs 挂载选项:-o inode64,noatime
- mkfs.ext4 选项
- ext4 mount options: -o noatime,user_xattr
在测试期间,collectl 用于记录各种系统性能统计信息。
4KB RADOS BENCH 写入结果 ¶
好的,希望这张图表大部分是自解释的,但如果不是,基本上想法是,我们为每个文件系统都有 3 个样本,大量的不同参数,并且我们根据性能高于或低于默认配置绘制彩色圆圈。可能需要注意的是,BTRFS 和 XFS 在显式启用文件存储刷新器时会受到多少影响。除此之外,看起来启用日志 AIO 通常是一个优势。
就像 16 个并发操作的结果一样,BTRFS 和 XFS 在启用文件存储刷新器时会受到影响。但是,启用日志 AIO 再次表现出优势。使用 256 个操作,我们还可以看到,增加队列中的并发操作数量可能会提高性能。同样,减少并发操作的数量似乎会降低性能。
4KB RADOS 基准测试读取结果 ¶
刷新器的情况仍然不容乐观。它严重损害了 XFS 和 EXT4 的读取性能。禁用调试通常有助于提高性能,并且看起来增加 OSD 操作线程的数量对性能有积极的影响。
我认为到目前为止,我们已经确定刷新器对小 IO 没有太大帮助。禁用调试似乎再次有所帮助,这可能对于具有大量消息输出到日志的繁重小 IO 工作负载来说是合理的。有趣的是,增加队列中允许的 OPs 数量似乎会损害 EXT4 的性能。否则,我们看到相同的趋势,即增加 OSD 操作线程的数量似乎会提高性能。另外请注意,有多少不同的参数似乎会提高 XFS 的性能。我有一种感觉,“默认”XFS 性能的样本平均值低于应有的水平,这使得许多参数看起来比实际更好。
128KB RADOS 基准测试写入结果 ¶
默认情况下,文件存储刷新器仅针对大于 64k 的操作启用。通过显式禁用它,我们看到 BTRFS 的性能有所提高,但 XFS 的性能却相反。启用日志 AIO 再次提供性能提升。
这很有趣。正如我们之前所说,默认情况下,文件存储刷新器仅针对大于 64k 的操作启用。在这种情况下,禁用它会提高 EXT4 的性能。更有趣的是,显式为所有 IO 大小启用它实际上会损害性能,尽管我们正在执行 128k 操作。日志 AIO 再次提高了性能,还有一些其他选项会增加或减少性能。
128KB RADOS 基准测试读取结果 ¶
再次出现各种不同的选项,这些选项可能会提供一些性能改进(似乎是 BTRFS),但最明显的影响似乎仍然是 OSD 操作线程的数量,就像在 4K 读取测试中一样。
我有一种感觉,我们再次看到“默认”性能的样本有点偏差的情况。在这种情况下,也许有点偏高(即,很多其他东西看起来很低)。话虽如此,OSD 操作线程的数量似乎仍然有相当大的影响。
4MB RADOS 基准测试写入结果 ¶
看起来禁用刷新器和启用日志 AIO 再次是提高写入性能的两个主要变化。
对于我们最后的写入结果……奇怪!禁用刷新器没有太大帮助,启用它也没有。启用日志 AIO 从对 BTRFS 提高性能转变为损害性能。限制各种缓冲区和队列中允许的字节数会损害性能。至少对于 BTRFS 而言,增加它也会损害性能!如果我们可以对每个测试进行 100 个样本,那该多好?
4MB RADOS 基准测试读取结果 ¶
啊哈!更多意外的结果。看起来 OSD 操作线程仍然有影响,但对于 XFS 和 EXT4,随着线程数量的增加,性能正在下降。看起来禁用消息传递中的 CRC32C 也会提供一点性能提升。
最后,使用更多的并发读取操作,我们再次看到增加 OSD 操作线程计数会损害 EXT4 和 XFS 的性能。对于 BTRFS,看起来性能在 4 个 OSD 操作线程时达到峰值。
RESULTS SUMMARY ¶
以上散点图让我们对不同 IO 大小下不同参数如何相互影响,以及如何影响性能有了一个大致的了解,但并不能真正深入了解每个参数如何影响整体性能。让我们分别查看每个参数。在以下图表中,计算并比较了每个参数测试的样本的平均值和标准差,以及“默认”配置的平均值和标准差。显示了平均值之间的百分比差异。如果结果的 1 个标准差范围重叠,则不进行颜色编码。如果 1 个标准差范围不重叠且参数平均值较高,则结果以绿色编码。如果范围不重叠且参数平均值较低,则以红色编码。
看起来,通过增加我们“大字节”测试中定义的各种队列和缓冲区中允许的字节数,可以提高中等大小写性能。话虽如此,它似乎只有在有大量并发 IO 正在进行时才会产生影响,并且似乎只对 EXT4 有持续的好处。
当有大量小 IO 正在进行时,增加队列中允许的小操作数量似乎确实有好处。EXT4 读取有一个相当明显的例外。也许通过单独测试这个组中的每个参数,我们可以隔离导致它的原因并保持这些好处。
禁用调试似乎对小 IO 性能有益,尤其是对于读取。这可能是与 OSD 操作线程的数量有关,因此值得尝试将其与更多或更少的线程结合使用,看看会发生什么。
这有点有趣。将 filestore 操作线程的数量(即实际写入数据的线程)从 2(默认值)减少到 1 似乎可以提高小到中等大小操作的性能。这可能是因为我们使用的是 JBOD 配置,每个 OSD 后面只有一个磁盘。
将 filestore 操作线程的数量从 2 增加到 4 可能会提供一些轻微的改进,但总体性能似乎大致相同。
然而,将 filestore 操作线程的数量从 2 增加到 8 似乎会导致一些性能下降。
看起来将 XATTRS 保留在文件系统中并没有比将其放在 leveldb 中提供太多好处。对于 XFS,leveldb 实际上可能略快,但这些结果可能不够精确,无法确定。
在 Bobtail 中,filestore flusher 默认启用,但仅适用于 64kb 或更大的操作。当我们显式禁用它时,看到对 256 个并发 4K EXT4 写入产生如此大的影响,这很奇怪。这让我怀疑 EXT4 的结果是否被扭曲了。在更大的 IO 大小下,结果好坏参半。至少对于 BTRFS 来说,关闭 flusher 似乎是有意义的。
然而,显式启用 flusher 几乎总是对小操作不利,除了 EXT4 上的 4K 写入。如果您还记得我们之前的 Argonaut vs Bobtail Performance Preview 文章,我们注意到 EXT4 读取性能有所提高,而 EXT4 写入性能有所下降。Argonaut 默认情况下为所有写入启用 filestore flusher,而 Bobtail 更改了该行为,仅刷新 64k 或更大的写入。如果您使用的是 EXT4,您目前必须在更快的读取和小操作之间做出选择。
Journal AIO 看起来几乎在所有写入方面都是一种优势,可能除了大量并发大 IO 之外。这可能是我们将在未来的 Ceph 版本中考虑默认启用的事情。
在主机上安装 8 个 OSD 和 12 个 2.0GHz Xeon E5 核心的情况下,禁用 messenger 中的 CRC32c 计算并没有太大作用。我们可能不太受 CPU 限制。在似乎有影响的两种情况下,我要冒险说我们没有足够的样本。
这里的结论似乎不太明确。我认为我们再次需要更多样本。
同样,结果似乎不太明确,但也许令人鼓舞。将 OSD 磁盘线程的数量增加到 4 可能会产生一些积极影响。
在 8 个 OSD 磁盘线程下,看起来除了积极影响之外,可能还有一些负面影响。我们可能需要更多样本才能确定。
将 OSD 操作线程的数量从 2(默认值)减少到 1 几乎总是对性能不利,除了在少数特定场景中。主要看起来,如果您使用 EXT4 并执行大量大读取,它可能会提供适度的性能提升。
我们之前已经讨论过,但为了回顾一下,增加 OSD 操作线程从 2 到 4 的情况似乎相反。性能(尤其是读取)随着更多 OSD 操作线程的增加而显著提高,除了 EXT4 和 XFS 上的大读取,性能会下降。
进一步增加 OSD 操作线程的数量会增加收益,也会增加损失。
鉴于我们通常对 256 个并发 4K XFS 读取结果表示怀疑,我愿意说减少队列中允许的字节数对性能不利,尤其是在使用大 IO 时。我认为令人惊讶的是,减少这些值并没有导致性能更大的下降。
最后,减少允许排队的 ops 数量肯定会导致小操作的性能下降。再次,我们看到 256 个并发 XFS 读取看起来像一个异常。对于大 IO,我们似乎在其他地方遇到了瓶颈。
结论 ¶
虽然我认为我们从这项练习中获得了一些有趣的结果,但我还是要重申,我们每个测试只有 3 个样本。这几乎肯定太少,无法真正辨别微妙的影响,并且可能存在假阳性和假阴性。除此之外,不同的硬件和软件配置可能会显示不同的行为。请以适当的谨慎对待所有这些结果。
话虽如此,我们在这套配置中了解了一些关于 Ceph 的知识。特别是,flusher 可能根本不值得使用(但似乎也有例外!),journal AIO 通常是一种优势,并且 OSD 操作线程的数量对读取性能有显著影响。在进行更多调查后,我们还可以在其他地方隔离性能提升。不幸的是,也缺少一些东西。测试 filestore 同步间隔的变化,以及更改 subdir 合并和拆分行为,将会很有趣。不幸的是,在设置和运行所有这些测试的过程中,我忘记包含这些了。好吧,下次再做吧。
我希望这篇文章对您有所帮助,并为人们调整自己的 Ceph 部署提供一个起点。如果您执行自己的性能测试并发现任何有趣的事情,请务必在我们的邮件列表中分享您的结果!Ceph 爱好者们,下次再见!































