kvm虚拟出来的虚拟机(vm)是运行在单独的一个逻辑cpu还是可以分别在各个cpu之间运行?虚拟机cpu(vcpu)是什么概念?物理机(host)怎么看待kvm和vcpu? 为了搞懂这个概念我们还是要回到命令行中看。举例说明:
我这里有一个虚拟机叫core8,它含有8个虚拟cpu它的进程编号是20736。就是说core8在host看来就是一个进程而已,这个集成的编号是20736.那么现在提出一个问题,这个core8的8个vcpu是怎么个情况呢?在哪里运行呢?这时还是得借助命令行。我们在host里使用ps指令,但是不能单纯用ps,还要借助于参数: ps -eL (e的意思是打印所有进程,L的意思是连县城也不放过)。我这里只显示一下和我们的20736进程相关的信息:
你会看到和20736相关的有九行,那么这九行是什么呢?首先第一列都是20736,第二列里只有第一行是20736,后面的都不是。那么我们这时就应该明白了,对于host来说,kvm虚拟机是一个进程(20736),虚拟机的vcpu都是这个进程衍生出来的线程。这就是为什么除了20736还有另外八行的原因。
那么我们接着询问,这八个线程是跑在同一个逻辑cpu里吗?为了回答这个问题,我们接着做实验:
还是借助于ps指令 :ps -eLo ruser,pid,ppid,lwp,psr| awk ‘{if($5==1) print $0}’。解释为:ps命令显示当前系统的进程信息的状态,它的“-e”参数用于显示所有的进程,“-L”参 数用于将线程(LWP,light-weight process)也显示出来,“-o”参数表示以用户自定义的格式输出(其中“psr”这列表示当前分配给进程运行的处理器编号,“lwp”列表示线程的 ID,“ruser”表示运行进程的用户,“pid”表示进程的ID,“ppid”表示父进程的ID,)。结合ps和 awk工具的使用,是为了分别打印出来运行在不同的逻辑cpu上的进程线程情况。上面的指令就是打印出1号(从0开始编号)cpu的进行线程情况,我们这里只列出和我们相关的:
这时看到,20736号进程衍生出来的线程只有一部分运行在逻辑cpu1上,其它的线程在其它的cpu上了。
这时就大概明白了,不同的vcpu只是不同的线程,而不同的线程是跑在不同的cpu上的。
Qemu/kvm为客户机提供一套完整的硬件系统环境,在客户机看来其所拥有的cpu即是vcpu(virtual CPU)。在KVM环境中,每个客户机都是一个标准的Linux进程(qemu进程),而每一个vCPU在宿主机中是Qemu进程派生的一个普通线程。
KVM中的一个客户机作为一个用户空间进程(qemu-kvm)运行的,它和其他普通的用户进程一样由内核来调度使其运行在物理cpu上,不过它由KVM模块控制。多个客户机就是宿主机中的多个QEMU进程,而一个客户机的多个vCPU就是一个QEMU进程中的多个线程。在客户机系统中,同样分别运行着客户机的内核和客户机的用户空间应用程序。
疑问:
KVM环境下的smp的架构是如何处理时限的,也就是cores * 2,socket * 2 ,threads * 2与 cores * 1,socket * 8,thread * 1 有什么本质的区别?
因为为虚拟机提供计算的vcpu在宿主机上实际为一个线程,线程上并不会对cores、sockets或者threads做明确区分,也就是整体设置2*2*2 和 1*8*1是没区别的。
不过在虚拟机内部,可能会有系统倾向于(服务器的设别程度)多物理插槽,或者多物理核心。(之前遇到的win2k8(非Datacenter)的情况就是,无法识别超过8个的vcpu,但是设置成2*6*1 即可实现12个vcpu的服务器)
进程的处理器亲和性和VCPU绑定
什么是进程亲和性:简单的一句话就是我这个Linux进程到底可以在哪几个cpu上做负载均衡。
KVM虚拟机是一个普通的linux进程,vcpu是一个线程,我们可以在宿主机上将vcpu线程对应的tid绑定到指定的cpu上。
用户希望把虚拟机的VCPU绑定在特定物理CPU上,VCPU只在绑定的物理CPU上调度,达到隔离VCPU并提升虚拟机性能的目的。如果没有作VCPU绑定,则虚拟机的VCPU可以在所有物理CPU上调度。
绑定vcpu到指定的cpu上,的确会提高性能,因为在vcpu的线程在物理cpu做负载均衡的时候,会有一些必要的数据结构初始化(vmlaunch)相对于VM-Entry来说是比较奢侈的,加上cache的命中,性能必然会有所提高,但破坏了负载均衡。当绑定在同一cpu上的两个vcpu同时高负载的时候,性能就会大打折扣,而其他的cpu也没有得到充分的利用。
在KVM环境中,一般并不推荐手动设置qemu进程的处理器亲和性来绑定vCPU,但是,在非常了解系统硬件架构的基础上,根据实际应用的需求,可以将其绑定到特定的CPU上,从而提高客户机中的CPU执行效率或实现CPU资源独享的隔离性。
为了实现这个功能,你首先得会 taskset命令,直观上来说,taskset就是设置任务,也就是制定任务运行的情况,是一个很好用的工具。
taskset -p [mask] pid
那么我们这里就可以使用taskset了,只需把这九个线程都绑定在同一个cpu上即可。假设我们把这个虚拟机绑定到1号cpu上:
taskset -p 2 20736
taskset -p 20740
taskset -p 20741
......
taskset -p 20747
ok,这时你再运行ps -eLo ruser,pid,ppid,lwp,psr| awk ‘{if($5==1) print $0}’,会看到形如下面的结果:
那么也就是完成了我们的虚拟机绑定任务,为了验证一下是否真正实现了绑定,我们在core8虚拟机里运行一个死循环,然后看host里的 top指令的结果:
我们可以清楚的看到1号cpu的利用率100%,而其它的cpu基本上没用到,这说明我们的绑定是成功的,完成了客户提出的需求。
Taskset命令设置某虚拟机在某个固定cpu上运行
设置某个进程pid在某个cpu上运行:
[root@test~]# taskset -p 100 95090
pid 95090's current affinity mask: 1
pid 95090's new affinity mask: 100
解释:设置95090这个进程,在cpu8上运行
95090是我提前用ps –aux|grep “虚拟机名” 找到的虚拟机进程id。
vcpupin命令设置虚拟机某个vcpu在某个固定cpu上运行
vcpupin的命令如下:
virsh vcpupin 4 0 8:绑定domain 4的vcpu 0 到物理CPU8
taskset和vcpupin区别
Taskset是以task(也就是虚拟机)为单位,也就是以虚拟机上的所有cpu为一个单位,与物理机上的cpu进行绑定,它不能指定虚拟机上的某个vcpu与物理机上某个物理cpu进行绑定,其粒度较大。
vcpupin命令就可以单独把虚拟机上的vcpu与物理机上的物理cpu进行绑定。
比如vm1和vm2都有3个vcpu(core),物理机有8个cpu(8个core,假如每个core一个线程),taskset能做到把vm2的3个vcpu同时绑定到一个或者多个cpu上,但vcpupin能把vm1的每个vcpu与每个cpu进行绑定。
libvirt实现方式
cpuset='1-2'>4
查看CPU绑定情况(其中28863为qemu的进程IP):
#grep Cpus_allowed_list /proc/28863/task/*/status/proc/28863/task/28863/status:Cpus_allowed_list: 1-2
/proc/28863/task/28864/status:Cpus_allowed_list: 1-2/proc/28863/task/28865/status:Cpus_allowed_list: 1-2/proc/28863/task/28866/status:Cpus_allowed_list: 1-2/proc/28863/task/28867/status:Cpus_allowed_list: 1-2
cputune提供了精细的vcpu绑定设定,可以具体到每个vcpu设置。而且提供vcpu能力的标准化,如quota,period,shares,可以用于实现cpu的Qos。
placement=
'static'
>
4
2048
1000000
-1
vcpu=
'0'
cpuset=
'8'
/>
vcpu=
'1'
cpuset=
'16'
/>
cpuset=
'16'
/>
参考自:
http://www.cnblogs.com/fengrenzw/p/3378344.html
http://www.linuxidc.com/Linux/2015-01/112328.htm
http://www.ckernel.org/media/ppt/2014_NFV%E5%9C%BA%E6%99%AF%E4%B8%8B%E8%99%9A%E6%8B%9F%E6%9C%BA%E9%9A%94%E7%A6%BB%E9%83%A8%E7%BD%B2.pdf
http://blog.csdn.net/u010818955/article/details/9901103
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/5/html/Virtualization/ch33s08.html