天天看點

OpenStack Nova 高性能虛拟機之 CPU 綁定

目錄

前文清單​

KVM

KVM(Kernel-based Virtual Machine 基于核心的虛拟機)是可嵌入 Linux Kernel 的核心功能子產品,與 QEMU、Libvirt 等使用者态應用程式協同組成一套完整的 Linux 全虛拟化解決方案。

由 KVM 提供 CPU 和核心虛拟化,并通過 /dev/kvm 裝置暴露出建立 vCPU、配置設定虛拟記憶體位址空間、讀寫 vCPU 寄存器等 Hypervisor 功能調用接口。但隻有 vCPU 和虛拟記憶體不足以構成虛拟機,還需要依賴于由 QEMU 模拟出來的各類 I/O 裝置共同組成。KVM 提供的核心虛拟化能力彌補了原生 QEMU 需要通過模拟 CPU 來進行指令翻譯所産生的性能損耗。在較新的 QEMU 發行版(1.3 及以上)中,已經合并了 KVM 的适配代碼實作,在執行 qemu 指令時通過選項 ​<code>​--enable-kvm​</code>​ 即可啟用。

OpenStack Nova 高性能虛拟機之 CPU 綁定

簡單來說,KVM 運作在核心态,負責 CPU 和記憶體的虛拟化。QEMU 運作在使用者态,負責模拟和管理各類虛拟硬體裝置。QEMU 通過 ioctl() 調用 /dev/kvm 接口,将 CPU 指令翻譯的部分交由 KVM 完成。

OpenStack Nova 高性能虛拟機之 CPU 綁定

為了追求更好的虛拟機性能,後續還為該方案追加了一些具有直通(Pass-through)特性的半虛拟化裝置和驅動程式(e.g. virtio_blk、virtio_net ),用于替代 QEMU 對一些關鍵裝置(e.g. 磁盤、網卡)的模拟,進一步提升了性能,使用者可以根據實際需要來選擇是否啟用。

OpenStack Nova 高性能虛拟機之 CPU 綁定

除了上述的 QEMU + KVM 虛拟化實作之外,還需要為使用者提供友好的操作入口才能算是一套完整的解決方案。Libvirt 就充當着這個入口,為使用者提供 GUI、CLI、API 等工具集。

OpenStack Nova 高性能虛拟機之 CPU 綁定

為了友善描述,在下文中,我們将這一套 Linux 全虛拟化解決方案,簡稱為 KVM。

支援 SMP 體系結構親和

支援 NUMA 體系結構親和

支援 CPU 親和性

支援 CPU 和記憶體超分(Overcommit)

支援 PCI 直通裝置和 SR-IOV

支援半虛拟化 I/O 裝置和驅動(VirtIO)

支援熱插拔 CPU,DISK,NIC 等虛拟硬體裝置

支援熱遷移(Live Migration)

支援核心記憶體共享技術(KSM,Kernel Shared Memory)

virsh:指令行工具(CLI)

virt-manager:圖形界面工具(GUI)

virt-viewer:虛拟機遠端桌面連接配接工具

virt-v2v:虛拟機遷移工具

virt-install:虛拟機建立指令行工具

virt-clone:虛拟機克隆工具

virt-top:虛拟機性能監控工具

sVirt:虛拟機安全工具

KVM 虛拟機,常用 Guest 表述,由 vCPU、虛拟記憶體、虛拟 I/O 裝置以及 GuestOS 組成:

Guest 的本質是一個 QEMU 程序

Guest 的一個 vCPU 就是一個 QEMU 程序内的線程

Guest 的虛拟記憶體就是配置設定給 QEMU 程序的記憶體位址空間的一部分

GuestOS 可以繼承 HostOS 核心中的 NUMA 和 大頁記憶體特性

vCPU、QEMU 程序、實體 CPU 及系統排程器之間的邏輯關系:

OpenStack Nova 高性能虛拟機之 CPU 綁定

而 GuestOS 的實體表現實際上就是一個 XML 檔案,描述了 GuestOS 的特征資訊。

OpenStack Nova 高性能虛拟機之 CPU 綁定

注:上圖為 vSphere 的 vCPU 排程示意圖,與 KVM 大同小異,可以用作參考。

既然 HostOS 将 vCPU 當普通線程來進行排程,那麼 vCPU 的排程與性能問題實際上就是 Linux 線程在多處理器計算平台中的排程與性能問題。關于這個問題我們曾經在《多程序、多線程與多處理器計算平台的性能問題》一文中讨論過,這裡不再贅述。簡單來說,提高虛拟機 vCPU 的性能,需要貫徹三點原則:

減少多線程上下文切換的性能損耗

減少使用者線程模式切換的性能損耗

提高高速緩存的命中率

而實作這些原則的手段大緻上有兩種:

規劃出給 Guest 專用的 pCPU s,并且 vCPUs 和 pCPUs 所擁有的 Cores 數量相近

将 vCPU 綁定到指定的 pCPU 上運作

KVM 本身就支援 CPU 綁定的相關功能,使用非常簡單:

Nova 支援的 vCPU 綁定

vcpu_pin_set 是 compute node 上的 nova.conf 配置項,是 OpenStack 最早設計用于限定 Guest 可以使用 compute node 上的 pCPUs 的範圍,解決了下述問題:

currently the instances can use all of the pcpu of compute node, the host may become slowly when vcpus of instances are busy, so we need to pin vcpus to the specific pcpus of host instead of all pcpus. the vcpu xml conf of libvirt will change to like this: ​<code>​&lt;vcpu cpuset="4-12,^8,15"&gt;1&lt;/vcpu&gt;​</code>​

簡單來說,就是為了讓使用者一方面可以劃分出 Guest 專用的 pCPUs 以保證性能,另一方面也是為了防止 Guest 過分争搶 Host 程序的 CPU 資源,為 Host 适當的留下一些 CPU 以保證正常運作。

NOTE:如果指定的 CPU 範圍超出了主控端原有的 CPU 範圍則會觸發異常。

CPU 綁定政策機制經常會結合 NUMA topology 一起使用,在《OpenStack Nova 高性能虛拟機之 NUMA 架構親和》一文中我們已經介紹過,這裡也不再贅述。

CPU-POLICY:

shared (default):不獨占 pCPU 政策,允許 vCPUs 在不同的 pCPUs 間浮動,盡管 vCPUs 受到 NUMA node 的限制也是如此。

dedicated:獨占 pCPU 政策,Guest 的 vCPUs 将會嚴格的 pinned 到 pCPUs 的集合中。在沒有明确配置 Guest NUMA Topology 的情況下,Nova 會将每個 vCPU 都作為一個 Socket 中的一個 Core;如果已經明确的配置了 Guest NUMA Topology 的話,那麼虛拟機就會嚴格按照 Guest NUMA Topology 和 Host NUMA Topology 的映射關系将 vCPUs pinned to pCPUs,pCPUs 可能是一個 Core 或是一個 Thread,根據 Host 實際的處理器體系結構以及 CPU-THREAD-POLICY 來共同決定。此時的 CPU overcommit ratio 為 1.0(不支援 CPU 超配),避免 vCPU 的數量大于 Core 的數量導緻的線程上下文切換損耗。

CPU-THREAD-POLICY:

prefer (default):如果 Host 開啟了超線程,則 vCPU 優先選擇在 Siblings Thread 中運作,即所有的 vCPU 都隻會考慮 siblings。例如:4 個邏輯核屬于同一 NUMA,其中 CPU1 和 CPU2 屬于相同實體核,CPU3 和 CPU4 屬于不同的實體核,若此時建立一個 Flavor vCPU 為 4 的雲主機會建立失敗,因為 siblings 隻有 [set([1, 2])];否則,vCPU 優先選擇在 Core 上運作。

isolate(vCPU 性能最好):vCPU 必須綁定到 Core 上。如果 Host 沒有開啟超線程,則理所當然會将 vCPU 綁定到 Core 上;相反,如果 Host 開啟了超線程,則 vCPU 會被綁定到 Siblings Thread 的一個 Thread 中,并且其他的 vCPU 不會再被配置設定到該 Core 上,相當于 vCPU 獨占一個 Core,避免 Siblings Thread 競争。

require(vCPU 數量最多):vCPU 必須綁定到 Thread 上。Host 必須開啟超線程,每個 vCPU 都會被綁定到 Thread 上,直到 Thread 用完為止。如果沒有開啟的話,那麼該 Host 不會出現在 Nova Scheduler 的排程名單中。

NOTE 1:隻有設定 ​<code>​hw:cpu_policy=dedicated​</code>​ 時,​<code>​hw:cpu_thread_policy​</code>​ 才會生效。後者設定的是 vCPU pinning to pCPU 的政策。

NOTE 2:如果 pinned(isolate) 和 unpinned 的虛拟機運作在同一個 compute node,則會發生 CPU 競争,因為 unpinned 的虛拟機不會考慮到 pinned 虛拟機的資源需求,由于 Cache 的影響,這将會嚴重的影響進行了 CPU 綁定的虛拟機的性能,尤其當兩者同處一個 NUMA 節點時。是以,應該使用 Host Aggregate 來區分開 pinned 和 unpinned 的虛拟機,退一步來說,最起碼也應該讓兩者運作在不同的 NUMA 節點上。而且如果一個 compute node 上運作的全是 pinned 虛拟機,那麼這個 compute node 不建議配置超配比。

NOTE 3:如果 ​<code>​cpu_thread_policy=prefer | require​</code>​ 時,Nova 的 Thread 配置設定政策是盡量先占滿一個 Core,然後再使用下一個 Core 上的 Thread,盡量避免 Thread/Core 碎片影響到後面建立的虛拟機。

繼續閱讀