【KVM系列02】KVM的CPU 和内存虚拟化
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?第二章?KVM的CPU 和內存虛擬化
? ? ? ??1. 為什么需要 CPU 虛擬化
1.1 基于二進制翻譯的全虛擬化(Full Virtualization with Binary Translation)
1.2. 超虛擬化(或者半虛擬化/操作系統輔助虛擬化 Paravirtualization)?
1.3. 硬件輔助的全虛擬化?
2. KVM CPU 虛擬化
2.1. CPU 物理特性
2.2 多 CPU 服務器架構:SMP,NMP,NUMA
2.2 KVM CPU 虛擬化
2.3 客戶機CPU結構和模型
2.4 客戶機 vCPU 數目的分配方法
2. KVM 內存虛擬化
2.1 內存虛擬化的概念
2.2 KVM 內存虛擬化
2.3.2 好處
2.4 ?KVM Huge Page Backed Memory (巨頁內存技術)
【KVM系列文章】https://blog.csdn.net/baidu_37107022/article/details/88812463
?
1. 為什么需要 CPU 虛擬化
X86 操作系統是設計在直接運行在裸硬件設備上的,因此它們自動認為它們完全占有計算機硬件。x86 架構提供四個特權級別給操作系統和應用程序來訪問硬件。?Ring 是指 CPU 的運行級別,Ring 0是最高級別,Ring1次之,Ring2更次之……?就 Linux+x86 來說,?
- 操作系統(內核)需要直接訪問硬件和內存,因此它的代碼需要運行在最高運行級別 ?Ring0上,這樣它可以使用特權指令,控制中斷、修改頁表、訪問設備等等。?
- 應用程序的代碼運行在最低運行級別上ring3上,不能做受控操作。如果要做,比如要訪問磁盤,寫文件,那就要通過執行系統調用(函數),執行系統調用的時候,CPU的運行級別會發生從ring3到ring0的切換,并跳轉到系統調用對應的內核代碼位置執行,這樣內核就為你完成了設備訪問,完成之后再從ring0返回ring3。這個過程也稱作用戶態和內核態的切換。
?
?
那么,虛擬化在這里就遇到了一個難題,因為宿主操作系統是工作在 ring0 的,客戶操作系統就不能也在 ring0 了,但是它不知道這一點,以前執行什么指令,現在還是執行什么指令,但是沒有執行權限是會出錯的。所以這時候虛擬機管理程序(VMM)需要避免這件事情發生。 虛機怎么通過 VMM 實現 Guest CPU 對硬件的訪問,根據其原理不同有三種實現技術:
1. 全虛擬化
2. 半虛擬化
3. 硬件輔助的虛擬化?
1.1 基于二進制翻譯的全虛擬化(Full Virtualization with Binary Translation)
客戶操作系統運行在?Ring 1,它在執行特權指令時,會觸發異常(CPU的機制,沒權限的指令會觸發異常),然后 VMM 捕獲這個異常,在異常里面做翻譯,模擬,最后返回到客戶操作系統內,客戶操作系統認為自己的特權指令工作正常,繼續運行。但是這個性能損耗,就非常的大,簡單的一條指令,執行完,了事,現在卻要通過復雜的異常處理過程。
異常 “捕獲(trap)-翻譯(handle)-模擬(emulate)” 過程:
1.2. 超虛擬化(或者半虛擬化/操作系統輔助虛擬化 Paravirtualization)?
? 半虛擬化的思想就是,修改操作系統內核,替換掉不能虛擬化的指令,通過超級調用(hypercall)直接和底層的虛擬化層hypervisor來通訊,hypervisor?同時也提供了超級調用接口來滿足其他關鍵內核操作,比如內存管理、中斷和時間保持。
? 這種做法省去了全虛擬化中的捕獲和模擬,大大提高了效率。所以像XEN這種半虛擬化技術,客戶機操作系統都是有一個專門的定制內核版本,和x86、mips、arm這些內核版本等價。這樣以來,就不會有捕獲異常、翻譯、模擬的過程了,性能損耗非常低。這就是XEN這種半虛擬化架構的優勢。這也是為什么XEN只支持虛擬化Linux,無法虛擬化windows原因,微軟不改代碼啊。
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模式下。
而且兩種操作模式可以互相轉換。運行在 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廠商,支持虛擬化的力度越來越大,靠硬件輔助的全虛擬化技術的性能逐漸逼近半虛擬化,再加上全虛擬化不需要修改客戶操作系統這一優勢,全虛擬化技術應該是未來的發展趨勢。
| ? | 利用二進制翻譯的全虛擬化 | 硬件輔助虛擬化 | 操作系統協助/半虛擬化 |
| 實現技術 | BT和直接執行 | 遇到特權指令轉到root模式執行 | Hypercall |
| 客戶操作系統修改/兼容性 | 無需修改客戶操作系統,最佳兼容性 | 無需修改客戶操作系統,最佳兼容性 | 客戶操作系統需要修改來支持hypercall,因此它不能運行在物理硬件本身或其他的hypervisor上,兼容性差,不支持Windows |
| 性能 | 差 | 全虛擬化下,CPU需要在兩種模式之間切換,帶來性能開銷;但是,其性能在逐漸逼近半虛擬化。 | 好。半虛擬化下CPU性能開銷幾乎為0,虛機的性能接近于物理機。 |
| 應用廠商 | VMware Workstation/QEMU/Virtual PC | VMware ESXi/Microsoft Hyper-V/Xen 3.0/KVM | Xen |
2. KVM CPU 虛擬化
KVM 是基于CPU 輔助的全虛擬化方案,它需要CPU虛擬化特性的支持。
2.1. CPU 物理特性
這個命令查看主機上的CPU 物理情況:
[s1@rh65 ~]$ numactl --hardwareavailable: 2 nodes (0-1) //2顆CPU node 0 cpus: 0 1 2 3 4 5 12 13 14 15 16 17 //這顆 CPU 有8個內核 node 0 size: 12276 MBnode 0 free: 7060 MBnode 1 cpus: 6 7 8 9 10 11 18 19 20 21 22 23 node 1 size: 8192 MBnode 1 free: 6773 MBnode distances:node 0 1 0: 10 21 1: 21 10要支持 KVM, Intel CPU 的 vmx 或者 AMD CPU 的 svm 擴展必須生效了:
[root@rh65 s1]# egrep "(vmx|svm)" /proc/cpuinfoflags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 popcnt aes lahf_lm arat epb dts tpr_shadow vnmi flexpriority ept vpid2.2 多 CPU 服務器架構:SMP,NMP,NUMA
從系統架構來看,目前的商用服務器大體可以分為三類:
- 多處理器結構 (SMP : Symmetric Multi-Processor):所有的CPU共享全部資源,如總線,內存和I/O系統等,操作系統或管理數據庫的復本只有一個,這種系統有一個最大的特點就是共享所有資源。多個CPU之間沒有區別,平等地訪問內存、外設、一個操作系統。SMP 服務器的主要問題,那就是它的擴展能力非常有限。實驗證明, SMP 服務器 CPU 利用率最好的情況是 2 至 4 個 CPU 。
- 海量并行處理結構 (MPP : Massive Parallel Processing)?:NUMA 服務器的基本特征是具有多個 CPU 模塊,每個 CPU 模塊由多個 CPU( 如 4 個 ) 組成,并且具有獨立的本地內存、 I/O 槽口等。在一個物理服務器內可以支持上百個 CPU 。但 NUMA 技術同樣有一定缺陷,由于訪問遠地內存的延時遠遠超過本地內存,因此當 CPU 數量增加時,系統性能無法線性增加。
- MPP 模式則是一種分布式存儲器模式,能夠將更多的處理器納入一個系統的存儲器。一個分布式存儲器模式具有多個節點,每個節點都有自己的存儲器,可以配置為SMP模式,也可以配置為非SMP模式。單個的節點相互連接起來就形成了一個總系統。MPP可以近似理解成一個SMP的橫向擴展集群,MPP一般要依靠軟件實現。
- 非一致存儲訪問結構 (NUMA : Non-Uniform Memory Access):它由多個 SMP 服務器通過一定的節點互聯網絡進行連接,協同工作,完成相同的任務,從用戶的角度來看是一個服務器系統。其基本特征是由多個 SMP 服務器 ( 每個 SMP 服務器稱節點 ) 通過節點互聯網絡連接而成,每個節點只訪問自己的本地資源 ( 內存、存儲等 ) ,是一種完全無共享 (Share Nothing) 結構。
詳細描述可以參考?SMP、NUMA、MPP體系結構介紹。
查看你的服務器的 CPU 架構:
[root@rh65 s1]# uname -aLinux rh65 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux #這服務器是 SMP 架構?2.2 KVM CPU 虛擬化
2.2.1 KVM 虛機的創建過程
可見:
(1)qemu-kvm 通過對 /dev/kvm 的 一系列 ICOTL 命令控制虛機,比如
open("/dev/kvm", O_RDWR|O_LARGEFILE) = 3 ioctl(3, KVM_GET_API_VERSION, 0) = 12 ioctl(3, KVM_CHECK_EXTENSION, 0x19) = 0 ioctl(3, KVM_CREATE_VM, 0) = 4 ioctl(3, KVM_CHECK_EXTENSION, 0x4) = 1 ioctl(3, KVM_CHECK_EXTENSION, 0x4) = 1 ioctl(4, KVM_SET_TSS_ADDR, 0xfffbd000) = 0 ioctl(3, KVM_CHECK_EXTENSION, 0x25) = 0 ioctl(3, KVM_CHECK_EXTENSION, 0xb) = 1 ioctl(4, KVM_CREATE_PIT, 0xb) = 0 ioctl(3, KVM_CHECK_EXTENSION, 0xf) = 2 ioctl(3, KVM_CHECK_EXTENSION, 0x3) = 1 ioctl(3, KVM_CHECK_EXTENSION, 0) = 1 ioctl(4, KVM_CREATE_IRQCHIP, 0) = 0 ioctl(3, KVM_CHECK_EXTENSION, 0x1a) = 0(2)一個?KVM 虛機即一個 Linux qemu-kvm 進程,與其他 Linux 進程一樣被Linux 進程調度器調度。
(3)KVM 虛機包括虛擬內存、虛擬CPU和虛機 I/O設備,其中,內存和 CPU 的虛擬化由 KVM 內核模塊負責實現,I/O 設備的虛擬化由 QEMU 負責實現。
(3)KVM戶機系統的內存是 qumu-kvm 進程的地址空間的一部分。
(4)KVM 虛機的 vCPU 作為 線程運行在 qemu-kvm 進程的上下文中。
vCPU、QEMU 進程、LInux 進程調度和物理CPU之間的邏輯關系:
2.2.2 因為 CPU 中的虛擬化功能的支持,并不存在虛擬的 CPU,KVM Guest 代碼是運行在物理 CPU 之上
? ? 根據上面的 1.3 章節,支持虛擬化的 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 給客戶機使用。
?這篇文章?是關于 vSphere 中 CPU 虛擬化的,我覺得它和 KVM CPU 虛擬化存在很大的一致。下圖是使用 2 socket 2 core 共 4 個 vCPU 的情形:
?? 幾個概念:socket (顆,CPU 的物理單位),core (核,每個 CPU 中的物理內核),thread (超線程,通常來說,一個 CPU core 只提供一個 thread,這時客戶機就只看到一個 CPU;但是,超線程技術實現了 CPU 核的虛擬化,一個核被虛擬化出多個邏輯 CPU,可以同時運行多個線程)。?
? 上圖分三層,他們分別是是VM層,VMKernel層和物理層。對于物理服務器而言,所有的CPU資源都分配給單獨的操作系統和上面運行的應用。應用將請求先發送給操作系統,然后操作系統調度物理的CPU資源。在虛擬化平臺比如 KVM 中,在VM層和物理層之間加入了VMkernel層,從而允許所有的VM共享物理層的資源。VM上的應用將請求發送給VM上的操作系統,然后操縱系統調度Virtual CPU資源(操作系統認為Virtual CPU和物理 CPU是一樣的),然后VMkernel層對多個物理CPU Core進行資源調度,從而滿足Virtual CPU的需要。在虛擬化平臺中OS CPU Scheduler和Hyperviisor CPU Scheduler都在各自的領域內進行資源調度。?
? ?KVM 中,可以指定 socket,core 和 thread 的數目,比如 設置 “-smp 5,sockets=5,cores=1,threads=1”,則 vCPU 的數目為 5*1*1 = 5。客戶機看到的是基于 KVM vCPU 的 CPU 核,而 vCPU 作為 QEMU 線程被 Linux 作為普通的線程/輕量級進程調度到物理的 CPU 核上。至于你是該使用多 socket 和 多core,這篇文章?有仔細的分析,其結論是在 VMware ESXi 上,性能沒什么區別,只是某些客戶機操作系統會限制物理 CPU 的數目,這種情況下,可以使用少 socket 多 core。
2.2.3 客戶機系統的代碼是如何運行的
?一個普通的 Linux 內核有兩種執行模式:內核模式(Kenerl)和用戶模式 (User)。為了支持帶有虛擬化功能的 CPU,KVM 向 Linux 內核增加了第三種模式即客戶機模式(Guest),該模式對應于 CPU 的 VMX non-root mode。
KVM 內核模塊作為 User mode 和 Guest mode 之間的橋梁:
- User mode 中的 QEMU-KVM 會通過 ICOTL 命令來運行虛擬機
- KVM 內核模塊收到該請求后,它先做一些準備工作,比如將 VCPU 上下文加載到 VMCS (virtual machine control structure)等,然后驅動 CPU 進入 VMX non-root 模式,開始執行客戶機代碼
三種模式的分工為:
- Guest 模式:執行客戶機系統非 I/O 代碼,并在需要的時候驅動 CPU 退出該模式
- Kernel 模式:負責將 CPU 切換到 Guest mode 執行 Guest OS 代碼,并在 CPU 退出 ?Guest mode 時回到 Kenerl 模式
- User 模式:代表客戶機系統執行 I/O 操作
(來源)
QEMU-KVM 相比原生 QEMU 的改動:
- 原生的 QEMU 通過指令翻譯實現 CPU 的完全虛擬化,但是修改后的 QEMU-KVM 會調用 ICOTL 命令來調用 KVM 模塊。
- 原生的 QEMU 是單線程實現,QEMU-KVM 是多線程實現。
主機 Linux 將一個虛擬視作一個 QEMU 進程,該進程包括下面幾種線程:
- I/O 線程用于管理模擬設備
- vCPU 線程用于運行 Guest 代碼
- 其它線程,比如處理 event loop,offloaded tasks 等的線程
在我的測試環境中(RedHata Linux 作 Hypervisor):
| smp 設置的值 | 線程數 | 線程 |
| 4 | 8 | 1 個主線程(I/O 線程)、4 個 vCPU 線程、3 個其它線程 |
| 6 | 10 | 1 個主線程(I/O 線程)、6 個 vCPU 線程、3 個其它線程 |
這篇文章?談談了這些線程的情況。
(來源)
| 客戶機代碼執行(客戶機線程) | I/O 線程 | 非 I/O 線程 |
| 虛擬CPU(主機 QEMU 線程) | QEMU I/O 線程 | QEMU vCPU 線程 |
| 物理 CPU | 物理 CPU 的 VMX non-root 模式中 | 物理 CPU 的 VMX non-root 模式中 |
2.2.4 從客戶機線程到物理 CPU 的兩次調度
要將客戶機內的線程調度到某個物理 CPU,需要經歷兩個過程:
? ? KVM 使用標準的 Linux 進程調度方法來調度 vCPU 進程。Linux 系統中,線程和進程的區別是 進程有獨立的內核空間,線程是代碼的執行單位,也就是調度的基本單位。Linux 中,線程是就是輕量級的進程,也就是共享了部分資源(地址空間、文件句柄、信號量等等)的進程,所以線程也按照進程的調度方式來進行調度。
(1)Linux 進程調度原理可以參考?這篇文章?和?這篇文章。通常情況下,在SMP系統中,Linux內核的進程調度器根據自有的調度策略將系統中的一個可運行(runable)進程調度到某個CPU上執行。下面是 Linux 進程的狀態機:
(2)處理器親和性:可以設置 vCPU 在指定的物理 CPU 上運行,具體可以參考這篇文章?和?這篇文章。
? ? 根據 Linux 進程調度策略,可以看出,在 Linux 主機上運行的 KVM 客戶機 的總 vCPU 數目最好是不要超過物理 CPU 內核數,否則,會出現線程間的 CPU 內核資源競爭,導致有虛機因為 vCPU 進程等待而導致速度很慢。
關于這兩次調度,業界有很多的研究,比如上海交大的論文?Schedule Processes, not VCPUs?提出動態地減少 vCPU 的數目即減少第二次調度。
另外,這篇文章?談到的是 vSphere CPU 的調度方式,有空的時候可以研究下并和 KVM vCPU 的調度方式進行比較。
2.3 客戶機CPU結構和模型
KVM 支持 SMP 和 NUMA 多CPU架構的主機和客戶機。對 SMP 類型的客戶機,使用 “-smp”參數:
-smp [,cores=][,threads=][,sockets=][,maxcpus=]對 NUMA 類型的客戶機,使用 “-numa”參數:
-numa [,mem=][,cpus=]][,nodeid=]?CPU 模型 (models)定義了哪些主機的 CPU 功能 (features)會被暴露給客戶機操作系統。為了在具有不同 CPU 功能的主機之間做安全的遷移,qemu-kvm 往往不會將主機CPU的所有功能都暴露給客戶機。其原理如下:
你可以運行?qemu-kvm -cpu ??命令來獲取主機所支持的 CPU 模型列表。
[root@rh65 s1]# kvm -cpu ? x86 Opteron_G5 AMD Opteron 63xx class CPUx86 Opteron_G4 AMD Opteron 62xx class CPUx86 Opteron_G3 AMD Opteron 23xx (Gen 3 Class Opteron)x86 Opteron_G2 AMD Opteron 22xx (Gen 2 Class Opteron)x86 Opteron_G1 AMD Opteron 240 (Gen 1 Class Opteron)x86 Haswell Intel Core Processor (Haswell)x86 SandyBridge Intel Xeon E312xx (Sandy Bridge)x86 Westmere Westmere E56xx/L56xx/X56xx (Nehalem-C)x86 Nehalem Intel Core i7 9xx (Nehalem Class Core i7)x86 Penryn Intel Core 2 Duo P9xxx (Penryn Class Core 2)x86 Conroe Intel Celeron_4x0 (Conroe/Merom Class Core 2)x86 cpu64-rhel5 QEMU Virtual CPU version (cpu64-rhel5)x86 cpu64-rhel6 QEMU Virtual CPU version (cpu64-rhel6)x86 n270 Intel(R) Atom(TM) CPU N270 @ 1.60GHzx86 athlon QEMU Virtual CPU version 0.12.1 x86 pentium3x86 pentium2x86 pentiumx86 486 x86 coreduo Genuine Intel(R) CPU T2600 @ 2.16GHzx86 qemu32 QEMU Virtual CPU version 0.12.1 x86 kvm64 Common KVM processorx86 core2duo Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHzx86 phenom AMD Phenom(tm) 9550 Quad-Core Processorx86 qemu64 QEMU Virtual CPU version 0.12.1 Recognized CPUID flags:f_edx: pbe ia64 tm ht ss sse2 sse fxsr mmx acpi ds clflush pn pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de vme fpuf_ecx: hypervisor rdrand f16c avx osxsave xsave aes tsc-deadline popcnt movbe x2apic sse4.2|sse4_2 sse4.1|sse4_1 dca pcid pdcm xtpr cx16 fma cid ssse3 tm2 est smx vmx ds_cpl monitor dtes64 pclmulqdq|pclmuldq pni|sse3extf_edx: 3dnow 3dnowext lm|i64 rdtscp pdpe1gb fxsr_opt|ffxsr fxsr mmx mmxext nx|xd pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de vme fpuextf_ecx: perfctr_nb perfctr_core topoext tbm nodeid_msr tce fma4 lwp wdt skinit xop ibs osvw 3dnowprefetch misalignsse sse4a abm cr8legacy extapic svm cmp_legacy lahf_lm[root@rh65 s1]#? ? 每個 Hypervisor 都有自己的策略,來定義默認上哪些CPU功能會被暴露給客戶機。至于哪些功能會被暴露給客戶機系統,取決于客戶機的配置。qemu32 和 qemu64 是基本的客戶機 CPU 模型,但是還有其他的模型可以使用。你可以使用 qemu-kvm 命令的 -cpu 參數來指定客戶機的 CPU 模型,還可以附加指定的 CPU 特性。"-cpu" 會將該指定 CPU 模型的所有功能全部暴露給客戶機,即使某些特性在主機的物理CPU上不支持,這時候QEMU/KVM 會模擬這些特性,因此,這時候也許會出現一定的性能下降。?
RedHat Linux 6 上使用默認的 cpu64-rhe16 作為客戶機 CPU model:
你可以指定特定的 CPU model 和 feature:
qemu-kvm -cpu Nehalem,+aes?
你也可以直接使用 -cpu host,這樣的話會客戶機使用和主機相同的 CPU model。
2.4 客戶機 vCPU 數目的分配方法
這篇文章 (http://my.oschina.net/chape/blog/173981) 介紹了一些指導性方法,摘要如下:
我們來假設一個主機有 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在觀測性能是否可以接受。
2. KVM 內存虛擬化
2.1 內存虛擬化的概念
? ? 除了 CPU?虛擬化,另一個關鍵是內存虛擬化,通過內存虛擬化共享物理系統內存,動態分配給虛擬機。虛擬機的內存虛擬化很象現在的操作系統支持的虛擬內存方式,應用程序看到鄰近的內存地址空間,這個地址空間無需和下面的物理機器內存直接對應,操作系統保持著虛擬頁到物理頁的映射。現在所有的 x86 CPU?都包括了一個稱為內存管理的模塊MMU(Memory Management Unit)和?TLB(Translation Lookaside Buffer),通過MMU和TLB來優化虛擬內存的性能。
?
? ?KVM 實現客戶機內存的方式是,利用mmap系統調用,在QEMU主線程的虛擬地址空間中申明一段連續的大小的空間用于客戶機物理內存映射。
?
(圖片來源?HVA 同下面的 MA,GPA 同下面的 PA,GVA 同下面的 VA)
?
在有兩個虛機的情況下,情形是這樣的:
可見,KVM 為了在一臺機器上運行多個虛擬機,需要增加一個新的內存虛擬化層,也就是說,必須虛擬?MMU?來支持客戶操作系統,來實現 VA -> PA -> MA 的翻譯。客戶操作系統繼續控制虛擬地址到客戶內存物理地址的映射 (VA -> PA),但是客戶操作系統不能直接訪問實際機器內存,因此VMM 需要負責映射客戶物理內存到實際機器內存 (PA -> MA)。
VMM 內存虛擬化的實現方式:
- 軟件方式:通過軟件實現內存地址的翻譯,比如?Shadow page table (影子頁表)技術
- 硬件實現:基于 CPU 的輔助虛擬化功能,比如 AMD 的 NPT 和 Intel 的 EPT 技術?
影子頁表技術:
2.2 KVM 內存虛擬化
?KVM 中,虛機的物理內存即為 qemu-kvm 進程所占用的內存空間。KVM 使用 CPU 輔助的內存虛擬化方式。在 Intel 和 AMD 平臺,其內存虛擬化的實現方式分別為:
- AMD 平臺上的 NPT (Nested Page Tables) 技術
- Intel 平臺上的 EPT (Extended Page Tables)技術
EPT 和 NPT采用類似的原理,都是作為?CPU 中新的一層,用來將客戶機的物理地址翻譯為主機的物理地址。關于 EPT, Intel 官方文檔中的技術如下(實在看不懂...)
EPT的好處是,它的兩階段記憶體轉換,特點就是將 Guest Physical Address → System Physical Address,VMM不用再保留一份 SPT (Shadow Page Table),以及以往還得經過 SPT 這個轉換過程。除了降低各部虛擬機器在切換時所造成的效能損耗外,硬體指令集也比虛擬化軟體處理來得可靠與穩定。
2.3 KSM (Kernel SamePage Merging 或者?Kernel Shared Memory)
KSM 在 Linux?2.6.32 版本中被加入到內核中。
2.3.1 原理
其原理是,KSM 作為內核中的守護進程(稱為 ksmd)存在,它定期執行頁面掃描,識別副本頁面并合并副本,釋放這些頁面以供它用。因此,在多個進程中,Linux將內核相似的內存頁合并成一個內存頁。這個特性,被KVM用來減少多個相似的虛擬機的內存占用,提高內存的使用效率。由于內存是共享的,所以多個虛擬機使用的內存減少了。這個特性,對于虛擬機使用相同鏡像和操作系統時,效果更加明顯。但是,事情總是有代價的,使用這個特性,都要增加內核開銷,用時間換空間。所以為了提高效率,可以將這個特性關閉。
2.3.2 好處
其好處是,在運行類似的客戶機操作系統時,通過 KSM,可以節約大量的內存,從而可以實現更多的內存超分,運行更多的虛機。?
2.3.3 合并過程
(1)初始狀態:
(2)合并后:
(3)Guest 1 寫內存后:
2.4 ?KVM Huge Page Backed Memory (巨頁內存技術)
這是KVM虛擬機的又一個優化技術.。Intel 的 x86 CPU 通常使用4Kb內存頁,當是經過配置,也能夠使用巨頁(huge page):?(4MB on x86_32, 2MB on x86_64 and x86_32 PAE)
使用巨頁,KVM的虛擬機的頁表將使用更少的內存,并且將提高CPU的效率。最高情況下,可以提高20%的效率!
使用方法,需要三部:
mkdir /dev/hugepagesmount -t hugetlbfs hugetlbfs /dev/hugepages #保留一些內存給巨頁sysctl vm.nr_hugepages=2048 (使用 x86_64 系統時,這相當于從物理內存中保留了2048 x 2M = 4GB 的空間來給虛擬機使用) #給 kvm 傳遞參數 hugepagesqemu-kvm - qemu-kvm -mem-path /dev/hugepages也可以在配置文件里加入:驗證方式,當虛擬機正常啟動以后,在物理機里查看:
cat /proc/meminfo |grep -i hugepages老外的一篇文檔,他使用的是libvirt方式,先讓libvirtd進程使用hugepages空間,然后再分配給虛擬機。
參考資料:
http://www.cnblogs.com/xusongwei/archive/2012/07/30/2615592.html
https://www.ibm.com/developerworks/cn/linux/l-cn-vt/
http://www.slideshare.net/HwanjuKim/3cpu-virtualization-and-scheduling
http://www.cse.iitb.ac.in/~puru/courses/autumn12/cs695/classes/kvm-overview.pdf
http://www.linux-kvm.com/content/using-ksm-kernel-samepage-merging-kvm
http://blog.csdn.net/summer_liuwei/article/details/6013255
http://blog.pchome.net/article/458429.html
http://blog.chinaunix.net/uid-20794164-id-3601787.html
虛擬化技術性能比較和分析,周斌,張瑩
http://wiki.qemu.org/images/c/c8/Cpu-models-and-libvirt-devconf-2014.pdf
http://frankdenneman.nl/2011/01/11/beating-a-dead-horse-using-cpu-affinity/
?
總結
以上是生活随笔為你收集整理的【KVM系列02】KVM的CPU 和内存虚拟化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【KVM系列01】KVM简介及安装
- 下一篇: 【KVM系列03】KVM的I/O 全虚拟