天天看點

amd 虛拟化怎麼開_KVM 虛拟化基本原理

X86 作業系統是設計在直接運作在裸硬體裝置上的,是以它們自動認為它們完全占有計算機硬體。x86 架構提供四個特權級别給作業系統和應用程式來通路硬體。 Ring 是指 CPU 的運作級别,Ring 0是最進階别,Ring1次之,Ring2更次之…… 就 Linux+x86 來說,

作業系統(核心)需要直接通路硬體和記憶體,是以它的代碼需要運作在最高運作級别 Ring0上,這樣它可以使用特權指令,控制中斷、修改頁表、通路裝置等等。

應用程式的代碼運作在最低運作級别上ring3上,不能做受控操作。如果要做,比如要通路磁盤,寫檔案,那就要通過執行系統調用(函數),執行系統調用的時候,CPU的運作級别會發生從ring3到ring0的切換,并跳轉到系統調用對應的核心代碼位置執行,這樣核心就為你完成了裝置通路,完成之後再從ring0傳回ring3。這個過程也稱作使用者态和核心态的切換。

amd 虛拟化怎麼開_KVM 虛拟化基本原理

那麼,虛拟化在這裡就遇到了一個難題,因為宿主作業系統是工作在 ring0 的,客戶作業系統就不能也在 ring0 了,但是它不知道這一點,以前執行什麼指令,現在還是執行什麼指令,但是沒有執行權限是會出錯的。是以這時候虛拟機管理程式(VMM)需要避免這件事情發生。 虛機怎麼通過 VMM 實作 Guest CPU 對硬體的通路,根據其原理不同有三種實作技術:

1. 全虛拟化

2. 半虛拟化

3. 硬體輔助的虛拟化

1.1 基于二進制翻譯的全虛拟化(Full Virtualization with Binary Translation)

amd 虛拟化怎麼開_KVM 虛拟化基本原理

客戶作業系統運作在 Ring 1,它在執行特權指令時,會觸發異常(CPU的機制,沒權限的指令會觸發異常),然後 VMM 捕獲這個異常,在異常裡面做翻譯,模拟,最後傳回到客戶作業系統内,客戶作業系統認為自己的特權指令工作正常,繼續運作。但是這個性能損耗,就非常的大,簡單的一條指令,執行完,了事,現在卻要通過複雜的異常處理過程。

異常 “捕獲(trap)-翻譯(handle)-模拟(emulate)” 過程:

amd 虛拟化怎麼開_KVM 虛拟化基本原理

1.2. 超虛拟化(或者半虛拟化/作業系統輔助虛拟化 Paravirtualization)

半虛拟化的思想就是,修改作業系統核心,替換掉不能虛拟化的指令,通過超級調用(hypercall)直接和底層的虛拟化層hypervisor來通訊,hypervisor 同時也提供了超級調用接口來滿足其他關鍵核心操作,比如記憶體管理、中斷和時間保持。

這種做法省去了全虛拟化中的捕獲和模拟,大大提高了效率。是以像XEN這種半虛拟化技術,客戶機作業系統都是有一個專門的定制核心版本,和x86、mips、arm這些核心版本等價。這樣以來,就不會有捕獲異常、翻譯、模拟的過程了,性能損耗非常低。這就是XEN這種半虛拟化架構的優勢。這也是為什麼XEN隻支援虛拟化Linux,無法虛拟化windows原因,微軟不改代碼啊。

amd 虛拟化怎麼開_KVM 虛拟化基本原理

1.3. 硬體輔助的全虛拟化

2005年後,CPU廠商Intel 和 AMD 開始支援虛拟化了。 Intel 引入了 Intel-VT (Virtualization Technology)技術。 這種 CPU,有 VMX root operation 和 VMX non-root operation兩種模式,兩種模式都支援Ring 0 ~ Ring 3 共 4 個運作級别。這樣,VMM 可以運作在 VMX root operation模式下,客戶 OS 運作在VMX non-root operation模式下。

amd 虛拟化怎麼開_KVM 虛拟化基本原理

而且兩種操作模式可以互相轉換。運作在 VMX root operation 模式下的 VMM 通過顯式調用 VMLAUNCH 或 VMRESUME 指令切換到 VMX non-root operation 模式,硬體自動加載 Guest OS 的上下文,于是 Guest OS 獲得運作,這種轉換稱為 VM entry。Guest OS 運作過程中遇到需要 VMM 處理的事件,例如外部中斷或缺頁異常,或者主動調用 VMCALL 指令調用 VMM 的服務的時候(與系統調用類似),硬體自動挂起 Guest OS,切換到 VMX root operation 模式,恢複 VMM 的運作,這種轉換稱為 VM exit。VMX root operation 模式下軟體的行為與在沒有 VT-x 技術的處理器上的行為基本一緻;而VMX non-root operation 模式則有很大不同,最主要的差別是此時運作某些指令或遇到某些事件時,發生 VM exit。

也就說,硬體這層就做了些區分,這樣全虛拟化下,那些靠“捕獲異常-翻譯-模拟”的實作就不需要了。而且CPU廠商,支援虛拟化的力度越來越大,靠硬體輔助的全虛拟化技術的性能逐漸逼近半虛拟化,再加上全虛拟化不需要修改客戶作業系統這一優勢,全虛拟化技術應該是未來的發展趨勢。

(1)一個 KVM 虛機即一個Linux qemu-kvm 程序,與其他 Linux 程序一樣被Linux 程序排程器排程。

(2)KVM 虛機包括虛拟記憶體、虛拟CPU和虛機 I/O裝置,其中,記憶體和 CPU 的虛拟化由 KVM 核心子產品負責實作,I/O 裝置的虛拟化由 QEMU 負責實作。

(3)KVM戶機系統的記憶體是 qumu-kvm 程序的位址空間的一部分。

(4)KVM 虛機的 vCPU 作為 線程運作在 qemu-kvm 程序的上下文中。

支援虛拟化的 CPU 中都增加了新的功能。以 Intel VT 技術為例,它增加了兩種運作模式:VMX root 模式和 VMX nonroot 模式。通常來講,主機作業系統和 VMM 運作在 VMX root 模式中,客戶機作業系統及其應用運作在 VMX nonroot 模式中。因為兩個模式都支援所有的 ring,是以,客戶機可以運作在它所需要的 ring 中(OS 運作在 ring 0 中,應用運作在 ring 3 中),VMM 也運作在其需要的 ring 中 (對 KVM 來說,QEMU 運作在 ring 3,KVM 運作在 ring 0)。CPU 在兩種模式之間的切換稱為 VMX 切換。從 root mode 進入 nonroot mode,稱為 VM entry;從 nonroot mode 進入 root mode,稱為 VM exit。可見,CPU 受控制地在兩種模式之間切換,輪流執行 VMM 代碼和 Guest OS 代碼。

對 KVM 虛機來說,運作在 VMX Root Mode 下的 VMM 在需要執行 Guest OS 指令時執行 VMLAUNCH 指令将 CPU 轉換到 VMX non-root mode,開始執行客戶機代碼,即 VM entry 過程;在 Guest OS 需要退出該 mode 時,CPU 自動切換到 VMX Root mode,即 VM exit 過程。可見,KVM 客戶機代碼是受 VMM 控制直接運作在實體 CPU 上的。QEMU 隻是通過 KVM 控制虛機的代碼被 CPU 執行,但是它們本身并不執行其代碼。也就是說,CPU 并沒有真正的被虛級化成虛拟的 CPU 給客戶機使用。

主機 Linux 将一個虛拟視作一個 QEMU 程序,該程序包括下面幾種線程:

1.I/O 線程用于管理模拟裝置

2.vCPU 線程用于運作 Guest 代碼

3.其它線程,比如處理 event loop,offloaded tasks 等的線程

在我的測試環境中(RedHata Linux 作 Hypervisor):

amd 虛拟化怎麼開_KVM 虛拟化基本原理

要将客戶機内的線程排程到某個實體 CPU,需要經曆兩個過程:

客戶機線程排程到客戶機實體CPU 即 KVM vCPU,該排程由客戶機作業系統負責,每個客戶機作業系統的實作方式不同。在 KVM 上,vCPU 在客戶機系統看起來就像是實體 CPU,是以其排程方法也沒有什麼不同。

vCPU 線程排程到實體 CPU 即主機實體 CPU,該排程由 Hypervisor 即 Linux 負責。

KVM 使用标準的 Linux 程序排程方法來排程 vCPU 程序。Linux 系統中,線程和程序的差別是 程序有獨立的核心空間,線程是代碼的執行機關,也就是排程的基本機關。Linux 中,線程是就是輕量級的程序,也就是共享了部分資源(位址空間、檔案句柄、信号量等等)的程序,是以線程也按照程序的排程方式來進行排程。

vCPU如何設定

我們來假設一個主機有 2 個socket,每個 socket 有 4 個core。主頻2.4G MHZ 那麼一共可用的資源是 2*4*2.4G= 19.2G MHZ。假設主機上運作了三個VM,VM1和VM2設定為1socket*1core,VM3設定為1socket*2core。那麼VM1和VM2分别有1個vCPU,而VM3有2個vCPU。假設其他設定為預設設定。

那麼三個VM獲得該主機CPU資源配置設定如下:VM1:25%; VM2:25%; VM3:50%

假設運作在VM3上的應用支援多線程,那麼該應用可以充分利用到所非配的CPU資源。2vCPU的設定是合适的。假設運作在VM3上的應用不支援多線程,該應用根本無法同時使用利用2個vCPU. 與此同時,VMkernal層的CPU Scheduler必須等待實體層中兩個空閑的pCPU,才開始資源調配來滿足2個vCPU的需要。在僅有2vCPU的情況下,對該VM的性能不會有太大負面影響。但如果配置設定4vCPU或者更多,這種資源排程上的負擔有可能會對該VM上運作的應用有很大負面影響。

确定 vCPU 數目的步驟。假如我們要建立一個VM,以下幾步可以幫助确定合适的vCPU數目

1 了解應用并設定初始值

該應用是否是關鍵應用,是否有Service Level Agreement。一定要對運作在虛拟機上的應用是否支援多線程深入了解。咨詢應用的提供商是否支援多線程和SMP(Symmetricmulti-processing)。參考該應用在實體伺服器上運作時所需要的CPU個數。如果沒有參照資訊,可設定1vCPU作為初始值,然後密切觀測資源使用情況。

2 觀測資源使用情況

确定一個時間段,觀測該虛拟機的資源使用情況。時間段取決于應用的特點和要求,可以是數天,甚至數周。不僅觀測該VM的CPU使用率,而且觀測在作業系統内該應用對CPU的占用率。特别要區分CPU使用率平均值和CPU使用率峰值。

假如配置設定有4個vCPU,如果在該VM上的應用的CPU

使用峰值等于25%, 也就是僅僅能最多使用25%的全部CPU資源,說明該應用是單線程的,僅能夠使用一個vCPU (4 * 25% = 1 )

平均值小于38%,而峰值小于45%,考慮減少 vCPU 數目

平均值大于75%,而峰值大于90%,考慮增加 vCPU 數目

3 更改vCPU數目并觀測結果

每次的改動盡量少,如果可能需要4vCPU,先設定2vCPU在觀測性能是否可以接受。

KVM 實作客戶機記憶體的方式是,利用mmap系統調用,在QEMU主線程的虛拟位址空間中申明一段連續的大小的空間用于客戶機實體記憶體映射。

amd 虛拟化怎麼開_KVM 虛拟化基本原理

KVM 中,虛機的實體記憶體即為 qemu-kvm 程序所占用的記憶體空間。KVM 使用 CPU 輔助的記憶體虛拟化方式。在 Intel 和 AMD 平台,其記憶體虛拟化的實作方式分别為:

AMD 平台上的 NPT (Nested Page Tables) 技術

Intel 平台上的 EPT (Extended Page Tables)技術

EPT 和 NPT采用類似的原理,都是作為 CPU 中新的一層,用來将客戶機的實體位址翻譯為主機的實體位址。

KSM 作為核心中的守護程序(稱為 ksmd)存在,它定期執行頁面掃描,識别副本頁面并合并副本,釋放這些頁面以供它用。是以,在多個程序中,Linux将核心相似的記憶體頁合并成一個記憶體頁。這個特性,被KVM用來減少多個相似的虛拟機的記憶體占用,提高記憶體的使用效率。由于記憶體是共享的,是以多個虛拟機使用的記憶體減少了。這個特性,對于虛拟機使用相同鏡像和作業系統時,效果更加明顯。但是,事情總是有代價的,使用這個特性,都要增加核心開銷,用時間換空間。是以為了提高效率,可以将這個特性關閉。

其好處是,在運作類似的客戶機作業系統時,通過 KSM,可以節約大量的記憶體,進而可以實作更多的記憶體超分,運作更多的虛機。

(1)初始狀态:

amd 虛拟化怎麼開_KVM 虛拟化基本原理

(2)合并後:

amd 虛拟化怎麼開_KVM 虛拟化基本原理

(3)Guest 1 寫記憶體後:

amd 虛拟化怎麼開_KVM 虛拟化基本原理

Intel 的 x86 CPU 通常使用4Kb記憶體頁,當是經過配置,也能夠使用巨頁(huge page): (4MB on x86_32, 2MB on x86_64 and x86_32 PAE)

使用巨頁,KVM的虛拟機的頁表将使用更少的記憶體,并且将提高CPU的效率。最高情況下,可以提高20%的效率!

大頁面和透明大頁面(THP)

x86 CPU 通常會在 4kB 頁面中處理記憶體,但可以使用更大的 2MB 或 1GB 頁面,即 huge page(大頁面)。大頁面記憶體可以支援 KVM 客機部署,通過增加點選轉換後備緩沖器(TLB)的 CPU 緩存以改善性能。

kernel 功能将在 Red Hat Enterprise Linux 7 中預設啟用,大頁面可以大幅提高性能,尤其是對于較大的記憶體和記憶體密集型的負載。Red Hat Enterprise Linux 7 可以通過使用大頁面增加頁面大小,以便有效管理大量記憶體。

過程 7.1. 為客機啟用 1GB 大頁面

Red Hat Enterprise Linux 7.1 系統支援 2MB 或 1GB 大頁面,配置設定将在啟動或運作時進行。頁面大小均可以在運作時被釋放。例如,在啟動時配置設定 4 個 1GB 的大頁面和 1,024 個 2MB 的大頁面,請使用以下指令行:

'default_hugepagesz=1G hugepagesz=1G hugepages=4 hugepagesz=2M hugepages=1024'

此外,大頁面還可以在運作時配置設定。運作時配置設定允許系統管理者選擇從何種 NUMA 模式配置設定頁面。然而由于記憶體碎片的存在,運作時的頁面配置設定會比啟動時配置設定更容易造成配置設定失敗。以下運作時的配置設定示例顯示了從 node1 配置設定 4 個 1GB 的大頁面以及從 node3 配置設定 1,024 個 2MB 的大頁面:

# echo 4 > /sys/devices/system/node/node1/hugepages/hugepages-1048576kB/nr_hugepages

# echo 1024 > /sys/devices/system/node/node3/hugepages/hugepages-2048kB/nr_hugepages

接下來,将 2MB 和 1GB 的大頁面挂載到主機:

# mkdir /dev/hugepages1G # mount -t hugetlbfs -o pagesize=1G none /dev/hugepages1G # mkdir /dev/hugepages2M # mount -t hugetlbfs -o pagesize=2M none /dev/hugepages2M
           

預設1GB 大頁面現在對客機不可用。客戶機中要想使用1G大記憶體頁,需要如下配置:

在以下示例中,客機 NUMA 節點 0-5(不包括 NUMA 節點 4)将會使用 1 GB 的大頁面,客機 NUMA 節點 4 将使用 2 MB 的大頁面,無論客機 NUMA 節點在主機的任何位置。

透明大頁面(THP,transparent huge page)将為性能自動優化系統設定。通過允許所有的空餘記憶體被用作緩存以提高性能。

一旦 /sys/kernel/mm/transparent_hugepage/enabled 被設定為 always,透明大頁面将被預設使用。運作以下指令禁用透明大頁面:

# echo never > /sys/kernel/mm/transparent_hugepage/enabled

透明大頁面支援不能阻止 hugetlbfs 的使用。但在 hugetlbfs 未使用時,KVM 将使用透明大頁面來替代正常的 4KB 頁面大小

例子:

使用方法,需要三部:

mkdir /dev/hugepages mount -t hugetlbfs hugetlbfs /dev/hugepages #保留一些記憶體給巨頁 sysctl vm.nr_hugepages=2048 (使用 x86_64 系統時,這相當于從實體記憶體中保留了2048 x 2M = 4GB 的空間來給虛拟機使用) #給 kvm 傳遞參數 hugepages qemu-kvm - qemu-kvm -mem-path /dev/hugepages
           

也可以在配置檔案裡加入:

驗證方式,當虛拟機正常啟動以後,在實體機裡檢視:

cat /proc/meminfo |grep -i hugepages