KVM 介紹(2):CPU 和內存虛擬化

學習 KVM 的系列文章: html

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這種半虛擬化技術,客戶機操做系統都是有一個專門的定製內核版本,和x8六、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虛擬化特性的支持。node

2.1. CPU 物理特性

這個命令查看主機上的CPU 物理狀況:linux

[s1@rh65 ~]$ numactl --hardware
available: 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 MB
node 0 free: 7060 MB
node 1 cpus: 6 7 8 9 10 11 18 19 20 21 22 23
node 1 size: 8192 MB
node 1 free: 6773 MB
node distances:
node   0   1 
  0:  10  21 
  1:  21  10 

要支持 KVM, Intel CPU 的 vmx 或者 AMD CPU 的 svm 擴展必須生效了:es6

[root@rh65 s1]# egrep "(vmx|svm)" /proc/cpuinfo
flags        : 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 vpid

2.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體系結構介紹windows

查看你的服務器的 CPU 架構:api

[root@rh65 s1]# uname -a
Linux 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,須要經歷兩個過程:

  1. 客戶機線程調度到客戶機物理CPU 即 KVM vCPU,該調度由客戶機操做系統負責,每一個客戶機操做系統的實現方式不一樣。在 KVM 上,vCPU 在客戶機系統看起來就像是物理 CPU,所以其調度方法也沒有什麼不一樣。
  2. vCPU 線程調度到物理 CPU 即主機物理 CPU,該調度由 Hypervisor 即 Linux 負責。

    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 <n>[,cores=<ncores>][,threads=<nthreads>][,sockets=<nsocks>][,maxcpus=<maxcpus>]

對 NUMA 類型的客戶機,使用 「-numa」參數:

-numa <nodes>[,mem=<size>][,cpus=<cpu[-cpu>]][,nodeid=<node>] 
 
CPU 模型 (models)定義了哪些主機的 CPU 功能 (features)會被暴露給客戶機操做系統。爲了在具備不一樣 CPU 功能的主機之間作安全的遷移,qemu-kvm 每每不會將主機CPU的全部功能都暴露給客戶機。其 原理以下:
 
你能夠運行 qemu-kvm -cpu ? 命令來獲取主機所支持的 CPU 模型列表。
[root@rh65 s1]# kvm -cpu ?
x86       Opteron_G5  AMD Opteron 63xx class CPU                      
x86       Opteron_G4  AMD Opteron 62xx class CPU                      
x86       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.60GHz          
x86           athlon  QEMU Virtual CPU version 0.12.1                 
x86         pentium3                                                  
x86         pentium2                                                  
x86          pentium                                                  
x86              486                                                  
x86          coreduo  Genuine Intel(R) CPU           T2600  @ 2.16GHz 
x86           qemu32  QEMU Virtual CPU version 0.12.1                 
x86            kvm64  Common KVM processor                            
x86         core2duo  Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz 
x86           phenom  AMD Phenom(tm) 9550 Quad-Core Processor         
x86           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 fpu
  f_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|sse3
  extf_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 fpu
  extf_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 <model> 參數來指定客戶機的 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 數目的分配方法

  1. 不是客戶機的 vCPU 越多,其性能就越好,由於線程切換會耗費大量的時間;應該根據負載須要分配最少的 vCPU。
  2. 主機上的客戶機的 vCPU 總數不該該超過物理 CPU 內核總數。不超過的話,就不存在 CPU 競爭,每一個 vCPU 線程在一個物理 CPU 核上被執行;超過的話,會出現部分線程等待 CPU 以及一個 CPU 核上的線程之間的切換,這會有 overhead。
  3. 將負載分爲計算負載和 I/O 負載,對計算負載,須要分配較多的 vCPU,甚至考慮 CPU 親和性,將指定的物理 CPU 核分給給這些客戶機。

這篇文章 (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/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

也能夠在配置文件里加入:

<memoryBacking>
<hugepages/>
</memoryBacking>

驗證方式,當虛擬機正常啓動之後,在物理機裏查看:

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/

相關文章
相關標籤/搜索