本次测试是针对KVM虚拟化在CPU、内存、磁盘、网络4大方面的全面性能测试与性能优化实践,目的在于经过对比测试,找出最适合咱们所使用的硬件与软件架构的最佳优化配置,为OpenStack实现更高的性能提供支持。linux
本次测试中,咱们将经过OpenStack平台做为虚拟机管理工具,而且全部的用于测试的虚拟机都均运行在同一台物理机上:算法
下面介绍一下本次测试的主机的软件环境:缓存
以上就是本次KVM虚拟化测试所在主机的软件环境,其中值得注意的是Kvm和Libvirt的版本。性能优化
为了保证测试的科学严谨性,咱们将选用同等规格的KVM虚拟机,在openstack中咱们统一选用m1.small规格,即1颗vCPU、2G内存、系统磁盘为20G。架构
咱们的虚拟机统一经过openstack来作建立、终止等操做,这样既保证了建立等操做不会由于人为操做失误而产生误差,同时也使本次测试的结果为OpenStack的Hypervisor选型提供参考。
在虚拟化技术的发展过程当中,咱们能够看到也是CPU技术飞速发展的阶段,同时,这也说明了虚拟化对于CPU的要求是硬性的,即很难经过更加优秀的策略和算法来大量地提高性能。
可是,在这个追求高效低碳的时代,性能上的一点点提高都是值得咱们去努力探索的。
在KVM虚拟化的CPU使用机制中,虚拟机的vCPU在虚拟机内部实现的各类调度对于宿主机的CPU是透明,每一个vCPU对于物理CPU来讲仅仅至关于一个进程,经过不一样虚拟机不一样优先级的状况来将CPU的核心分配给vCPU独占使用。
这样,咱们不由想知道,在KVM虚拟机中使用vCPU和宿主机中使用物理CPU,中间的性能损失有多少呢?
下面,咱们将利用一个由C++编写的“找出1-1千万之内的质数”程序,在虚拟机和宿主机中分别进行测试,利用time工具查看他们分别须要多少的时间,以此来判断CPU的性能。
值得注意的是,咱们的虚拟机分配了1颗vCPU,可是因为咱们编写的测试程序是单线程的,因此在宿主机和虚拟机中运行都只能使用到1颗CPU核心,保证了测试的严谨性。
而且,该程序不会由于内存问题而使得宿主机和虚拟机的测试产生误差,由于对于改程序来讲其须要的内存在虚拟机上也是彻底知足的。
如下是测试所用程序的源码:
#include<iostream> #include<math.h> using namespace std; static int num=100000000; int main(){ bool *array=new bool[num+1]; array[0]=false; array[1]=false; for(int i=2;i<=num;i++) array[i]=true; int b=int(pow(num,0.5))+1; int index=0; for(int j=2;j<=b;j++){ index=2*j; while(index<=num){ array[index]=false; index+=j; } } delete array; cout<<endl<<"===========Done!==========="<<endl; return 0; }
为了使数据更加有参考意义,咱们将分别测试找出不一样数量的质数,如1百万之内、1千万之内、1亿之内的质数。
首先,咱们在虚拟机中运行测试程序:
接下来,咱们在宿主机运行测试程序:
以上的测试数据都通过了3次测试,而且取平均值,以保证测试数据的可靠性。咱们将以上两部分的测试结果汇总以下:
从以上数据咱们能够看到在1百万和1千万两次测试中,虚拟机和宿主机的性能几乎是没有损失的,可是到了1亿数据测试时,在性能表现上出现了巨大的变化,针对这样的结果,咱们在虚拟中利用vmstat监控CPU的状态。
上图是虚拟机中执行1千万数据测试的状态,在查找过程当中,虚拟机CPU使用率大约在30%-50%,CPU没有达到满负荷。
上图是虚拟机执行1亿数据测试的vmstat状态,咱们能够看到虚拟机CPU持续地保持在100%的负载,此时则说明该测试已经到了虚拟机CPU的性能天花板,这样的性能表现不是由于宿主机的资源抢占形成的。
为了证实虚拟机在1亿数据量时的性能降低不是宿主机资源抢占形成的,咱们将同时在宿主机和虚拟机上运行测试程序。
如下是宿主机和虚拟机同时运行测试程序的测试数据:
从以上数据可知,宿主机与虚拟机同时运行时的表现和单独运行几乎是没有误差的,而宿主机上的CPU为何没有不会像虚拟机中那样满负荷呢?多是因为CPU自身的调度机制,这里不深究。
因为1亿的数据量对于单vCPU的虚拟机来讲已经到了性能瓶颈,不能对比体现虚拟机与宿主机使用CPU的性能损耗,故不能做为对比的数据。
咱们将以上的数据汇总并生成条形图,能够看到KVM虚拟机对于物理机的CPU损失很是小,这也是彻底虚拟化最大的优势之一。
近年来的虚拟化技术的发展中,针对内存方面的探索明显比其余方面要多,由于内存每每决定了虚拟机的运行性能,当宿主机须要使用swap交换分区来为虚拟机分配内存的时候,则虚拟机的性能将急速降低。
下面咱们针对应用面最广的KSM内存页共享和HugePage大页技术来进行性能测试分析和优化的实践。
在咱们选用一款虚拟化产品以前,咱们最但愿了解的是虚拟机中的CPU与内存跟物理机相比,性能将损失多少,其损失的性能是咱们所能接受的吗?
针对这样的问题,咱们将对虚拟机和宿主机进行内存测试,咱们采用了一款功能强大的内存质量测试工具:memtester。你能够指定要用于测试的内存大小,例如100M,memtester会从可用内存中抓取100M内存,进行各项测试运算,包括随机值写入、乘法、除法、异或比较、与或运算等等。咱们利用time工具统计内存测试完成的时间,经过比较时间来看内存性能。
首先,咱们须要在测试用虚拟机和宿主机中分别安装memtester软件:
# apt-get install memtester
咱们分别抓取10M、100M、1000M的内存做为测试的内存大小,每一个测试重复测试3次,取平均值。
如下是虚拟机中的测试数据:
以相同的方法在宿主机上测试,获得以下数据:
将虚拟机和宿主机的测试数据汇总,获得以下表格,完成所有内存测试项目用时最少的代表性能越好。
以上是由测试数据生成的图表,咱们能够看到,对于虚拟机来讲,的确会对内存产生部分的性能损耗,对于KVM虚拟化来讲,CPU的性能是十分微小的,由于KVM彻底虚拟机的内部机制决定了它在CPU方面的表现,可是KVM的内存调度并无太大的改进,彻底虚拟化的内存调度不须要经过OS,而是直接由Hypervisor直接从内存中获取,这样的机制相比半虚拟化有部分的性能提高。
本次内存性能测试中,咱们的结论是,KVM虚拟化产品的内存与物理机内存相比,其性能损失大约在10%如下,这样的表现对于虚拟化产品来讲是比较出色的。
KSM(KernelSamepage Merging)即内存页共享机制。页共享早已有之,linux中称之为COW(copyon write)。Linux 2.6.32内核以后又引入了KSM。KSM的主要特性是可让内核查找内存中彻底相同的内存页而后将他们合并起来,并将合并后的内存页打上COW标记。KSM对KVM环境有很重要的意义,当KVM上运行许多相同系统的虚拟机时,虚拟机之间将有许多内存页是彻底相同的,特别是只读的加载在内存中的内核代码页,彻底能够在虚拟机之间共享,从而减小虚拟机占用的内存资源,从而使得宿主机能够同时运行更多的虚拟机。
咱们在宿主机上运行10个虚拟机,统一采用OpenStack中的Small硬件规格,在没有开启KSM的状况下,咱们监控宿主机CPU的负载状况,以后开启KSM功能,并设置KSM持续刷新,同时继续监控宿主机CPU负载,以此对比得出KSM功能对CPU负载会有多大的影响。
本次测试咱们使用sar工具来实时查看宿主机的CPU负载信息,当10台虚拟机彻底启动以后,咱们在宿主机上运行一段时间的sar,抓取没有开启KSM的CPU负载,取平均值。
首先,咱们须要在OpenStack中利用Dashboard图形化界面从同一个镜像文件启动10台虚拟机实例。
所有的虚拟机实例启动完成以后,咱们使用sar工具每一个2秒一次CPU负载信息,抓取20次,将当前宿主机CPU空闲率取平均值。
最后得出,当前宿主机CPU空闲率为96.86%。
接下来,咱们开启KSM功能,在Debian中默认没有开启KSM功能,须要咱们手动开启:
# echo 1 > /sys/kernel/mm/ksm/run
/sys/kernel/mm/ksm/目录就是KSM模块所在的位置,针对KSM的全部设置都只能在这里把数据echo进去,/sys/kernel/mm/ksm/run是用于控制是否开启KSM功能的文件,“1”表示开启,“0”表示关闭。
同时,/sys/kernel/mm/ksm/目录下还有不少其余的用于精细化配置的文件,例如/sys/kernel/mm/ksm/sleep_millisecs,此文件用于指定KSM查找相同内存页的时间间隔。
为了测试出KSM对于宿主机CPU负载的影响,咱们将KSM查找相同内存页的时间间隔设置为“0”,即KSM会不停地在内存中查找有没有相同的内存页。设置方法以下:
# echo 0 >/sys/kernel/mm/ksm/sleep_millisecs
设置完成后,咱们使用sar监控CPU负载的变化:
通过计算,当前宿主机CPU空闲率为95.12%。
如下是关闭KSM和开启KSM状况下的CPU负载图表,这样能使咱们更加直观地看出对比。
咱们能够得出,开启KSM以后会比关闭KSM的CPU负载高1.74%。可是这样的数据是在宿主机的虚拟机数量较少,而且全部虚拟机都处于空闲状态,因此真实环境下负载的提升是跟虚拟机以及业务有关的,根据官方数据,在生产环境下开启KSM,其会占用的CPU负载大概为3%-10%。
这是一个极限测试,可是在真实应用中,咱们每每会根据宿主机的软件硬件状况设置不一样的时间间隔,尽可能减小KSM对宿主机CPU负载的负担,同时KSM项目组也在积极努力以使得KSM能占用更少的CPU。
作完以上的测试分析,新的问题立刻浮出了水面:咱们到底要不要开启KSM呢?
咱们知道,KSM机制最根本的目的在于使得一个宿主机能尽量多地运行更多的虚拟机。若是你的虚拟化架构须要运行尽可能多的虚拟机,例如IDC商,那么开启KSM会是一个十分不错的选择;若是你更多的是追求虚拟机有更高的性能,内存不是大家的稀缺资源,而且不但愿KSM加大了宿主机的负载,那么请关闭KSM。
对于OpenStack的应用来讲,每每运算节点上运行着众多由同一个镜像启动起来的虚拟机实例,这种状况开启KSM是十分有利的,而且根据咱们的测试,KSM对于宿主机的影响是比较轻微的,咱们能够根据宿主机的CPU性能、内存大小、预计运行虚拟机数量来设置KSM查找相同内存页的时间间隔,以此来控制KSM对宿主机的影响。
值得注意的是:国人对KSM作了进一步优化,发布了UKSM(UltraKSM)项目,听说比KSM扫描更全面,扫描页面速度更快,并且CPU占用率更低,目前此项目已经能在Fedora和Ubuntu的源中使用。
Huge Page,有人称为巨页,也能够称为大页。x86架构一般使用4K内存页,但也有能力使用更大的内存页,x86_32可使用4MB内存页,x86_64和x86_32PAE可使用2MB内存页。
x86内存使用多级页表结构,通常有三级:页目录表、页表、页。咱们经过使用大页,能够减小页目录表和页表对内存的消耗。经过为虚拟机提供大页的后端内存,能够减小虚拟机消耗的内存并提升内存TLB(页表缓存)命中率,从而提高KVM性能。
下面介绍一下测试环境。咱们依然在hz188-139宿主机上进行所有的测试,虚拟机在OpenStack建立,规格为m1.Small。
咱们首先在没有配置HugePage的状况下,利用内存测试工具memtester对虚拟机中的内存进行测试,以后配置开启HugePage大页功能,再在虚拟机中作一样的测试,以后汇总结果进行分析。
每一个测试测试3次,取平均值。
如下是咱们在宿主机上配置HugePage大页的操做:
# mkdir /dev/hugepage
查看hugepage的相关内核参数:
# sysctl -a | grep -i huge
其中的“vm.nr_hugepages”参数是指用户大页的页面数,在设置咱们要开启的大页数以前,须要查看一下当前系统HugePage的大小:
# cat /proc/meminfo | grep -i huge
咱们能够看到当前系统的大页为2M,而设置开启大页数量是一门大学问,由于大页是常驻内存的,咱们要严谨地分析、合理地规划,确保不会影响宿主机系统的性能,同时又让KVM能最大限度地使用大页。
咱们将要设置的参数写入到sysctl.conf文件中:
# vi /etc/sysctl.conf
# sysctl -p | grep huge
接下来挂载hugepage虚拟文件系统:
# mount -t hugetlbfs hugetlbfs/dev/hugepage
为了使hugepage的设置开机自启动,咱们须要把挂载信息写入到fatab中。
当咱们须要建立KVM虚拟机的时候,咱们须要手动地用“-mem-path”参数来指定hugepage虚拟文件系统的地址,让KVM经过hugepage获取内存。
在咱们能够在/proc/meminfo中查看“HugePages_Total”和“HugePages_Free”项,能够直观地看到当前宿主机上hugepage的使用状况。
咱们的测试将利用memtester做为测试工具,在虚拟机内部,当咱们须要使用内存时,KVM会经过必定的机制去申请获取物理内存,而普通状况下换入换出的内存页大小为4K,当咱们设置使用大页以后,KVM虚拟机就会直接经过大页来申请内存,这时的内存页大小为2M。Memtester中的内存质量测试都会是同样的,惟独在申请内存及使用时,普通的方式和经过大页的方式有所区别,因此咱们能够经过完成memtester的时间做为一个衡量的标尺。
如下是普通内存分配方式下的测试数据:
如下是Huge Page内存分配方式下的测试数据:
下面,咱们将以上的两组数据汇总以下:
根据以上的测试数据,咱们能够看到使用了HugePage的内存分配机制以后,测试时间有了必定程度的缩短,这就说明hugepage比传统X86的内存页大得多而使得测试过程当中节省了大量的内存页分配时间。
可是,设置Hugepage以后这部分的内存会直接被其占用管理,也就是说操做系统没法再对这部份内存作任何操做,因此在设置Hugepage的时候咱们须要合理地作好规划,尽可能提高Hugepage带来的优势。
相对于CPU和内存的发展步伐,硬盘技术的发展确实是不给力。因此在现今的企业IT架构中,每每磁盘I/O才是真正的瓶颈。对于虚拟化来讲,磁盘性能也直接影响着虚拟机的性能。
下面咱们将针对两种最多见的虚拟机磁盘镜像格式:Qcow2和Raw,一个是COW(Copyon Write)设备,一个是RAW设备。根据咱们以往的了解,咱们知道qcow2格式的镜像占用空间小,这也是全部COW设备的优势,而RAW设备则是彻底的磁盘大小,可是听说读写性能优于Qcow2。
下面就让咱们经过严谨的测试分析,找到最适合咱们使用的镜像格式,从而总体提高OpenStack的性能。
本次测试咱们主要围绕着从虚拟机中读取和写入数据时,不一样磁盘文件的读写性能表现。咱们将在同一台宿主机上开启两台彻底相同规格的虚拟机,他们采用统一的镜像,只是利用qemu-img转换了镜像的格式。
咱们分别以100M、500M、1000M为单位在不一样格式的虚拟机上作读取数据和写入数据的操做,利用time统计操做的时间,以此来对比不一样磁盘格式的虚拟机读写数据的性能。
在Qcow2磁盘格式的虚拟机中,咱们利用dd工具从随机数中写入到某个文件中,经过time来统计完成时间。
如下是测试数据统计表:
接下来,咱们在RAW磁盘格式的虚拟机中执行相同的测试,利用time统计完成时间,数值越小表示性能越好,数据以下:
根据以上两种磁盘格式的测试结果,咱们能够将数据汇总起来,并造成更加直观的图表:
将两种磁盘格式的读性能数据汇总起来,造成图表如上。
能够看到RAW格式的读性能是彻底优于Qcow2格式的,因此若是咱们的镜像存储再也不须要考虑镜像占用空间大小的话,RAW格式能够提供更加优秀的读性能。
将两种磁盘格式的写性能数据汇总起来,造成图表如上。
相对于读性能的差距,写性能的对比相对没有这么明显,可是在写性能方面,依然是RAW格式具备更好的性能。
根据以上的读写测试与分析,咱们能够知道RAW设备是优于Qcow2设备的,可是咱们考虑技术的选型不该该仅仅从性能出发,例如当咱们须要考虑到镜像存储的容量问题时、当咱们须要考虑虚拟机启动加载问题时,在Openstack中运算节点启动虚拟机须要先从镜像池中拷贝一份备份,以后再从运算节点上启动,这样Qcow2格式的特色显然能使启动速度提高一个档次。
具体的选型须要全面的分析和规划。
对于全部的虚拟化来讲,其所得到的资源都是来自硬件的,只是利用资源利用的机制,提升了资源利用率。一样地,虚拟化的网络性能与宿主机的网卡性能和吞吐率也是直接关联的,因此在网络方面咱们能够调整的并很少。
下面咱们将针对KVM中的virtIO驱动器进行测试,KVM默认的I/O驱动为IDE,而virtIO驱动因为其机制上的创新而具备更高的性能,那么virtIO究竟能为咱们提高多少性能呢?
首先,你们必定很想知道什么是virtIO?
虚拟化的方方面面都在高速发展,惟有I/O部分始终难以突破。如何让Hypervisor可以在I/O虚拟化方面充分地利用底层内核呢?答案是使用virtio驱动,它为hypervisor提供一组通用的 I/O 虚拟化驱动程序,提供高效的抽象。
如上图,VirtIO实际上是一个基于半虚拟化的产品,在KVM的应用中,virtIO会在Qemu空间内为虚拟机提供一个I/O虚拟的前端,而在Hypervisor上提供一个后端和设备虚拟的功能,这样虚拟机与宿主机之间的I/O通讯就再也不是经过Hypervisor的物理信号模拟(效率低),而是经过virtIO的机制进行通讯,大大提升了I/O效率。
本次测试咱们将分为虚拟机与物理机之间的数据传输、虚拟机与虚拟机之间的数据传输。固然,本次测试环境中虚拟机与物理机都是处于同一个局域网的,保证测试环境的一致性。
下面,咱们首先在不开启virtIO的状况下作数据传输测试,咱们利用dd命令建立了一个1G大小的文件,咱们将使用scp命令进行传输,利用time工具计算整个传输过程所使用的时间,以后计算出本次传输的平均传输速率。
如下是未使用VirtIO驱动的测试数据:
如下是使用了VirtIO驱动的测试数据:
咱们将上面两组数据进行汇总,获得如上数据对比表。经过传输的速率咱们能够看到,使用了VirtIO以后的传输速率获得了惊人的提高,下面咱们将数据造成图表,以下。
根据以上的图表,咱们看到开启VirtIO以后,不管是虚拟机与虚拟机、物理机与虚拟机之间的数据传输速率相差很少,这也是VirtIO的主要特色之一。在咱们本次测试中,传输速率大概在27MB/s,这样速度在千兆网卡的环境下已是超凡的表现了。
根据以上的测试和分析,咱们知道使用VirtIO驱动是有百利无一害的,由于VirtIO的机制使得KVM这类彻底虚拟化产品最大的弊端以及企业级应用中最大的瓶颈获得解决。
因此在OpenStack系统中,咱们须要在nova.conf主配置文件中加入VirtIO的相关参数“libvirt_use_virtio_for_bridges=True”,这样将为各节点之间链接的网桥启用VirtIO,极大提高I/O性能。
至此,本次KVM虚拟化性能测试与优化实践完结了。经过本次CPU、内存、磁盘、网络4方面的测试分析,咱们更加深刻地了解了KVM的性能,同时也找到了一些适合生产环境使用的强悍的技术。
性能优化的工做并非作简单的性能测试,更重要的是在实际的生产环境中,在真实的线上压力下,全面测试性能和稳定性,根据咱们业务的需求找到最适合咱们的技术,这才是性能优化的根本宗旨。