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/

相关文章
相关标签/搜索