QEMU/KVM + Ceph Librbd 性能測試以及深度優(yōu)化
?介紹
最近,很多人都會問:如何設(shè)置 QEMU/KVM 以獲取最高的性能?
雖然,過去很多人都在測試或者使用 Ceph 過程中進(jìn)行調(diào)優(yōu)設(shè)置以獲取最佳性能,但到目前而言,還沒有一個最優(yōu)的最新數(shù)據(jù)。通常,我們在使用 Ceph 的時候,有經(jīng)驗的工程師往往會通過消除系統(tǒng)高級別的性能瓶頸來優(yōu)化。
這可能意味著可能會通過 librbd 與同步 IO 隔離測試單個OSD的延遲,或者使用大量有高 IO 深度的客戶端在裸機上的 OSD 集群上產(chǎn)生大量IO。在這種情況下,請求是用大量并發(fā) IO 驅(qū)動由 librbd 支持的單個 QEMU/KVM,并查看其速度。
下文,我們將了解 QEMU/KVM 在使用 Ceph 的 librbd 驅(qū)動程序時的執(zhí)行速度。
集群設(shè)置
所有節(jié)點都位于同一個 Juniper QFX5200 交換機上,并通過單個 100GbE QSFP28 鏈路連接。雖然集群有 10 個節(jié)點,但在決定最終設(shè)置之前我們也評估了各種配置。最終使用 5 個節(jié)點作為 OSD 主機,總共有 30 個 NVMe 支持的 OSD。
此設(shè)置的預(yù)期總體性能約為 1M 隨機讀取 IOPS 和至少 250K 隨機寫入 IOPS(在 3 副本的場景下),這足以測試單個 VM 的 QEMU/KVM 性能。集群中剩余的一個節(jié)點用作 VM 客戶端主機。不過,在配置 VM 之前,使用 CBT (https://github.com/ceph/cbt/) 構(gòu)建了幾個測試集群,并使用 fio 的 librbd 引擎運行測試工作負(fù)載以獲得基線結(jié)果。
基線測試
CBT 的配置為匹配 Ceph 環(huán)境修改了一些,而不是使用默認(rèn)的配置。首先,禁用了 rbd 緩存 (1),每個 OSD 被分配了一個 8GB 的 OSD 內(nèi)存 traget,并且在初始測試中禁用了 cephx ,并且使用 msgr V1(但在以后的測試中使用安全模式下的 msgr V2 啟用了 cephx)。創(chuàng)建集群后,CBT 配置為使用帶有 librbd 引擎的 fio 創(chuàng)建一個 6TB RBD 卷,然后通過 iodepth=128 的 fio 執(zhí)行 16KB 隨機讀取 5 分鐘。由于使用 CBT 重新創(chuàng)建集群和運行多個基線測試非常簡單,因此,下面測試了幾種不同的集群大小以獲得 librbd 引擎和基于 kernel-rbd 的 libaio 引擎的基線結(jié)果。
在集群級別禁用 RBD 緩存將對使用 librbd 引擎的 fio 有效,但不會對 QEMU/KVM 的 librbd 驅(qū)動程序有效。相反,cache=none 必須通過 qemu-kvm 的驅(qū)動部分顯式傳遞。
Kernel-RBD 在從單個 OSD 讀取時表現(xiàn)非常出色,但 Librbd 在完整的 30 個 OSD Ceph 集群中以略高于 122K IOPS 的速度實現(xiàn)了最高性能。librbd 和 kernel-rbd 在 5 OSD Ceph 集群上的表現(xiàn)幾乎一樣。
盡管如此,在 5 個節(jié)點、30 個 OSD Ceph 集群上我們執(zhí)行了進(jìn)一步的測試。此場景更好地模仿了用戶在小規(guī)模但更貼近真實環(huán)境并且配置 NVMe 的 Ceph 集群上可能看到的結(jié)果。
虛擬機部署
使用 RBD 部署和引導(dǎo) QEMU 虛擬機鏡像相當(dāng)簡單了。
1. 下載鏡像
使用了 CentOS8 Stream qcow2 映像,并注入了 root 密碼和公鑰以便于訪問:
2. RBD 鏡像池創(chuàng)建、初始化和設(shè)置 LibVirt 身份驗證
這用于存儲 RBD 鏡像。
3. 將 qcow2 鏡像轉(zhuǎn)換為 Ceph RBD 鏡像并調(diào)整大小
調(diào)整它的大小,以便為基準(zhǔn)測試留出一些空間!
4. 完成設(shè)置虛擬機并預(yù)填充基準(zhǔn)數(shù)據(jù)
最后,從 RBD 啟動 VM,登錄,設(shè)置分區(qū),并預(yù)填充 FIO 文件以進(jìn)行測試。在這種情況下,僅使用了 20GB 的鏡像部分,但不要擔(dān)心。稍后將在真正的 XFS 文件系統(tǒng)上生成更大 (2TB) 文件的結(jié)果。
對 VM 進(jìn)行基準(zhǔn)測試
1. 默認(rèn)情況
眾所周知,在 ide 和 virtio-blk 等 qemu 設(shè)備之間存在相當(dāng)顯著的性能差異。QEMU/KVM 配置為使用其默認(rèn)值的性能如何?
結(jié)果慘不忍睹!那virtio-blk 又是怎么樣的了?
2. 使用 virtio-blk-pci
結(jié)果有很大的進(jìn)步。現(xiàn)在是時候添加一個單獨的 iothread。
3. 添加單獨的 IO 線程
結(jié)果更好,但其實仍然很慢。此時,我使用 ( uwpmp (https://github.com/markhpc/uwpmp/) ) 分析了 QEMU/KVM。有各種各樣的問題,包括不匹配的 debug symbols 和其他煩人的問題。為了防止結(jié)果不標(biāo)準(zhǔn),我們進(jìn)行了數(shù)十次測試。最終推動測試?yán)^續(xù)的是對 QEMU 調(diào)用 librbd 緩存層的 wallclock 配置文件調(diào)整。QEMU 中的 librbd 驅(qū)動程序會覆蓋 Ceph 全局配置中設(shè)置的內(nèi)容。要在 QEMU/KVM 中禁用 RBD 緩存(這在告訴集群上很重要),必須在 qemu-kvm 的驅(qū)動器配置中明確設(shè)置 cache=none。
4. 禁用 LibRBD 驅(qū)動器緩存
禁用 LibRBD 緩存帶來了相當(dāng)大的性能改進(jìn),但幸運的是這還沒有結(jié)束。在運行 wallclock profiler 時,我們注意到不僅有大量時間花在 rbd 緩存上,還有 libc 內(nèi)存分配例程。Ceph 的內(nèi)存模型通常涉及創(chuàng)建許多小的臨時對象,這些對象會分割內(nèi)存并且對內(nèi)存分配器來說非常困難。TCMalloc(和 JEMalloc)傾向于比 libc malloc 更好地處理 Ceph 的行為。幸運的是,可以通過 LD_PRELOAD 指令注入 TCMalloc。
5. 將內(nèi)存分配器切換到 TCMalloc
結(jié)果變得更好了,但它可以更快嗎?
6. 使用新版本的 LibRBD
目前本次測試使用的是CentOS Stream8自帶的系統(tǒng)版本librbd。它已經(jīng)很老了,后面的版本有顯著的改進(jìn)。這些主要與由 Adam Emerson 編寫并由 Jason Dillaman 在 RBD 中實現(xiàn)的 boost::asio IO 路徑返工有關(guān)。可以設(shè)置 LD_LIBRARY_PATH 來告訴 qemu-kvm 使用編譯 Ceph (v16.2.9) 時安裝在 /usr/local 中的新版本 librbd。
新版本的 librbd 顯著提高了性能,現(xiàn)在的結(jié)果比直接使用 librbd 的基線 fio 測試要快一些!
更大鏡像的測試
到目前為止,只有一個直接位于 RBD 塊設(shè)備上的小型 (20G) 數(shù)據(jù)集用于測試。為了使這些測試更真實,更接近我們的基線測試,可以安裝一個 XFS 文件系統(tǒng)并預(yù)填充 2TB 的數(shù)據(jù)(遺憾的是受到前面提到的分區(qū)大小限制)。
不錯。即使 iodepth=16 相當(dāng)適中,fio 也能夠以大致 NVMe 的速度填充 RBD 卷。16K randread 工作量怎么樣?
16K 隨機讀取
16K 隨機寫入怎么樣?
16K 隨機寫入
不如本地 NVMe 驅(qū)動器快,但對于單個 VM 來說還不錯。值得注意的是,在隨機讀取測試期間,Ceph 的所有三個異步 msgr 線程都以 100% 的 CPU 運行。在測試運行時使用 ( uwpmp (https://github.com/markhpc/uwpmp/) )查看 qemu-kvm 進(jìn)程,發(fā)現(xiàn)正在進(jìn)行相當(dāng)多的工作,但在 librbd 端沒有明顯的快速優(yōu)化區(qū)域。然而,將 boost::asio 帶入堆棧更深可能會提供額外的改進(jìn)。
進(jìn)一步的 QEMU 優(yōu)化?
完成上述測試后,我聯(lián)系了 QEMU 維護(hù)者 Stefan Hajnoczi 以獲得他對結(jié)果的看法。他提供了幾個額外的選擇來嘗試:
- 較新的 --blockdev rbd,node-name=rbd0,cache.direct=on,pool=libvirt-pool,image=CentOS8 參數(shù)省略了 “raw'” 驅(qū)動程序以實現(xiàn)微小的加速...I / O請求直接進(jìn)行使用這種新參數(shù)從模擬的 virtio-blk 設(shè)備到 rbd 驅(qū)動程序。
- 使用 -M q35 獲得現(xiàn)代機器類型。
事實證明,測試這很容易,我們可以使用新參數(shù)重新啟動 qemu-kvm:
最終,性能非常接近,使用新命令的讀取速度可能稍慢,寫入速度稍快,但需要進(jìn)一步測試以了解結(jié)果是否具有統(tǒng)計相關(guān)性。
Msgr V2 和 AES 加密
到目前為止,這些測試都使用了完全禁用 CephX 的 Msgr V1。這不是運行真實集群的一種非常現(xiàn)實的方式。唯一應(yīng)該像這樣配置集群的情況是,網(wǎng)絡(luò)以及 Ceph 客戶端是完全可靠信任的。Ceph 的默認(rèn)身份驗證模式允許身份驗證和防止中間人攻擊。Ceph 還可以在“安全”模式下運行,該模式還提供 AES-128-GCM 在線加密。這可以通過將幾個 Ceph 配置選項設(shè)置為“安全”來啟用:
這些設(shè)置對基線測試中的客戶端性能有多大影響?
這里的下降似乎并不算太糟糕,但是從上面的“更大鏡像的測試”部分重復(fù) QEMU/KVM 隨機讀取測試導(dǎo)致得分約為 87K IOPS,而沒有加密時為 123K IOPS。在 qemu-kvm 進(jìn)程中,異步 msgr 線程仍然固定在 100%,但是這次(反向)wallclock 配置文件看起來有點不同:
作為框架組裝工作的一部分,每個異步 msgr 線程至少花費 14% 的時間在 libssl 的 EVP_DecryptUpdate 函數(shù)中。值得注意的是,即使在這個 AMD Rome 處理器上,libssl 似乎也能正確使用 AES-NI 指令。仔細(xì)查看代碼,似乎對于每一幀,Ceph 都會遍歷每個段并依次解密各個緩沖區(qū)(每個段可能有多個?。?。IE 的偽代碼看起來像這樣:
也許如果可以一次解密更大的數(shù)據(jù)塊,那么這里的 AES-NI 開銷就可以減少。但是什么大小真的很重要?Openssl 提供了一個速度測試,可以幫助縮小范圍:
看來,在這個處理器上,當(dāng)我們只處理 16K 塊并利用一個完整的核心來進(jìn)行 AES 解密時,我們應(yīng)該能夠達(dá)到接近 4GB/s(256K 塊/秒)的速度。即使是 1-8K 的塊處理速度也很快,但非常小的塊對解密性能有重大影響。
這可能有助于解釋啟用安全模式時的性能損失。如果 3 個 IO 線程中的每一個都在 libssl 函數(shù)中花費 14-20% 的時間(并非所有都顯示在上面的配置文件片段中),那么根據(jù) openssl 速度測試,預(yù)期應(yīng)該可以實現(xiàn) 120-130K IOPS。如果可以減少 msgr 線程之間的爭用,那么額外的 msgr 線程可能能夠以增加 CPU 使用率為代價來提高性能。
結(jié)論
這篇文章介紹了如何為 VM 存儲調(diào)整以及優(yōu)化 QEMU/KVM 和 librbd 的性能。
對于 16K 的 IO,qemu+librbd 經(jīng)過仔細(xì)調(diào)優(yōu)后,可以從單個 VM 實現(xiàn) 64-67K 的隨機寫入 IOPS 和 123K 的隨機讀取 IOPS。即使在使用 libssl 的 AES-NI 支持時,在 Ceph 中啟用 128 位在線 AES 加密也會對性能產(chǎn)生顯著影響(30% 以上)。
在加密和未加密的情況下,性能似乎主要受到飽和 msgr 線程的限制。有一些跡象表明,線程之間的爭用可能在限制單客戶端性能方面發(fā)揮了作用。在啟用AES加密的情況下,幀段的分解和解密順序可能會影響性能。似乎沒有證據(jù)表明 virtio-blk-pci 達(dá)到了極限。
*原文鏈接:https://ceph.io/en/news/blog/2022/qemu-kvm-tuning/