Ceph OSD CPU 性能優(yōu)化 之一
介紹
通常情況下,Ceph 的整體性能還是不錯的,大量的場景優(yōu)化為 Ceph 集群提供了可靠的性能保障。但是,很少有人知道 Ceph 當前并沒有充分發(fā)揮出硬件的性能,也就說集群的性能與硬件的性能并不是呈線性增長的。
目前,我們正在進行多種方法來優(yōu)化 Ceph 的數(shù)據(jù)路徑,但現(xiàn)實情況是 Ceph 一直都是需要相當多的 CPU 才能充分發(fā)揮出比如像 NVMe 這樣高速存儲設備的性能。
之前,一位用戶向我們提出了對低 CPU Core 下性能的擔憂。我們給出的建議是,在使用 NVMe 磁盤時,可以為每個 OSD 分配 2 個 CPU Core 。我們并沒有去解釋原因。最終,用戶購買了相應的硬件服務器,且服務器只插了一半的 NVMe 磁盤(即每個 OSD 有 4 個CPU Core 可用)。正常情況下,該配置的性能是可以接受的。但用戶依然比較關心當服務器插滿所有的 NVMe 磁盤時候,性能是否有影響。
遺憾的是,我們不得不告訴他們,添加更多磁盤后,他們很可能只會看到容量增加,而不是性能增加。但我們的建議并非完全沒有價值。如果用戶不關心小型隨機 IO 的性能,則每個 OSD 2 個 CPU Core 可能是一個很好的推薦。除了提高小型隨機 IO 性能之外,在 NVMe 磁盤運行 Ceph 還有很多好處。然而,對于該用戶來說,小型隨機 IO 是必須要關注的,而這恰恰是 CPU 資源最重要的情況。
所以不得不告訴他們,在增加磁盤后,他們很可能只會看到容量增加,而不是性能的增加。
遺憾的是,這不是第一次出現(xiàn)這個問題,并且該問題依然有很多困擾點。2 年前,我們更新了上游 Ceph 文檔,試圖在 PR (https://github.com/ceph/ceph/pull/32093 ) 中提供更好的案例。當時,我們的推薦場景要求如下:
- 1 core per 200-500 MB/s
- 1 core per 1000-3000 IOPS
不過這里最重要的方面是 IOPS 性能。本文將重點介紹 Ceph 小型隨機 IOPS 性能如何隨著 CPU 資源的增加而擴展。
集群配置
Nodes | 10 x Dell PowerEdge R6515 |
CPU | 1 x AMD EPYC 7742 64C/128T |
Memory | 128GiB DDR4 |
Network | 1 x 100GbE Mellanox ConnectX-6 |
NVMe | 6 x 4TB Samsung PM983 |
OS Version | CentOS Stream release 8 |
Ceph Version | Pacific V16.2.9 (built from source) |
所有節(jié)點通過 100GbE QSFP28 連接到同一臺 Juniper QFX5200 交換機上。安裝集群并使用 CBT (https://github.com/ceph/cbt/) 執(zhí)行 fio 測試。除非單獨說明,否則每個節(jié)點都配置為最多 6 個 OSD,并使用 4 個 fio 進程使用 librbd 進行測試。
英特爾系統(tǒng)上一個重要的操作系統(tǒng)級優(yōu)化是將調(diào)整后的配置文件設置為 “l(fā)atency-performance” 或 “network-latency”。這主要有助于避免與 CPU C/P 狀態(tài)轉(zhuǎn)換相關的延遲峰值。基于 AMD Rome 的系統(tǒng)在這方面似乎不那么敏感,但是為這些測試調(diào)整的配置文件仍然設置為 “network-latency”。
測試配置
基于 CBT 測試的 Ceph 集群有幾個配置需要修改。首先,禁用 rbd 緩存,為每個 OSD 分配 8GB 內(nèi)存,并在禁用 cephx 的情況下使用 msgr V1。在最近的測試中,我們發(fā)現(xiàn)使用默認 cephx 身份驗證的 Msgr V2 似乎結(jié)果與使用 Msgr V1 一樣,盡管啟用加密可能會導致高達 30-40% 的性能損失,并且兩臺服務器和客戶端上的 CPU 使用率相近甚至更高。
首先通過 Fio 預寫入填充 RBD 卷,然后是循環(huán) 3 次 4K 隨機讀取,接下來是 iodepth=128 的 4K 隨機寫入,每次持續(xù) 5 分鐘。CBT 允許 OSD 與其他工具或環(huán)境變量一起工作,numactl 用于控制 OSD 可以在系統(tǒng)上使用多少 CPU Core。初始測試使用單個 OSD 和 1 副本進行。多 OSD 測試是使用多個 OSD 和 3 副本進行的。
單個 OSD 測試
在多集群上,ceph 以偽隨機算法實現(xiàn)數(shù)據(jù)分布存儲。不同的 OSD 承載的熱點數(shù)據(jù)是不同的。有些 OSD 可能比其他 OSD 承受更多的壓力,因此總體性能可能也會受到影響。最終,我們可以看到 Ceph 集群的性能是受到集群中最慢 OSD 性能的限制(木桶原理——最短的木片決定木桶的容量)。
針對單個 OSD 的測試可以避免這種問題,同時也進一步消除了額外的復制延遲和開銷,確保 OSD 以最高效率工作。測試單個 OSD 并不能代表整個集群的性能,但它確實展示了對應的 OSD 在最佳條件下的性能。
這里首先要注意的是,CPU 在 2 到 4 Core 之間,性能大約提高了 100%。這幾乎是線性增加。但是在 4 個 CPU Core 之后,增加開始放緩。從 4 個 CPU Core 增加到 16 個 CPU Core 僅產(chǎn)生 100% 的性能增長,在 10 個 CPU Core 時增長幾乎完全趨于平穩(wěn)。不過,寫入性能會更高,在 14-16 個 CPU Core 時最高可達 350% 左右。但是在測試中 Ceph OSD 是否真的使用了所有這些被分配的 CPU Core 嗎?
事實證明,為 OSD 分配更多 CPU Core 可以持續(xù)提高性能,最多可達 14-16 Core,但在 CPU 高 Core 數(shù)時,OSD 不會使用所有 Core。對于讀取尤其如此。更多的 CPU Core 意味著更高的性能,但效率會隨著您的提升而降低。然而,使用的每個 CPU Core 的 IOPS 仍然相對平穩(wěn)。
為什么會這樣,限制是什么?默認情況下,Ceph OSD 每個 OSD 有 80 多個線程,但從資源消耗的角度來看,最重要的是:
- 16 個 OSD 工作線程(8 個分片,每個分片有 2 個線程)
- 3 個異步消息線程
- 1 個 bluestore key/value 線程
- 1 個 bluestore “finisher” 線程
- RocksDB flush(高優(yōu)先級)和compaction(低優(yōu)先級)后臺線程
此處無需深入了解細節(jié)(我們將在稍后的文章中討論),常用 OSD 的實際最大 CPU Core 使用率可能約為 23 個 Core。我們在實驗中, 5 分鐘內(nèi)測試下來的最高使用率是 4K 隨機寫入大約 占用18-19 Core,對 OSD 沒有限制并且禁用了 RocksDB 的預寫日志。那么為什么我們在這些測試中看不到呢?可能的答案是 ceph 根本無法讓所有 16 個工作線程一直處于忙碌狀態(tài)。工作線的等待時間是很短的。雖然一個 OSD 平均可能使用 6 或 8 Core,但當它可以在短時間內(nèi)爆發(fā)到 16 個以上的 Core 數(shù)時,它可能表現(xiàn)最佳,而其他時候它可能只需要 3-4 個 CPU Core。
60 個 OSD 集群測試
在部署完整集群時是否會出現(xiàn)在單個 OSD 測試中觀察到的趨勢?
在查看 60 OSD 集群測試結(jié)果時,有幾個結(jié)果是很明顯的。雖然曲線看起來類似于單個 OSD 測試,但性能最高時每個 OSD 大約 8-10 Core 用于讀取,每個 OSD 大約 12 Core 用于寫入。在單個 OSD 測試中,讀取和寫入增益分別達到約 200% 和 350%。在完整集群配置中,增益達到 100% 和 250%。
簡單地看一下 OSD.0,看起來更大規(guī)模集群中的 OSD 在隨機讀取測試中使用的 Core 更少。同時,分配的每個 Core 的 IOPS 和使用的每個 Core 的 IOPS 數(shù)量也低得多。在寫入端,現(xiàn)在使用 3 副本。為了能夠與單個 OSD 測試進行比較,我們必須確認 OSD 的 IOPS 并考慮復制因素。即使這樣做,每個 Core 的寫入性能也比單個 OSD 測試低很多。
在讀取方面,Ceph 為每 Core 提供大約 7500 IOPS,并且根據(jù)分配給 OSD 的 Core 數(shù)量,每個 Core 分配的 IOPS 從 2400 到 8500 不等。在寫入端,Ceph 為每個使用的 Core 提供大約 3500 IOPS,每個分配的 Core 提供 1600 到 3900 IOPS 。這些結(jié)果比我們 2 年前結(jié)果要好一些,我們在最近的 Quincy 版本中進行了進一步的改進。
單 OSD 與多 OSD NVMe 性能對比
另一個經(jīng)常出現(xiàn)的問題是 Ceph 如何很好地利用 NVMe 磁盤。通常的測試方式是直接從本地連接的驅(qū)磁盤寫入或讀取數(shù)據(jù)。
用戶想知道為什么 Ceph 在有大量磁盤的情況下,速度依然慢。簡單點說,Ceph 確實比直接寫入磁盤是要慢的,原因有很多。主要的原因如下:
- 計算 crush placement、校驗和、加密、糾刪碼、網(wǎng)絡開銷等帶來的延遲。
- 處理數(shù)據(jù)(編碼/解碼/等)并在線程甚至 RocksDB 之間分配/復制/移動內(nèi)存中的數(shù)據(jù)。
- Ceph 不只是寫入數(shù)據(jù),還會寫出關于該數(shù)據(jù)的元數(shù)據(jù)。這在執(zhí)行小型寫入時是很重要的。
- 允許線程在沒有任務時進入休眠狀態(tài),并在任務到來時喚醒它們。這樣做是為了減少低負載期間的 CPU 開銷,但是當線程進入休眠和喚醒太快時它會對性能產(chǎn)生重大影響。
如果不做任何調(diào)整與優(yōu)化,其中一些問題是很難改進的。Ceph 很容易受到網(wǎng)絡的性能影響(盡管 dpdk 之類的優(yōu)化可以提供些幫助)。Crush 確定數(shù)據(jù)的分布時也會帶來一些延遲,并且總會有一些由 crc32、編碼/解碼等引起的額外延遲。話雖如此,單 OSD 和多 OSD 之間存在非常大的性能差異—— OSD 測試。
上述的圖表可能有些粗糙。盡管 60 個 OSD 的集群提供了大約 200 萬次隨機讀取 IOPS,但單獨的 OSD 能夠以更高的效率提供近 4 倍于每個 NVMe 的性能。在寫入方面,情況更接近一些,但單個 OSD 仍然比每個 NVMe 快大約 2 倍。在 Ceph Quincy 中,我們努力提高寫路徑性能。在 Ceph Quincy 版本的改進和選擇性 RocksDB 調(diào)整之間,我們在完整的 60 個 OSD 集群上實現(xiàn)了超過 40% 的 4K 隨機寫入 IOPS 改進。
要了解我們是如何獲得這些結(jié)果的,請在此處查看 RocksDB 調(diào)優(yōu)深入研究文章 (https://ceph.io/en/news/blog/2022/rocksdb-tuning-deep-dive/)。
結(jié)論
最終,我們可以看到,在集群級別和 OSD 內(nèi)部實現(xiàn)更高性能還是有很大空間的。
在以后的博文中,我們將深入探討一些在低 CPU Core 數(shù)和高 CPU Core 數(shù)下限制性能的問題,以及一些如何進一步改進 Ceph 性能的想法。在此之前,每個 OSD 分配多少個 CPU Core 是需要權衡取舍的。為每個 OSD 分配 2-4 個CPU Core,Ceph 可以在小型讀取和小型寫入期間可充分使用所有 CPU Core。當分配更多的的CPU Core 數(shù)(甚至每個 OSD 最多 16+)時,是可以提高性能,但每添加一個 CPU Core 的增益就會降低。
正常情況下,OSD 能夠正常穩(wěn)定使用 CPU Core,但是當 OSD 分配了更高的CPU Core數(shù)量時,OSD 則無法充分使用每個 CPU Core。也就是說支出并不能帶來同等的收益。因此需要綜合考量 Ceph 硬件架構(gòu)設計以及軟件資源上的架構(gòu)設計的支出與收益。
最后,這篇文章是基于 Ceph Pacific 版本的,通過調(diào)優(yōu)后, Ceph 的性能有所提高。另外,我們需要注意,如果是使用Ceph Quincy 版本的話,結(jié)果可能有些差異。當前測試也是在一個新集群上進行的,如果是在一個運行時間比較長的舊的集群可能結(jié)果也是不一樣的。不過,本文至少為 CPU 是如何影響基于 NVMe OSD 性能提供一個思路。
*原文鏈接:Ceph.io — Ceph OSD CPU Scaling - Part (https://ceph.io/en/news/blog/2022/ceph-osd-cpu-scaling/) 推薦閱讀