万字长文 | CephFS性能基准测试与集群优化

本次测试的目的是通过使用 INTEL SSD PEYKX040T8 NVMe 驱动器从而在 Ceph 集群(特别是 CephFS)中实现最大的性能。同时为了保证本次测试的整体公平,故将会使用行业标准 IO500 基准测试来评估整个存储的性能。
备注:本次只使用了5节点的Ceph集群,因此无法正式提交结果到测试官网(至少需要10个节点),但是基准测试的分数已经足以进入最佳排名的前40名——2019 年的 10 节点存储系统

硬件准备

 
 
本次提供了以下的实验环境,该实验环境由连接到 100Gbps 网络的七台 Supermicro 服务器组成。其中六台服务器具有以下规格:
  • 型号:SSG-1029P-NES32R
  • 主板:X11DSF-E
  • CPU:2x Intel(R) Xeon(R) Gold 6252 CPU @ 2.10GHz(Turbo 频率高达 3.70 GHz),总共 96 个虚拟内核
  • RAM:8x Micron Technology 36ASF4G72PZ-2G9E2 32GB DDR4 DIMM,即总共 256 GB,配置为 2400 MT/s 但能够达到 2933 MT/s
  • 磁盘:8x INTEL SSDPEYKX040T8 NVMe 驱动器,每个 4TB
  • 其他磁盘:64GB SATA SSD
  • 板载网络:2x Intel Corporation Ethernet Controller 10G X550T [8086:1563]
  • PCIe 以太网卡:Mellanox Technologies MT27700 系列 [ConnectX-4] [15b3:1013] 带有两个 QSFP 端口,每个端口均能达到 100 Gbps
此外,还有一台配置与上面不同的服务器:
  • 型号:SSG-1029P-NMR36L
  • 主板:X11DSF-E
  • CPU:Intel(R) Xeon(R) Gold 6138 CPU @ 2.00GHz(Turbo 频率高达 3.70 GHz),总共 80 个虚拟内核
  • RAM:8x SK Hynix HMA84GR7CJR4N-WM 32GB DDR4 DIMM,即总共 256 GB,配置为 2666 MT/s 但能够达到 2933 MT/s
  • 磁盘:32 个 SAMSUNG MZ4LB3T8HALS NVMe 驱动器,每个 3.84 TB(未使用)
  • 其他磁盘:64GB SATA SSD
  • 板载网络:2x Intel Corporation Ethernet Controller 10G X550T [8086:1563]
  • PCIe 以太网卡:Mellanox Technologies MT27700 系列 [ConnectX-4] [15b3:1013] 带有两个 QSFP 端口,每个端口均能达到 100 Gbps
在所有服务器上,板载网络仅用于 IPMI 和管理。在每个 Mellanox 网卡的两个 100Gbe 端口中,只有一个使用直连网线连接到运行 Cumulus Linux 4.2 的 SSE-C3632S 交换机。

测试软件

 
 
在测试期间,SSG-1029P-NMR36L 服务器用作测试的管理服务器的同时也用作运行基准测试的主机。由于单个 100Gbps 链路很可能不足以展示出集群的性能,因此其中一台 SSG-1029P-NES32R 服务器也将会只用于客户端。在这两台服务器上,都安装了 Debian 10.5。内核是从 Debian 的“backports”存储库安装的,以便获得 cephfs 客户端的最新安装版本。
剩下的五台 SSG-1029P-NES32R 服务器用于 Ceph 集群(使用 Ceph 14.2.9),通过从管理节点网络来管理它们。内核版本为 4.19。

 

CEPH 集群

 
 
五台服务器参与了 Ceph 集群。在三台服务器上,较小的 SATA SSD 用于 MON 磁盘。在每个 NVMe 驱动器上,创建一个 OSD。在每台服务器上,都配置了一个 MDS(负责 cephfs 元数据的Ceph核心组件)。
通过并行元数据操作从而获取最大的性能,五个节点中,四个 MDS 服务器将被标记为active的,剩下的一个作为standby。请注意:对于生产 Ceph 集群,多个active的 MDS 服务器仍然可能会存在一些问题,所以请慎用!!!
在客户端节点上,使用内核 cephfs 客户端,在 /etc/fstab 中添加如下的内容,保证开机即可挂载:
:/ /mnt/cephfs ceph name=admin,_netdev 0 0
所有客户端和服务器都在一个二层的网络中,网络段为 10.10.49.0/24。同时每个节点都设置了ssh无密码登录,因为这是 OpenMPI 的要求,同时 IO500 基准测试使用 OpenMPI 以并行和分布式方式运行工作程序。
最初,我们打算将本次基准测试结果与另一个 Ceph 集群进行比较,后者每个节点有 6 个 OSD。因此,本次环境中,我们将每个主机上的两个 NVMe 分配到单独的设备类。然而,最终我们并没有这样做对比。尽管如此,大多数基准测试都是在每个节点只有 6 个 NVMe OSD 的情况下完成的。
Ceph存储被创建了三个存储池:cephfs_metadata(64 个 PG)、cephfs_data(512 个 PG)和 rbd_benchmark(也是 512 个 PG)。因此,虽然每个 OSD 的 PG 总数接近理想值,但 cephfs 在数据池中使用的 PG 比在这种情况下通常使用的 PG 少(即 1024)。理论上,太少的 PG 会导致数据不平衡(本次测试中,我们并不真正关心该问题),而太多的 PG 可能会造成性能问题。

IO500 基准测试

 
 
IO500 是 Virtual Institute for I/O 管理的存储基准测试软件。它测量不同场景下基于集群的文件系统的带宽和 IOPS 数据,并得出最终分数作为在所有测试阶段获得的性能指标的平均值。在每个阶段,执行“ior”工具(用于带宽测试)或“mdtest”工具(用于测试各种元数据操作的性能)的多个副本并将结果合并。还有一个基于并行“find”操作的阶段。作为实现细节,MPI 用于编排。
各个阶段的执行顺序是这样组织的,即基于 ior 和基于 mdtest 的阶段大多相互交错。

带宽测试阶段

带宽测试是使用“ior”工具完成的。有两个“difficulty”级别(easy 与 hard),对于每个级别,带宽分别针对写入和读取进行测量。基准测试结束时报告的带宽数字是所有四项测试的平均值。
默认情况下,两个difficulty级别的写入都需要 5 分钟,使用 POSIX 进行文件系统访问。在easy模式下,每个 ior 进程使用一个文件,并以 256 KiB 的传输大小顺序完成写入。在hard模式下,所有进程都写入同一文件的交错部分,使用47008 字节传输大小和“jumpy”线性访问(lseek() 对其他进程要写入的字节,写入 47008 字节,重复循环)。在这两种情况下,每个进程最后只执行一次 fsync() 调用,即基本上不受队列深度限制。
对于有多个客户端的 CephFS,hard I/O 模式确实很麻烦:每次写入都会导致一个RADOS对象的部分修改,该对象以前曾被另一个客户机修改,并且正在可能被另一个客户机同时修改,因此写入必须以原子方式执行。缺少fsync()调用(最后除外)也无济于事:fsync()保证数据访问稳定的存储,但此测试关心的是客户端之间的数据一致性,这是完全不同的事情,在兼容POSIX的文件系统中无法关闭。
因此,即使测试以GiB/s的速度显示结果,它也主要受到客户端和元数据服务器之间通信延迟的影响。
对于读取,easy和hard测试都使用与前面编写的相同的文件,以相同的方式访问它们,并验证文件中的数据是否与预期的签名匹配。

IOPS 测试阶段

几乎所有的 IOPS 测试都是使用“mdtest”工具完成的。与 ior 不同,mdtest 创建了大量文件并强调元数据操作。
就像带宽测试一样,测试有两个“difficulty”级别:easy和hard。对于每个difficulty,每个进程在“创建”阶段创建大量的测试文件(最多一百万个),然后在测试的“统计”阶段检查所有文件,然后在“删除”阶段删除所有文件. 在每个阶段结束时,都会执行“sync”命令并统计其运行时间。
hard测试与easy测试的不同之处在于以下几个方面:
  • easy测试中每个文件都是空的,在“创建”阶段写入 3901 个字节,然后在hard测试中读回;
  • 每个进程在简单的情况下获得一个唯一的工作目录,在hard测试中使用一个共享目录。

原始存储性能

 
 
fio 是最常用的基准测试工具,用于评估数据库应用程序中磁盘驱动器的原始性能。在后台,选择针对并行具体作业数量(从 1 到 16)运行此命令:

fio –filename=/dev/XXX –direct=1 –fsync=1 –rw=write –bs=4k –numjobs=YYY –iodepth=1 –runtime=60 –time_based –group_reporting –name=4k-sync-write-YYY

此基准测试作为 NVMe 驱动器的基础性能测试,并用于客观地比较它们在各种 BIOS 设置下的性能。
一个直接的发现是,不同的服务器拥有不同的性能,特别是在基准测试的单作业中,其IOPS介于78K和91K之间。16个作业的数据更加一致,仅显示548K(奇怪的是,在单作业基准测试中速度最快的服务器上)和566K IOPS之间的差异。
这种变化的原因最初被认为在于最初出现在服务器上的“CPU 配置”菜单中的 BIOS 设置不同。事实上,从高性能存储读取数据本身就是一个 CPU 密集型活动:在这种情况下,30% 的 CPU 被 fio 消耗,12% 被“ kworker/4:1H-kblockd”内核线程消耗。因此,让 CPU 达到尽可能高的时钟频率是合理的。
其实将 BIOS 的“高级电源管理配置”区域中的“电源技术”参数设置为“禁用”是错误的做法。它会将 CPU 频率锁定到最高非 Turbo 状态,即 2.10 GHz,并使 3.70 GHz 频率不可用。然后,fio 存储基准测试将只产生 66K IOPS,这太糟糕了。
此 BIOS 区域中的另一个选项决定是 BIOS 还是操作系统控制能效偏差。如果将控制权交给 BIOS,则有一个设置告诉它要做什么,而对于“Power Technology”参数的“Manual”设置,有很多选项可以微调 C-、P- 和T 状态。考虑到能效偏差控制以及对 C-、P-、和 CPU 的 T 状态,提供给操作系统。
在这两种情况下,NVMes 最初的基准测试为 89K-91K IOPS。不幸的是,后来的一些调优(不知道具体是什么)破坏了这一结果,最终结果再次是单线程的 84K 和 87K 写入 IOPS 之间的性能不一致。
好吧,至少从现在开始,所有服务器上的 BIOS 设置都变得一致 —— 请参见下表。这些设置背后的想法是尽可能多地控制操作系统而不是硬件或 BIOS 的 CPU 状态。我们还发现超线程、LLC Prefetch 和 Extended APIC 没有显着影响存储性能。因此,所有 CPU 功能都已启用。

网络性能

 
 
Mellanox 适配器无需任何调整即可达到 85+ Gbps 的吞吐量,但为此需要多个 TCP 流。将 net.core.rmem_max sysctl 设置为一个较大的值会进一步将可实现的吞吐量提高到 94 Gbit/s,但不会提高基准分数,所以没有进行操作。
为了体现出最佳的吞吐量,我们在两台主机上运行了 iperf(版本 2.0.12),如下所示:
在“server”上:iperf -s -p 9999
在“client”上:iperf -c 10.10.49.33 -p 9999,其中 10.10.49.33 是服务器 IP
对于单个 TCP 流,iperf 表示吞吐量为 39.5 Gbit/s。为了同时使用四个流,在客户端添加了“-P 4”参数,使吞吐量达到了 87.8 Gbit/s。
吞吐量是好的,但请记住,IOR500 的一些测试实际上是针对延迟的,还需要对其进行优化。对于延迟测试,我们使用了两个客观基准:
  • 在 RBD 设备上测量 4k 大小的写入 IOPS;
  • 只是ping另一个主机。
RBD 基准命令(比 IOR500 更激进)是:

fio –ioengine=rbd –pool=rbd_benchmark –rbdname=rbd0 –direct=1 –fsync=1 –rw=write –bs=4k –numjobs=1 –iodepth=1 –runtime=60 –time_based –group_reporting –name=4k-sync-write-1

没有任何调整,它仅达到 441 IOPS。是的,与原始存储相比减少了 200 多倍。
这里的限制因素之一是 CPU 时钟速度。Linux 内核中默认的“powersave”CPU 频率调节器将 CPU 时钟保持在较低水平,直到它发现工作负载太重。在这种情况下,它可能仍然“太低”(27%)并且不被视为提高频率的充分理由——这可以通过grep MHz /proc/cpuinfo | sort | tail -n 4在 fio 的命令来确认。
一旦在客户端和 Ceph OSD 节点 ( cpupower frequency-set -g performance)上将 CPU 频率调节器更改为“performance” ,情况就会改善:2369 IOPS。

 

优化网络延迟

 
 
正如已经提到的,IO500 基准测试对网络延迟很敏感。在没有任何调整的情况下,延迟(由“ping”命令报告)为 0.178 毫秒,这意味着在整个请求-响应周期中,仅浪费了 0.356 毫秒。ping 时间在这里加倍,因为有两个跃点延迟很重要:从客户端到主 OSD,以及从主 OSD 到辅助 OSD。上一节的 fio 基准测试中每秒有 2369 个这样的周期,因此每个周期平均持续 0.422 毫秒。因此,看起来减少延迟是非常重要的。
事实证明,CPU 负载足够低,其内核通过进入节能 C-states来降低使用。最深的这种状态是 C6,根据“ cpupower idle-info”,从它转换出来需要 0.133 毫秒。接下来的状态是 C1E、C1 和“CPUIDLE CORE POLL IDLE”(不节省任何电量),所有这些状态都需要不到 0.01 毫秒才能退出。
因此,下一个调整步骤是禁用 C6 状态。执行此操作的命令“ cpupower idle-set -D 11”实际上意味着“禁用所有需要超过 0.011 毫秒才能退出的空闲状态”。结果:ping 时间下降到 0.054 毫秒,但 fio 基准测试仅产生 2079 IOPS – 比以前更糟。这可能是因为不在 C6 中的内核会降低 CPU 可用的最大频率,而且,在这个“fio”基准测试中,达到可能的最高频率实际上更为重要。
尽管如此,正如我们稍后将看到的,禁用 C6 对整体 IO500 分数是有益的。

正式运行IO500基准测试

 
 
IO500 基准测试的源代码来自https://github.com/VI4IO/io500-app。本次使用的是“io500-isc20”分支(指向commit 46e0e53)的代码无法编译,因为“extern”变量使用不当。
幸运的是,该错误修复可从同一存储库的主分支中获得。因此,所有的基准测试都是通过 commit 20efd24 完成的。我们知道新的 IO500 版本已于 2020 年 10 月 7 日创建,但为了一致性,继续使用commit 46e0e53版本。
基准测试的主脚本名为“ io500.sh”。在文件的开始,有一个“ io500_mpiargs”变量,默认设置为“ -np 2”,表示“在本地运行两个进程”。为了测试分布式操作是否有效,将该变量更改为“ -np 4 -mca btl ^openib -mca btl_tcp_if_include 10.10.49.0/24 -oversubscribe -H 10.10.49.2,10.10.49.33 --allow-run-as-root”,以便在两个客户端节点中的每个节点上启动两个进程。
-mca btl ^openib”参数从 OpenMPI 尝试的传输列表中排除 InfiniBand。这是必须的,因为 Mellanox 网卡理论上支持 InfiniBand,但是在这个集群中还没有配置 InfiniBand。基准测试不需要在 worker 之间发送大量数据,因此回退到 TCP 是可以接受的。
-mca btl_tcp_if_include 10.10.49.0/24”参数指定在 OpenMPI 基准测试期间要使用的网络。如果没有这个参数,OpenMPI 有时会选择其中一台主机上的 docker0 接口作为主要的,并尝试从其他节点连接到 172.17.0.1,这会失败。
基准测试的所有阶段运行两次,一次使用 shell 脚本进行协调,一次使用 C 程序。这两个“驱动程序”以略有不同的格式打印结果,但从数量上来说,没有太大区别。因此,下面仅提及基于 shell 的驱动程序报告的基准分数。
基准测试还需要一个配置文件。在代码的配置中可以找到配置模板config-full.ini 。但是,配置只需要几个选项:IO500 将写入数据的目录、删除缓存的可选脚本以及用于调试的缩短基准测试持续时间的方法。在找到最佳选项之前,每次都执行完整的基准测试是没有意义的,因此,stonewall-time设置为 30 秒。
[global]`
`datadir = /mnt/cephfs/default`
`drop-caches = TRUE`
`drop-caches-cmd = /usr/local/bin/drop_caches
[debug]`
`stonewall-time = 30
/usr/local/bin/drop_caches脚本的内容是:

#!/bin/sh`
`echo 3 > /proc/sys/vm/drop_caches`
`ssh 10.10.49.33 echo 3 “>” /proc/sys/vm/drop_caches

 

 

是否禁用 C6

 
 
基准测试的 30 秒版本运行正常,并在完全未调整(操作系统调整除外)集群上生成此报告,启用 C6 空闲状态(这是默认设置):

[RESULT] BW   phase 1           ior_easy_write               6.021 GiB/s : time 35.83 seconds
[RESULT] BW   phase 2           ior_hard_write               0.068 GiB/s : time 43.69 seconds
[RESULT] BW   phase 3             ior_easy_read               5.144 GiB/s : time 46.86 seconds
[RESULT] BW   phase 4             ior_hard_read               0.219 GiB/s : time 13.52 seconds
[RESULT] IOPS phase 1         mdtest_easy_write               10.334 kiops : time 32.09 seconds
[RESULT] IOPS phase 2         mdtest_hard_write               5.509 kiops : time 45.68 seconds
[RESULT] IOPS phase 3                     find             123.770 kiops : time   4.71 seconds
[RESULT] IOPS phase 4         mdtest_easy_stat               31.086 kiops : time 10.67 seconds
[RESULT] IOPS phase 5         mdtest_hard_stat               30.733 kiops : time   8.19 seconds
[RESULT] IOPS phase 6       mdtest_easy_delete               4.868 kiops : time 68.13 seconds
[RESULT] IOPS phase 7         mdtest_hard_read               5.734 kiops : time 43.88 seconds
[RESULT] IOPS phase 8       mdtest_hard_delete               3.443 kiops : time 75.07 seconds
[SCORE] Bandwidth 0.822726 GiB/s : IOPS 12.6286 kiops : TOTAL 3.22333

禁用 C6 后,“ior_hard_write”测试得到显着提升,但大多数其他测试得到更差的结果。尽管如此,由于带宽和 IOPS,总体得分略有提高:

[RESULT] BW   phase 1           ior_easy_write               5.608 GiB/s : time 35.97 seconds
[RESULT] BW   phase 2           ior_hard_write               0.101 GiB/s : time 36.17 seconds
[RESULT] BW   phase 3             ior_easy_read               4.384 GiB/s : time 47.43 seconds
[RESULT] BW   phase 4             ior_hard_read               0.223 GiB/s : time 16.30 seconds
[RESULT] IOPS phase 1         mdtest_easy_write               10.614 kiops : time 31.73 seconds
[RESULT] IOPS phase 2         mdtest_hard_write               4.884 kiops : time 43.06 seconds
[RESULT] IOPS phase 3                     find             157.530 kiops : time   3.47 seconds
[RESULT] IOPS phase 4         mdtest_easy_stat               26.136 kiops : time 12.88 seconds
[RESULT] IOPS phase 5         mdtest_hard_stat               30.081 kiops : time   6.99 seconds
[RESULT] IOPS phase 6       mdtest_easy_delete               5.122 kiops : time 65.74 seconds
[RESULT] IOPS phase 7         mdtest_hard_read               7.689 kiops : time 27.35 seconds
[RESULT] IOPS phase 8       mdtest_hard_delete               3.382 kiops : time 64.18 seconds
[SCORE] Bandwidth 0.86169 GiB/s : IOPS 13.0773 kiops : TOTAL 3.35687

这并不奇怪:ior_easy_write 步骤在“ior”进程消耗 100% CPU 时遇到瓶颈,并且 C6 中零内核的可用时钟速度低于其他情况。为了避免这种 CPU 内核饱和现象,我们进行了一项单独的测试,每个主机有 4 个进程(而不是 2 个)。
启用 C6 的结果:

[RESULT] BW   phase 1           ior_easy_write               7.058 GiB/s : time 38.88 seconds
[RESULT] BW   phase 2           ior_hard_write               0.074 GiB/s : time 39.40 seconds
[RESULT] BW   phase 3             ior_easy_read               7.933 GiB/s : time 34.78 seconds
[RESULT] BW   phase 4             ior_hard_read               0.172 GiB/s : time 16.97 seconds
[RESULT] IOPS phase 1         mdtest_easy_write               11.416 kiops : time 34.38 seconds
[RESULT] IOPS phase 2         mdtest_hard_write               5.492 kiops : time 43.10 seconds
[RESULT] IOPS phase 3                     find             169.540 kiops : time   3.71 seconds
[RESULT] IOPS phase 4         mdtest_easy_stat               41.339 kiops : time   9.50 seconds
[RESULT] IOPS phase 5         mdtest_hard_stat               47.345 kiops : time   5.00 seconds
[RESULT] IOPS phase 6       mdtest_easy_delete               8.997 kiops : time 43.63 seconds
[RESULT] IOPS phase 7         mdtest_hard_read               9.854 kiops : time 24.02 seconds
[RESULT] IOPS phase 8       mdtest_hard_delete               3.213 kiops : time 75.66 seconds
[SCORE] Bandwidth 0.919144 GiB/s : IOPS 16.6569 kiops : TOTAL 3.91281

禁用 C6 的结果:

[RESULT] BW phase 1 ior_easy_write 5.983 GiB/s : time 39.96 seconds
[RESULT] BW phase 2 ior_hard_write 0.100 GiB/s : time 37.91 seconds
[RESULT] BW phase 3 ior_easy_read 7.413 GiB/s : time 31.65 seconds
[RESULT] BW phase 4 ior_hard_read 0.232 GiB/s : time 16.26 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 9.793 kiops : time 35.57 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 4.845 kiops : time 36.70 seconds
[RESULT] IOPS phase 3 find 147.360 kiops : time 3.57 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 50.768 kiops : time 6.86 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 50.125 kiops : time 3.55 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 7.763 kiops : time 44.87 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 13.135 kiops : time 13.54 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 3.699 kiops : time 50.04 seconds
[SCORE] Bandwidth 1.00608 GiB/s : IOPS 16.918 kiops : TOTAL 4.12563

结论保持不变:禁用 C6 的建议并不普遍。它有助于基准测试的一些“hard”测试方面,但会伤害其他方面。尽管如此,它在两种情况下都略微提高了总体得分,因此在其余基准测试中禁用了 C6。
 

调整 MDS

 
 
测试的简单版本运行顺利。但是,在使用默认300秒stonewall计时器的完整基准测试期间(特别是在“mdtest_hard_write”阶段),观察到一些MDS健康警告:
  • 修剪后的 MDS
  • MDS 报告超大缓存
  • 客户端无法响应缓存压力
最终分数也较低,特别是由于基于 mdtest 的“stat”测试:

[RESULT] BW phase 1 ior_easy_write 5.442 GiB/s : time 314.02 seconds
[RESULT] BW phase 2 ior_hard_write 0.099 GiB/s : time 363.64 seconds
[RESULT] BW phase 3 ior_easy_read 7.838 GiB/s : time 215.95 seconds
[RESULT] BW phase 4 ior_hard_read 0.231 GiB/s : time 155.15 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 11.423 kiops : time 431.68 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 5.518 kiops : time 328.02 seconds
[RESULT] IOPS phase 3 find 120.880 kiops : time 55.76 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 0.866 kiops : time 5694.08 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 2.072 kiops : time 873.55 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 1.972 kiops : time 2500.54 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 1.925 kiops : time 940.46 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 3.304 kiops : time 549.71 seconds
[SCORE] Bandwidth 0.99279 GiB/s : IOPS 4.51093 kiops : TOTAL 2.11622

显然,MDS 被基准测试创建的元数据负载压得喘不过气来。因此,已决定将“mds 缓存内存限制”Ceph 参数从默认值 1 GB 增加到 12884901888 (12 GB)。确切值选择为健康警告中报告的峰值缓存大小的 2 倍。这几乎恢复了基准测试的简单版本中看到的分数:

[RESULT] BW phase 1 ior_easy_write 5.274 GiB/s : time 322.44 seconds
[RESULT] BW phase 2 ior_hard_write 0.105 GiB/s : time 348.94 seconds
[RESULT] BW phase 3 ior_easy_read 7.738 GiB/s : time 217.92 seconds
[RESULT] BW phase 4 ior_hard_read 0.239 GiB/s : time 153.87 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 10.692 kiops : time 429.36 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 5.318 kiops : time 324.34 seconds
[RESULT] IOPS phase 3 find 211.550 kiops : time 29.85 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 44.120 kiops : time 104.05 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 29.881 kiops : time 57.72 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 6.993 kiops : time 656.42 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 9.773 kiops : time 176.46 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 2.949 kiops : time 586.78 seconds
[SCORE] Bandwidth 1.0071 GiB/s : IOPS 15.4197 kiops : TOTAL 3.94071

消除客户端瓶颈

 
 
将每台主机的 worker 数量增加到 4 以上并没有导致 IO500 分数的任何提高,并且没有增加 OSD 的 CPU 使用率。在这种情况下,“ior”阶段可能的瓶颈是单个客户端“kworker/u194:0+flush-ceph-1”线程,它消耗了 70-80% 的 CPU。这个线程是单一的,因为一台主机上的所有工作进程只使用一个 cephfs 挂载。
很明显,解决方案是多次挂载 cephfs,这样它们就不会共享单个“kworker/u194:0+flush-ceph-1”线程。此挂载选项称为“noshare”。以下是“mount.ceph”手册页中的描述:
创建一个新的客户端实例,而不是共享安装相同集群的客户端的现有实例。
但是,IO500 基准测试并非旨在通过多个挂载点访问存储。为了规避这个限制,在每个客户端主机上创建了多个 LXC 容器,每个容器都有一个单独的 cephfs 挂载。对于网络,使用了“macvlan”后端,以便将每个容器直接暴露给 100Gbps 网络,而不会因路由而产生额外开销。在每个主机本身上,添加了一个单独的 macvlan 接口,以便容器可以与主机进行通信。这是的相关部分/etc/network/interfaces

iface enp216s0f0np0 inet manual
up /sbin/ip link add link enp216s0f0np0 name enp216s0f0mv0 type macvlan mode bridge

allow-hotplug enp216s0f0mv0
iface enp216s0f0mv0 inet static
address 10.10.49.2/24

无法从容器内刷新 Linux 缓存,因此,必须将容器中的“ /usr/local/bin/drop_caches”脚本修改如下:

#!/bin/sh

ssh 10.10.49.2 echo 3 “>” /proc/sys/vm/drop_caches
ssh 10.10.49.33 echo 3 “>” /proc/sys/vm/drop_caches

也就是说,它将通过 ssh 连接到两个客户端主机,并以通常的方式在那里刷新缓存。
每个主机四个容器,每个容器三个或四个工作进程,获得了最佳结果。规定这一点的 mpirun 参数是:“ -np 32 -oversubscribe -H 10.10.49.3,10.10.49.4,... --allow-run-as-root”。事实上,使用 30 秒的stonewall计时器,基准测试的某些阶段,例如“mdtest_hard_stat”,变得太短(少于 4 秒),结果不可靠和可重复。因此,从现在开始,基准测试使用 300 秒的stonewall计时器运行。
以下是每个容器三个进程的基准测试结果:

[RESULT] BW phase 1 ior_easy_write 11.307 GiB/s : time 372.62 seconds
[RESULT] BW phase 2 ior_hard_write 0.383 GiB/s : time 352.78 seconds
[RESULT] BW phase 3 ior_easy_read 15.144 GiB/s : time 277.94 seconds
[RESULT] BW phase 4 ior_hard_read 0.931 GiB/s : time 145.10 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 14.032 kiops : time 472.96 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 9.891 kiops : time 313.09 seconds
[RESULT] IOPS phase 3 find 231.190 kiops : time 42.10 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 55.821 kiops : time 118.89 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 79.348 kiops : time 39.03 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 9.597 kiops : time 691.54 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 16.702 kiops : time 185.42 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 8.507 kiops : time 366.75 seconds
[SCORE] Bandwidth 2.79532 GiB/s : IOPS 25.7583 kiops : TOTAL 8.48544

每个容器有四个进程,一些基准测试结果(特别是“mdtest_hard_read”)看起来更好,但其他看起来更糟,集群肯定感觉过载(报告的中位延迟接近 0.5 秒)。因此,这里每个容器使用三个还是四个工作进程更好是有争议的。以下是基准测试结果:

[RESULT] BW phase 1 ior_easy_write 11.459 GiB/s : time 350.88 seconds
[RESULT] BW phase 2 ior_hard_write 0.373 GiB/s : time 354.69 seconds
[RESULT] BW phase 3 ior_easy_read 16.011 GiB/s : time 250.28 seconds
[RESULT] BW phase 4 ior_hard_read 0.930 GiB/s : time 142.02 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 15.894 kiops : time 441.59 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 10.690 kiops : time 313.34 seconds
[RESULT] IOPS phase 3 find 174.440 kiops : time 59.44 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 55.944 kiops : time 125.46 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 66.896 kiops : time 50.07 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 9.371 kiops : time 748.99 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 19.120 kiops : time 175.18 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 9.948 kiops : time 340.54 seconds
[SCORE] Bandwidth 2.82402 GiB/s : IOPS 25.8226 kiops : TOTAL 8.53953

这是一个相当严重的负载:在 Ceph 集群中,每个 OSD cpu 消耗在“ior_easy_write”阶段达到了约 400% 的峰值。这也是第一次观察到总客户端吞吐量超过单个 100Gbps 链路的能力。

 

 

扩展 MDS

 
 
前面几节执行的 MDS 调优显然已经完成——在“mdtest_easy_delete”和“mdtest_hard_delete”阶段,每个活跃的 ceph-mds 进程的 CPU 使用率都接近 100%。换句话说,只有四个活动的 MDS,这与集群在这些元数据密集型基准测试中的运行速度差不多。
在官方Ceph的文档(https://docs.ceph.com/en/nautilus/cephfs/add-remove-mds/)每个节点提到多个MDS作为MDS瓶颈可能的解决方案:
即使单个 MDS 守护进程无法充分利用硬件,也可能希望稍后在同一节点上启动更多活动的 MDS 守护进程以充分利用可用内核和内存。此外,对于集群上的工作负载,在同一节点上使用多个活动 MDS 而不是过度配置单个 MDS 会提高性能,这可能会变得很明显。
事实上,我们发现即使每个主机有两个 MDS 也不足以避免瓶颈。所以我们总共部署了 20 个 MDS——每台主机四个,并使其中的 16 个处于活动状态。这些都需要我们手工进行操作。
在每台主机上,必须(暂时)将管理密钥保存为/etc/ceph/ceph.client.admin.keyring. 之后,执行以下命令,替换正确的主机名而不是依然是croit-host-25作为新的 MDS 的名称。

# sudo -u ceph -s /bin/bash
$ mkdir /var/lib/ceph/mds/ceph-croit-host-25a
$ ceph-authtool –create-keyring /var/lib/ceph/mds/ceph-croit-host-25a/keyring –gen-key -n mds.croit-host-25a
$ ceph auth add mds.croit-host-25a osd “allow rwx” mds “allow” mon “allow profile mds” -i /var/lib/ceph/mds/ceph-croit-host-25a/keyring
$ cat /var/lib/ceph/mds/ceph-croit-host-25a/keyring

因此,每个主机有三个新的有效密钥,每个未来的 MDS 一个。在 croit 容器中,必须将它们插入到数据库中——这是 UI 不允许的。

$ mysql croit
MariaDB [croit]> insert into service values(NULL, 5, ‘mds’, NULL, ‘croit-host-25a’, ‘[mds.croit-host-25a]\nkey = AQA9jn1f7oyKDRAACIJ0Kj8e8D1C4z4p8hU2WA==\n’, ‘enabled’, NOW(), NULL);
[and the remaining keys]

然后 croit 在每个集群节点上启动额外的 MDS 守护进程,这些额外的守护进程甚至在滚动重启后仍然存在。
最后,要使它们处于活动状态,需要以下命令:
ceph fs set cephfs max_mds 16
正如预期的那样,基准测试结果有所改善(每个容器有四个工作进程):

[RESULT] BW phase 1 ior_easy_write 13.829 GiB/s : time 325.93 seconds
[RESULT] BW phase 2 ior_hard_write 0.373 GiB/s : time 365.60 seconds
[RESULT] BW phase 3 ior_easy_read 16.204 GiB/s : time 278.80 seconds
[RESULT] BW phase 4 ior_hard_read 0.920 GiB/s : time 148.24 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 25.154 kiops : time 594.93 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 13.227 kiops : time 316.73 seconds
[RESULT] IOPS phase 3 find 391.840 kiops : time 48.88 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 153.305 kiops : time 97.61 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 93.870 kiops : time 44.63 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 20.886 kiops : time 716.49 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 28.205 kiops : time 148.53 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 10.496 kiops : time 401.73 seconds
[SCORE] Bandwidth 2.96175 GiB/s : IOPS 42.959 kiops : TOTAL 11.2798

看起来每个主机四个 MDS 确实是集群可以使用的最大值。我们不再看到它们长时间消耗 100% CPU 的时期。现在的典型数字是 120% + 80% + 60% + 20%。

 

没有效果的“优化”

 
 

额外的 OSD参数

理论上,可以对 OSD 进行相同类型的额外配置。事实上,在过去,通常建议为每个 SSD 配置多个 (2-4) OSD。现代在Ceph 提供了不同的解决方案:由“osd op num shards”和“osd op num threads per shard”参数控制的内置 OSD 分片。我们尝试了这两个选项,但发现它们都没有提高整体基准分数。唯一持续改进的指标是“mdtest_hard_stat”,但分数被调整该参数带来的其他影响所拉低。

调整 OSD 内存目标

Bluestore OSD 使用自己的缓存,而不是 Linux 页面缓存,来用于存储可能再次需要的副本数据。通常,将“osd memory target”可调参数从其默认值(本次为 3 GB)增加应该可以提高性能,因为这样 OSD 将从缓存中提供更多服务,而从磁盘中提供更少服务。但是这个特定的基准测试旨在使缓存尽可能无效:它仅在将数据全部写入后才读取数据。因此,我们已经通过实验证实,增加 OSD 内存目标对最终分数没有影响。

调整网络 MTU

到目前为止,所有基准测试都是使用默认 MTU (1500) 和套接字缓冲区大小进行的。但是,通常建议在高速网络上将 MTU 设置为 9000,而我们的 100Gbps 网络当然可以。此外,建议增加套接字缓冲区大小的限制和默认值。
我们首先将 OSD 节点和客户端上的 MTU 增加到 9000。增加MTU后,“ior_easy_write”阶段的性能确实提升到了15.163 GiB/s。但是,我们无法完成基准测试,因为“MDS behind on trimming”和“MDS slow ops”健康警告,以及由此导致的客户端黑名单。然后一个 MDS 进入只读模式,这通常发生在文件系统以某种方式损坏时。
我们继续使用 iperf 重新测试网络吞吐量。它比以前更糟。使用 MTU 1500 和默认套接字缓冲区大小,我们能够使用四个并发连接达到 87 Gbit/s。使用 MTU 9000,我们只有 77 Gbit/s。显然,网卡在发送时可以高效地进行 TCP 分段卸载,而在接收时正好相反,只有 MTU = 1500。
MTU 调整被撤销,不幸的是,文件系统因此损坏而需要重新创建。

 

调整 TCP 参数

 
 
我们尝试使用以下 sysctls 允许 Linux 内核在 OSD 和客户端上将 TCP 缓冲区自动调整为更大的值:

net.core.rmem_max=33554432
net.core.wmem_max=33554432
net.ipv4.tcp_rmem=4096 65536 33554432
net.ipv4.tcp_wmem=4096 131072 33554432

结果再次降低了分数:

[RESULT] BW phase 1 ior_easy_write 12.905 GiB/s : time 351.74 seconds
[RESULT] BW phase 2 ior_hard_write 0.382 GiB/s : time 354.09 seconds
[RESULT] BW phase 3 ior_easy_read 16.459 GiB/s : time 275.82 seconds
[RESULT] BW phase 4 ior_hard_read 0.926 GiB/s : time 145.97 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 24.030 kiops : time 637.19 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 12.289 kiops : time 331.97 seconds
[RESULT] IOPS phase 3 find 252.270 kiops : time 76.87 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 95.420 kiops : time 160.47 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 97.223 kiops : time 41.96 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 16.660 kiops : time 919.06 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 15.179 kiops : time 268.76 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 8.265 kiops : time 497.80 seconds
[SCORE] Bandwidth 2.9435 GiB/s : IOPS 33.1105 kiops : TOTAL 9.87222

就像任何其他错误的调整尝试一样,这些设置都被撤消了。

 

增加 MDS 日志最大段

 
 
为了防止我们在 MTU = 9000 时看到的“MDSs behind on trimming”健康警告,我们尝试将“mds log max segment”选项设置为 1280(这大约是警告中 num_segments 峰值的 2 倍)。这严重降低了 mdtest 的性能,因此也已被撤销。下面是 MTU = 1500 的基准报告:

[RESULT] BW phase 1 ior_easy_write 12.733 GiB/s : time 335.69 seconds
[RESULT] BW phase 2 ior_hard_write 0.374 GiB/s : time 348.14 seconds
[RESULT] BW phase 3 ior_easy_read 17.026 GiB/s : time 256.40 seconds
[RESULT] BW phase 4 ior_hard_read 0.932 GiB/s : time 139.58 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 26.622 kiops : time 575.94 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 12.984 kiops : time 328.36 seconds
[RESULT] IOPS phase 3 find 341.760 kiops : time 57.34 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 107.865 kiops : time 142.15 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 103.463 kiops : time 41.21 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 14.181 kiops : time 1081.19 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 15.855 kiops : time 268.90 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 8.702 kiops : time 493.00 seconds
[SCORE] Bandwidth 2.94821 GiB/s : IOPS 35.5994 kiops : TOTAL 10.2447

 

 

消除 KSWAPD 瓶颈

 
 
在基准测试的 IOR 阶段,可以看到“kswapd[01]”内核线程占用了客户端 100% 的 CPU。“kswapd”线程,每个 NUMA 节点一个,让 Linux 内存子系统对空闲页面的数量感到满意。特别是,他们试图回收页面缓存。因此,看起来这些基准测试阶段会产生过多的脏页或缓存页。基准测试提供了一个选项(“ posix.odirect = True”在[global]配置文件的部分,或在特定阶段的部分)通过O_DIRECT标志绕过页面缓存。然而,它实际上使每个 IOR 阶段的得分变得更糟,即与预期效果完全相反。
为了让更多的 CPU 时间(实际上,更多的 CPU)可用于页面缓存回收任务,使用“ numa=fake=8”内核命令行参数在两个客户端上创建了一组假 NUMA 节点。结果:这对 IOR 阶段没有帮助(所以 kswapd 不是瓶颈),但伤害了“find“和大多数基于 mdtest 的阶段。

[RESULT] BW phase 1 ior_easy_write 13.674 GiB/s : time 342.55 seconds
[RESULT] BW phase 2 ior_hard_write 0.381 GiB/s : time 355.32 seconds
[RESULT] BW phase 3 ior_easy_read 16.784 GiB/s : time 278.14 seconds
[RESULT] BW phase 4 ior_hard_read 0.925 GiB/s : time 146.32 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 23.718 kiops : time 578.62 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 11.818 kiops : time 326.18 seconds
[RESULT] IOPS phase 3 find 261.800 kiops : time 67.14 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 101.016 kiops : time 135.85 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 69.404 kiops : time 55.54 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 18.087 kiops : time 758.75 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 26.474 kiops : time 145.60 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 9.933 kiops : time 390.60 seconds
[SCORE] Bandwidth 2.99932 GiB/s : IOPS 35.3655 kiops : TOTAL 10.2991

因此,这也必须撤消。

 

什么也不做

 
 
什么都不做不应该影响环境。它也不应该有帮助,因此它是测试基准测试结果再现性的好方法。因此,在取消所有糟糕的优化后,我们有望重新获得之前看到的高分。让我们检查:

[RESULT] BW phase 1 ior_easy_write 13.359 GiB/s : time 455.21 seconds
[RESULT] BW phase 2 ior_hard_write 0.376 GiB/s : time 338.87 seconds
[RESULT] BW phase 3 ior_easy_read 16.634 GiB/s : time 366.70 seconds
[RESULT] BW phase 4 ior_hard_read 0.934 GiB/s : time 136.30 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 24.508 kiops : time 606.63 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 12.352 kiops : time 329.28 seconds
[RESULT] IOPS phase 3 find 288.930 kiops : time 65.53 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 109.363 kiops : time 135.95 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 98.175 kiops : time 41.43 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 18.731 kiops : time 793.72 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 26.504 kiops : time 153.46 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 10.293 kiops : time 397.73 seconds
[SCORE] Bandwidth 2.9722 GiB/s : IOPS 38.4718 kiops : TOTAL 10.6933

不一定最佳,但至少仍然比迄今为止讨论的所有误导优化尝试要好。所以,结论还是成立的。

扩容集群进行基准测试

 
 
请记住,我们在每个节点上设置了两个 NVME 驱动器,因此它们不参与基准测试。现在是时候把它们加回来了,因此,也许可以证明底层存储至少是瓶颈的一部分。

[RESULT] BW phase 1 ior_easy_write 12.982 GiB/s : time 391.63 seconds
[RESULT] BW phase 2 ior_hard_write 0.383 GiB/s : time 349.43 seconds
[RESULT] BW phase 3 ior_easy_read 16.991 GiB/s : time 304.82 seconds
[RESULT] BW phase 4 ior_hard_read 0.923 GiB/s : time 145.14 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 23.997 kiops : time 600.49 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 11.300 kiops : time 335.35 seconds
[RESULT] IOPS phase 3 find 345.570 kiops : time 52.66 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 113.218 kiops : time 127.28 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 99.407 kiops : time 38.12 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 19.261 kiops : time 748.14 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 28.119 kiops : time 134.76 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 10.485 kiops : time 364.02 seconds
[SCORE] Bandwidth 2.97168 GiB/s : IOPS 39.5523 kiops : TOTAL 10.8414

嗯,改进是微不足道的。另一方面,每个节点只有四个 OSD(即使我们战略性地选择它们,使它们的 NVMe 驱动器的 NUMA 节点与网卡的 NUMA 节点匹配),分数略有降低,因为 NVME 驱动器在 IOR 期间过载阶段:

[RESULT] BW phase 1 ior_easy_write 10.775 GiB/s : time 344.10 seconds
[RESULT] BW phase 2 ior_hard_write 0.374 GiB/s : time 359.87 seconds
[RESULT] BW phase 3 ior_easy_read 16.431 GiB/s : time 224.47 seconds
[RESULT] BW phase 4 ior_hard_read 0.925 GiB/s : time 145.59 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 25.422 kiops : time 641.73 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 12.040 kiops : time 324.63 seconds
[RESULT] IOPS phase 3 find 374.070 kiops : time 54.06 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 101.753 kiops : time 160.33 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 78.571 kiops : time 49.74 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 19.180 kiops : time 850.58 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 25.747 kiops : time 151.80 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 9.840 kiops : time 399.77 seconds
[SCORE] Bandwidth 2.79783 GiB/s : IOPS 38.1085 kiops : TOTAL 10.3257

因此,虽然存储量确实会影响性能,但影响很小。这是对真正瓶颈在别处的理论的一个论点。

更改 PG 的数量

 
 
正如我们已经提到的,创建 cephfs_data 池时使用的 PG (512) 比通常为这种大小的集群推荐的 (1024) 少。只是为了测试,我们将池的大小调整为 1024 个 PG。结果是分数非常轻微的下降:

[RESULT] BW phase 1 ior_easy_write 13.373 GiB/s : time 349.24 seconds
[RESULT] BW phase 2 ior_hard_write 0.376 GiB/s : time 361.25 seconds
[RESULT] BW phase 3 ior_easy_read 16.557 GiB/s : time 282.76 seconds
[RESULT] BW phase 4 ior_hard_read 0.912 GiB/s : time 148.76 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 20.689 kiops : time 793.92 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 11.058 kiops : time 344.35 seconds
[RESULT] IOPS phase 3 find 333.310 kiops : time 60.70 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 143.516 kiops : time 114.45 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 104.899 kiops : time 36.30 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 19.006 kiops : time 864.21 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 23.765 kiops : time 160.23 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 9.188 kiops : time 417.02 seconds
[SCORE] Bandwidth 2.95176 GiB/s : IOPS 38.4369 kiops : TOTAL 10.6516

这是每个节点有 8 个 OSD。

 

 

升级至Octopus版本

 
 
作为测试的最后一部分,我们安装了 croit 容器的night版本,并使用它将集群升级到 Ceph Octopus(版本 15.2.5)。这确实导致了一些差异:

[RESULT] BW phase 1 ior_easy_write 13.656 GiB/s : time 347.14 seconds
[RESULT] BW phase 2 ior_hard_write 0.332 GiB/s : time 356.28 seconds
[RESULT] BW phase 3 ior_easy_read 16.740 GiB/s : time 282.90 seconds
[RESULT] BW phase 4 ior_hard_read 0.790 GiB/s : time 149.64 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 26.457 kiops : time 436.90 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 12.974 kiops : time 335.61 seconds
[RESULT] IOPS phase 3 find 413.790 kiops : time 38.46 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 117.764 kiops : time 98.16 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 90.990 kiops : time 47.85 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 20.957 kiops : time 551.56 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 25.622 kiops : time 169.94 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 9.646 kiops : time 453.91 seconds
[SCORE] Bandwidth 2.7817 GiB/s : IOPS 40.9341 kiops : TOTAL 10.6708

“hard”测试中的带宽更少,“find”和“mdtest_easy_write”中的 IOPS 更高,但最终得分相同。
我们还在 Ceph Octopus 上重新测试了 MTU 9000。这一次,对“ior_easy_write”阶段的积极影响得到了验证,但总体得分有所下降:

[RESULT] BW phase 1 ior_easy_write 15.608 GiB/s : time 343.82 seconds
[RESULT] BW phase 2 ior_hard_write 0.333 GiB/s : time 356.22 seconds
[RESULT] BW phase 3 ior_easy_read 14.657 GiB/s : time 368.92 seconds
[RESULT] BW phase 4 ior_hard_read 0.783 GiB/s : time 151.37 seconds
[RESULT] IOPS phase 1 mdtest_easy_write 25.044 kiops : time 557.53 seconds
[RESULT] IOPS phase 2 mdtest_hard_write 11.682 kiops : time 326.95 seconds
[RESULT] IOPS phase 3 find 394.750 kiops : time 45.04 seconds
[RESULT] IOPS phase 4 mdtest_easy_stat 121.566 kiops : time 114.85 seconds
[RESULT] IOPS phase 5 mdtest_hard_stat 91.986 kiops : time 41.52 seconds
[RESULT] IOPS phase 6 mdtest_easy_delete 19.932 kiops : time 700.49 seconds
[RESULT] IOPS phase 7 mdtest_hard_read 21.683 kiops : time 176.15 seconds
[RESULT] IOPS phase 8 mdtest_hard_delete 8.189 kiops : time 471.37 seconds
[SCORE] Bandwidth 2.77798 GiB/s : IOPS 38.2382 kiops : TOTAL 10.3065

因此,我们可以得出结论,11.27 是我们在该集群的 IO500 基准测试中可以获得的最高分,而 10.84 是我们可以重复获得的最高分。

剩余瓶颈

 
 
基准报告是不完整的,没有解释为什么测试不能更快。也就是说,没有确定无法消除的瓶颈。
“ior_easy_write”阶段是独一无二的,因为它在多个因素上成为瓶颈或几乎成为瓶颈:OSD 较少,这将是磁盘性能,而 MTU 1500,这是网络吞吐量(OSD 上为 80 Gbit/s)。此外,在客户端上,kswapd 对 CPU 的使用可能是一个问题(但我们无法确认它是否真的是一个问题)。
禁用 C6 会对几个阶段(“ior_hard_write”、“ior_hard_read”、“mdtest_hard_write”)产生积极影响,即它们对网络延迟敏感。甚至更多(“mdtest_easy_write”、“mdtest_easy_stat”、“mdtest_hard_stat”、“mdtest_easy_delete”、“mdtest_hard_read”)导致 MDS 的 CPU 使用率飙升至 100%,因为 MDS 主要是单线程的,这明显是瓶颈。
对于两个阶段(“find”和“mdtest_hard_delete”),我们无法确定确切的瓶颈,但是通过增加额外的MDS节点,从而带来了比较好的测试结果。

最后的话:Ceph 有很多可调参数。但是,本次环境中只需要其中之一(mds 缓存内存限制)。其余的优化都是关于调整 Linux 操作系统、规划集群和创建足够多的客户端。而不必要的调优化往往带来的可能是反面的影响而非正面的影响。

参考文章:
  1. https://croit.io/blog/ceph-performance-test-and-optimization
  2. https://docs.ceph.com