天天看點

位元組跳動提出 KVM 核心熱更新方案,效率提升 5.25 倍

作者:位元組跳動技術團隊

1. 介紹

作為雲計算最重要的底層基礎之一,KVM 虛拟化軟體在現代的資料中心中應用非常廣泛。基于 KVM 的 hypervisor 包括了構成主控端的軟硬體,共同為虛拟機中的應用程式提供高性能的 CPU、記憶體和 IO 裝置等資源。在大規模部署的生産環境中,作為雲服務提供商(Cloud Service Provider),如何從技術上保證軟硬體的可運維性,一直是大家重點關注的問題。

為了給使用者提供穩定、安全、高效并且功能豐富的雲資源,IaaS 的底層軟體必須能夠支撐軟硬體的各種運維需求。例如,在偶然出現一些難以避免的硬體故障時,需要能夠把虛拟機及時熱遷移到健康的主控端;或者,在軟體安全漏洞或功能缺陷被修複後,能夠通過熱更新,及時部署上線到生産環境中。

然而實作使用者無感覺地熱遷移和熱更新,卻是一個複雜的系統工程問題。因為 KVM 虛拟化涉及衆多不同層次的元件、諸多特性和靈活可選的組合方式,其中不乏一些非常複雜的軟硬體技術例如 SR-IOV、Linux 核心、QEMU、DPDK、KubeVirt 或者 OpenStack 等,系統總體架構複雜度很高。而且這些軟硬體子產品各自都有複雜的接口和内部狀态,在不影響虛拟機正常運作的情況下,要做到主控端軟體的熱更新和熱遷移,還需要做一些針對性的設計或改造。同時,作為雲計算底座的一部分,它們也需要緊密的配合才能完成預期的功能。特别是對于内部狀态處理能力要求非常高的熱更新功能,更需要深入、全面的打通。

目前,在各個開源社群(如 Linux,QEMU,CloudHypervisor 等)和各大雲計算公司,都在積極的嘗試對 KVM 的熱更新支援進行研發,也是曆年各大技術峰會的一個重要研讨主題。位元組跳動技術團隊從實際場景出發,相應地對熱更新問題進行了深入分析,與開源社群緊密合作,從多個角度做出了深度探索并取得了進展。

在今年 9 月份舉行的虛拟化領域全球技術峰會 KVM Forum 上,位元組跳動系統技術與工程團隊(System Technologies & Engineering,簡稱 STE 團隊)公布了相關的技術成果:首次提出一種在 KVM 熱更新場景中透明支援 PCI 直通裝置的方案,能夠顯著降低核心熱更新的實作成本。通過對 host 核心和 QEMU 的擴充和改進,可以做到不依賴于特定硬體修改或者 guest 配合的熱更新,支援 PCI 直通裝置。同時,在性能方面,也通過深入的分析和優化,将一次核心熱更新所需的最少時間(downtime)從 1000ms 降低至 160ms ,效率提升 5.25 倍。

本文将整理回顧 KVM Forum 大會中分享的主要技術方案,以飨讀者。

KVM Forum 會議演講視訊連結:

Preserving IOMMU States During Kexec Reboot:https://share.weiyun.com/Mz3Wk6v8

2. IOMMU狀态保持

PCI 裝置直通在目前資料中心的 KVM 虛拟化場景中廣泛應用,能夠為虛拟機中的應用提供高性能的 IO 裝置。同時,直通裝置的使用也為雲計算底層軟體設施的運維帶來了一些複雜度。

其中,對熱更新和熱遷移的相容性是 PCI 直通裝置的一大難點。這是因為熱更新或熱遷移操作依賴于對虛拟機狀态的提取、保持、傳輸等操作,而 PCI 直通裝置的狀态資料對于主控端側的 hypervisor 是不透明的。是以在 IaaS 的實踐中,往往需要對使用了直通裝置的虛拟機進行特殊處理。例如,通過定制的 SR-IOV 硬體,實作 PF 管理 VF 狀态的邏輯;或者在虛拟機中運作特殊的驅動程式和 agent 程序,通過 guest 在過程中的協同配合來完成熱遷移或熱更新操作。

這些方法可以在一定程度上解決 PCI 直通裝置的運維難題,但是帶來了更高的研發成本、軟體和配置的複雜度,也有可能會犧牲使用者體驗和 IO 性能。

2.1 技術方案調研

在 KVM 中對 PCI 裝置的直通需要通過 VFIO-PCI 接口來完成。VFIO-PCI 是 Linux 核心對 IOMMU 和 PCI 底層邏輯的抽象封裝 API,提供給運作在使用者态的 QEMU 或者其它 VMM(Virtual Machine Manager)軟體來配置虛拟裝置的 IO 映射關系,進而允許虛拟機核心驅動直接通路硬體資源,以達到較高的 IO 效率。

在熱更新過程中,虛拟機的運作狀态需要被穩定的保持在更新之前的狀态,其中包括虛拟機的 CPU 狀态(寄存器裡的資料等)、記憶體資料、虛拟裝置的接口狀态和内部狀态等。對于 PCI 直通裝置來說,有 2 個思路:

1.設法提取裝置的狀态資料,備份在預先設計好的位置(如預留的記憶體或者磁盤),然後在熱更新結束之前,從備份中恢複。提取備份的過程,一般稱之為序列化;從資料中恢複狀态的過程稱之為反序列化。

2.不提取裝置狀态資料,并在熱更新過程中完全不改變裝置狀态。熱更新完成後,虛拟機繼續通路這個硬體裝置。

前一種思路已經被證明是可行的方案,并且在某些較新的硬體中已實作,它的優點是不僅可以用來熱更新,也可以用來熱遷移;在熱遷移過程中,虛拟機會被轉移到不同的實體機上,也就不可能再使用同一個裝置。但是,這個方式的缺點是必須有硬體支援,同時因為存在序列化、反序列化的操作,完成熱更新所需時間較長。

我們對第二種情況進行調研和實驗後發現,通過對 Linux 核心進行一些局部的修改,在 Intel IOMMU 上可以實作在熱更新過程中,裝置狀态的完全隔離和保護,進而得到一個 PCI 透傳裝置的熱更新通用支援方法。

2.2 解決方案

本文提出的方案主要包括三個部分:

改進一:通過在 hypervisor 中引入必要的靜态頁面配置設定,保證 kexec 重新開機過程中的狀态保持。

靜态配置設定主要有使用者态和核心态兩部分工作。其中,使用者态的工作方式為:

1.虛拟機的 RAM 使用 memmap 方式配置設定,在 host 側使用 DAX 的形式管理。memmap 是一個核心參數,可以為實體記憶體配置設定不同的屬性。其中 E820 type 12 是一個 NVDIMM 類型(例如 memmap = 2G!6G)。

2.這個類型的實體頁,将不再被核心動态管理,而是作為“非易失性記憶體”來看待。在啟動後,我們可以通過建立一個 DevDax 字元裝置,mmap 到 QEMU 的位址空間。

3.DevDax 的建立可以使用系統調用,也可以用 ndctl 指令:

ndctl create-namespace -m devdax           

4.該指令會建立一個類似 /dev/dax1.0 的字元裝置。這個字元裝置提供一個支援 DAX(Linux核心提供的直接實體位址通路機制)的 mmap 接口,可以直接将實體記憶體映射到 QEMU 使用者态。QEMU 指令行參數如下:

$qemu ... -object memory-backend-file,id=mem,size=2G,mem-path=/dev/dax1.0,share=on,align=2M \ -numa node,memdev=mem           

5.而後 QEMU 會通過 KVM 接口把這段預留記憶體用于填充 EPT 頁表。

改進二: 核心态的靜态配置設定實作需要通過一個核心更新檔來實作

1.我們在核心中引入了一個新的實體頁管理器 KRAM,為其它子產品提供 2 個配置設定頁的函數接口。這兩個接口的主要目的是提供靜态實體頁給硬體相關子產品。

1. kram_get_fixed_page(area, index)

2. kram_alloc_page()

2.在 E820 的 enum 中定義新的 type 用以預留實體頁給 KRAM:memmap=*:* 。

3.在 Intel 的 IOMMU 驅動子產品中,使用 kram 接口來配置設定 root page 和 DMAR page。包括iommu_alloc_root_entry和alloc_pgtable_page等函數中,将原本的alloc_pgtable_page替換成對 KRAM 子產品的調用。

改進三:對 VFIO 裝置簡化,保證硬體狀态不被幹擾

在 VFIO - PCI 相關系統調用(VFIO_GROUP_SET_FLAGS)中,我們加入了一個新的标志位,用以在 QEMU 熱更新過程中,跳過對 VFIO - PCI 裝置的初始化和重置。

第二、三部分的相關代碼将會在後續開源。

2.3 PoC驗證

目前我們在 QEMU 模拟環境中對上面的方案進行了實驗。借助 KVM 在 Intel CPU 上的嵌套虛拟化支援,和 QEMU 對虛拟 IOMMU 的支援,可以很快的啟動一個測試環境:

$qemu -machine q35 -device intel-iommu,intremap=on-cpuhost... -device e1000e,netdev=guestnet           

上面的指令啟動的嵌套虛拟化的 L1,運作的是增加了 VFIO - PCI 熱更新的核心。對 L1 裡安裝的 QEMU 同樣也加入了 CPR(Checkpoint Restore)和 VFIO - PCI 的擴充調用。

使用 VFIO - PCI 我們配置設定上面的虛拟 e1000e 網卡給 L2:

$qemu ... -device vfio-pci,addr=06.0,host={dev}           

然後,通過 cpr-save -> kexec -> 啟動 qemu -> restore 的流程來熱更新整個 L1。

在測試過程中采集到的時間記錄如下:

位元組跳動提出 KVM 核心熱更新方案,效率提升 5.25 倍

從暫停虛拟機,到重新開機以後虛拟機恢複運作并在虛拟網絡上繼續發包,一共經過了 159ms。虛拟 e1000 網卡在這個過程中沒有被 reset,始終保持運作狀态。也就是說從外部或者應用視角來看,因主控端熱更新而導緻的總響應時間,僅僅增加了不到 160ms 的時長,并且由于網卡的 rx 隊列始終可用,在流量較低的情況下,也不會導緻丢包和重傳。

相比之下,如果用核心和 QEMU 的主線版本來執行上面的流程,可以采用 savevm 到磁盤後 kexec 重新開機并 loadvm 的步驟。但是這樣不僅不能支援 VFIO - PCI 裝置,也會因為缺少各種優化(如:savevm/loadvm 需要複制虛拟機記憶體),産生 1000ms 以上的 downtime 延遲。

3.結論

在使用 VFIO - PCI 透傳裝置的主控端上,部署了具有上述改進的 host 核心和 QEMU 等程式。在測試中,基于 QEMU 通用的 checkpointing and recovery(CPR)架構,我們現可以支援低損耗的 host 核心熱更新動作。從暫停虛拟機,到重新開機進入新核心并繼續執行虛拟機,整個過程可在 160ms 左右完成。

此技術方案可被應用在公有雲和私有雲的 IaaS 業務場景,具有很高的實用價值,能夠顯著降低運維成本,提高雲的安全性,并優化運維過程中的虛拟機運作性能和客戶體驗。位元組跳動系統與技術工程團隊将會繼續優化 Linux 核心和虛拟化軟體,為資料中心持續提供安全、穩定、高效運作的系統軟體。

此外,在 Virtio 裝置标準,QEMU 熱更新,Linux 啟動時間,io_uring,kexec 等方面,團隊也進行了深入的研究和優化。我們将會在本文和後續文章中持續分享相關技術和最新進展。

引用連結

CPR(Checkpoint Restore):

https://patchew.org/QEMU/[email protected]/

4. 關于 STE 團隊

位元組跳動 STE 團隊,一直緻力于作業系統核心與虛拟化、系統基礎軟體與基礎庫的建構和性能優化、超大規模資料中心的系統穩定性和可靠性建設、新硬體與軟體的協同設計等基礎技術領域的研發與工程化落地,具備全面的基礎軟體工程能力,為位元組上層業務保駕護航。同時,團隊積極關注社群技術動向,擁抱開源和标準,歡迎更多同學加入我們,一起交流學習。歡迎大家投遞履歷至:[email protected][email protected]

繼續閱讀