KVM优化

1
2
3
实例环境:
戴尔服务器:192.168.10.246
宿主机系统:Centos6.5 minimal 64位系统

KVM已经安装使用了一段时间,现在开始展开对KVM虚拟化方面的优化,提高虚拟机和宿主机的性能,优化可以从两个方面进行调整,一个是虚拟机上的优化,一个是对宿主机的优化,下面来分别讲讲整个优化的过程。

一、优化KVM虚拟机

1、虚拟机使用半虚拟化驱动(采用virtio驱动代替ide驱动)

virtio是KVM的半虚拟化机制,可提高IO性能,使用virtio可显著提高KVM性能。virtio包括磁盘驱动和网卡驱动

使用virtio半虚拟化驱动有两种情况:

1)已经安装了虚拟机,但是未使用virtio,修改虚拟机配置文件
1
vim /etc/libvirt/qemu/test.xml
1
2
3
4
5
6
7
修改磁盘使用virtio:
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='none'/>
<source file='/vms/kvmdisk/test.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</disk>
1
2
3
4
5
6
7
修改网卡使用virtio:
<interface type='bridge'>
<mac address='52:54:00:6e:a1:4e'/>
<source bridge='br0'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
2)新安装的虚拟机使用virtio半虚拟化驱动
1
virt-install --connect qemu:///system -n test02 -r 512 --disk path=/vms/kvmdisk/test02.qcow2,size=50,format=qcow2,bus=virtio,cache=writeback --vnc --vnclisten=192.168.10.246 --vncport=5909 --noautoconsole --vcpu=1 --network bridge=br0,model=virtio -c /vms/iso/CentOS-6.5-x86_64-minimal.iso

2、使用writeback缓存选项(如果采用raw格式的image,建议选择none,如果采用qcow2格式的image,建议选择writeback)

writethrough写操作时不使用主机的缓存,只有当主机接收到存储子系统写操作通知时,宿主机才通知客户机写操作,也就是说这是同步的。而writeback则是异步的,它是当客户机有写请求时,先将数据写入宿主机缓存,而此时主机并未将数据真正写入存储系统。之后,待合适的时机主机会真正的将数据写入存储。显然writeback会更快。

1)已经安装了虚拟机,但是未使用writeback,修改虚拟机配置文件
1
2
3
4
5
6
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='writeback'/>
<source file='/vms/kvmdisk/test.qcow2'/>
<target dev='hda' bus='virtio'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
2)新安装的虚拟机使用writeback缓存
1
virt-install --connect qemu:///system -n test02 -r 512 --disk path=/vms/kvmdisk/test02.qcow2,size=50,format=qcow2,bus=virtio,cache=writeback --vnc --vnclisten=192.168.10.246 --vncport=5909 --noautoconsole --vcpu=1 --network bridge=br0,model=virtio -c /vms/iso/CentOS-6.5-x86_64-minimal.iso

3、客户机的磁盘I/O调度策略(前提是磁盘是ssd固态硬盘)

Linux 的 I/O 调度器是一个以块式 I/O 访问存储卷的进程,有时也叫磁盘调度器。Linux I/O 调度器的工作机制是控制块设备的请求队列:确定队列中哪些 I/O 的优先级更高以及何时下发 I/O 到块设备,以此来减少磁盘寻道时间,从而提高系统的吞吐量。

目前 Linux 上有如下几种 I/O 调度算法:

1
2
3
4
1.noop - 通常用于内存存储的设备。
2.cfq - 完全公平调度器。进程平均使用IO带宽。
3.Deadline - 针对延迟的调度器,每一个 I/O,都有一个最晚执行时间。
4.Anticipatory - 启发式调度,类似 Deadline 算法,但是引入预测机制提高性能。

查看设备当前的 I/O 调度器:

1
cat /sys/block/<Disk_Name>/queue/scheduler

假设磁盘名称是 /dev/sdc:

1
2
3
cat /sys/block/sdc/queue/scheduler

noop anticipatory deadline [cfq]

如何改变硬盘设备 I/O 调度器

使用如下指令:

1
echo {SCHEDULER-NAME} >/sys/block/<Disk_Name>/queue/scheduler

比如设置 noop 调度器:

1
echo noop >/sys/block/sdc/queue/scheduler

以上设置重启后会失效,要想重启后配置仍生效,需要在内核启动参数中将 elevator=noop 写入 /boot/grub/grub.conf

客户机上的磁盘只不过是宿主机的一个文件,所以其IO调度并无太大意义,反而会影响IO效率,所以可以通过将客户机的IO调度策略设置为NOOP来提高性能。NOOP就是一个FIFO队列,不做IO调度。可以通过给内核传递一个参数来使用NOOP调度策略

在虚拟机上编辑文件:

1
vim /boot/grub/grub.conf

在kernel那行加入elevator=noop:

1
kernel /vmlinuz-2.6.32-431.el6.x86_64 ro root=/dev/mapper/vg_test-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rd_LVM_LV=vg_test/lv_root rhgb quiet elevator=noop

可以查看一下:

1
cat /sys/block/vda/queue/scheduler

PzWVVe.png

宿主机调度方式改为:deadline deadline是通过时间以及硬盘区域进行分类,这个分类和合并要求类似于noop的调度程序。确保了在一个截止时间内服务请求,默认读期限短于写期限.这样就防止了写操作因为不能被读取而饿死的现象

在宿主机上编辑文件:

1
2
3
vim /boot/grub/grub.conf

kernel /vmlinuz-2.6.32-431.el6.x86_64 ro root=/dev/mapper/vg_lianni01-lv_root rd_LVM_LV=vg_lianni01/lv_root rd_NO_LUKS nomodeset rd_NO_MD crashkernel=auto LANG=zh_CN.UTF-8 KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet elevator=deadline

二、优化KVM宿主机(内存)

1、EPT技术

EPT也就是扩展页表,这是intel开创的硬件辅助内存虚拟化技术。我们知道内存的使用,是一个逻辑地址跟物理地址转换的过程。虚拟机内部有逻辑地址转成成物理地址的过程,然后再跳出来,虚拟机这块内存又跟宿主机存在逻辑到物理的转换。有了EPT技术,那么能够将虚拟机的物理地址直接翻译为宿主机的物理地址,从而把后面那个转换过程去掉了,增加了效率。

那么这项技术,现在的服务器都支持,只要在BIOS打开了intel 的VT设置,那么这个也一起打开了。

可以使用cat /proc/cpuinfo | grep ept检查硬件是否支持EPT机制,如果支持那么KVM会自动的利用EPT

2、大页和透明大页

2.1、大页

所谓的大页指的是内存的大页面。当然,有大页面必然有对应的小页面… 我们知道内存采用的是分页机制,当初这个机制提出的时候,计算机的内存大小也就几十M,所以当时内存默认的页面大小都是4KB,那么这个4KB 也就是所谓的小页面。但是随着计算机的硬件发展,现在的内存基本上都是几十G 甚至上百G了,显然,如果还是4KB小页的方式,那么必然会存在一些问题。那么会有哪些问题呢?操作系统如果还是小页存在,那么将会产生较多的TLB Miss和缺页中断,从而大大影响性能。

为什么小页就存在较多的Miss和缺页中断呢?比如说系统里的一个应用程序需要2MB的内容,如果操作系统还是以4KB小页为单位,那么内存里就要有512个页面(512*4KB=2M),所以在TLB里就需要512个表项以及512个页表项,因此操作系统就要经历512次的TLB miss和512次的缺页中断才能将2MB的应用程序空间全部映射到物理内存里。想想,2MB内存的需要就要经历512次的操作,如果内存需求大呢?必然操作数量会大大增加,从而间接的影响性能。

如果把这个4KB变成2MB呢?那就很轻松了,一次TLB Miss和缺页中断操作就完成了,大大的增加了效率。

所以,虚拟机可以通过分配巨型页也就是刚才说的大页来提高运行性能。

查看大页信息:cat /proc/meminfo | tail -9

1
2
3
4
5
6
7
8
9
AnonHugePages:  40423424 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 7168 kB
DirectMap2M: 2019328 kB
DirectMap1G: 65011712 kB

参数说明:

1
2
3
4
5
1)AnonHugePages。匿名 HugePages 数量。HugePages_Total。HugePages 数量。空间大小为 HugePages 数乘以 2M。
2)HugePages_Free。池中尚未分配的 HugePages 数量。
3)HugePages_Rsvd。“reserved”的缩写形式,表示池中已经承诺分配但尚未分配的 HugePages 数量。保留的 HugePages 保证应用程序随时请求都能够从 HugePages 池分配 HugePages,即使系统已经运行一段时间。
4)HugePages_Surp。“surplus”的缩写形式,表示池中大于 /proc/sys/vm/nr_hugepages 中值的 HugePages 数量。剩余 HugePages 的最大数量由 /proc/sys/vm/nr_overcommit_hugepages 控制。此值为 0 的情况很常见。
5)Hugepagesize。HugePage 的大小。此参数当前为 2048 或 2 MB。

让虚拟机使用大页(单机):

查看大页情况:

PzWZUH.png

设置大页数量:

1
echo 2048 > /proc/sys/vm/nr_hugepages

PzWK2t.png

上面只是临时更改,永久生效为:

1
sysctl -w vm.nr_hugepages=2048

PzWMxP.png

挂载大页:

1
mount -t hugetlbfs hugetlbfs /dev/hugepages/

PzW1r8.png

重启libvirt:

1
service libvirtd restart

在虚拟机上查看是否开启大页:

1
cat /sys/kernel/mm/transparent_hugepage/enabled

PzWJaQ.png

然后编辑虚拟机配置文件添加内容:

1
2
3
4
5
vim /etc/libvirt/qemu/test.xml

<memoryBacking>
<hugepages/>
</memoryBacking>

PzWNPs.png

重启虚拟机,查看大页的使用情况:

1
cat /proc/meminfo | tail -9

PzWa2q.png

可以发现,HugePages_Free已经变成了1528了,那么使用了2048-1528=520个。Hugepagesize是2M,也就是每页页面的大小,使用了520个页面,那么2*520=1040M,正好跟虚拟机内存的大小1G差不多

如果想让虚拟机释放大页,那么只要把这个虚拟机关机或者删除XML里刚刚添加的配置即可。

让虚拟机使用大页(多机):

刚才的操作,我们只是针对一个虚拟机的,也就是说我们把大页面赋给了一个虚拟机。如果我们要赋予多个虚拟机怎么办?

步骤:

1
2
1)给NUMA各个node节点分配多个2MB或者1GB的大页
2)编辑虚拟机xml文件以使用node里分配好的大页

先查看宿主机NUMA有几个node节点:

1
numastat -c

PzWdx0.png

(表示只有1个)

或者也可以这么看:

1
numactl --hardware

PzW0MV.png

给宿主机各个NUMA Node节点(如果有多个)分配大页:

1
2
echo 4 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages
echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages

这两个命令的意思就是先给node0里分配4个1GB的大页,然后再给node1分配1024个2MB的大页

然后执行相关挂载操作

1
2
3
4
mkdir /dev/hugepages1G
mount -t hugetlbfs -o pagesize=1G none /dev/hugepages1G
mkdir /dev/hugepages2M
mount -t hugetlbfs -o pagesize=2M none /dev/hugepages2M

挂载成功后,重启下libvirtd服务,然后虚拟机就可以使用了,但是这里要注意的是,1GB的大页,虚拟机是不能直接使用的,需要在XML里指定。

1
2
3
4
5
6
<memoryBacking>
<hugepages/>
<page size="1" unit="G" nodeset="0-3,5"/>
<page size="2" unit="M" nodeset="4"/>
</hugepages>
</memoryBacking>

红色的部分就是要添加的参数,size是1,表示第一个使用的page;然后单位unit是G,nodeset=”0-3,5” 意思是虚拟机的NUMA node0,node1, node2 , node3和node5将使用1GB的大页 ; 虚拟机的node4将用2MB的大页。

注意:如果宿主机大页面不够用了,这样配置后,虚拟机起不来。大页文件系统需要的页面数可以由客户机需要的内存除以页面大小也就是2M来大体估算。

以上就是给虚拟机分配大页的方法。当然如果你想把宿主机的大页关闭,只要执行:

1
2
sysctl vm.nr_hugepages=0
umount hugetlbfs
2.2、透明大页

从Centos6开始,linux系统自带了一技术叫透明巨型页(transparent huge page),它允许所有的空余内存被用作缓存以提高性能,而且这个设置是默认开启的,我们不需要手动去操作。

Centos下,我们用 cat /sys/kernel/mm/transparent_hugepage/enabled 可以查看:

PzW2GR.png

我们看到这个中括号把这个always括起来了,说明这机器的透明巨型页的功能是打开的。当有512个页面可以整合的时候,就会合成一个2MB的大页;如果是在括号把never括起来了,那么就是关闭状态;madvise的话就是避免改变内存占用。

当然,如果你想改变透明巨型页的状态,比如说关闭它,那么运行下面的命令即可。

1
echo never >/sys/kernel/mm/transparent_hugepage/enabled

最后要注意的是透明巨型页跟刚才我们说的hugetlbfs 文件挂载大页是不冲突的,如果你没做任何大页的指定和挂载,那么KVM就会使用透明大页的方式。

那么说到这,大家就会疑问,既然有透明大页,我为何还要费劲的去做相关大页的指定? 其实这两种方式都差不多,区别就是一个是手动的,一个是自动的。手动的缺点就是,如果不是很熟悉宿主机的各项资源使用情况,很容易会把所有的虚拟机调整的起不来,或者是崩掉。

3、KSM技术

KSM是什么呢?KSM(Kernel SamePage Merging),也就是所谓的相同页面内存压缩技术。

KSM服务在linux系统里默认是开启的,它的作用就是让内存利用的更加高效,我们知道内存是分页的,如果多个程序中用的内存都是相同的页面,那么KSM就会把相同的内存合并,这样就能腾出更多的空间。

KSM在系统里有个守护进程,它的作用就是不断的扫描宿主机的内存情况,检测有相同的页面就会合并,当然这或多或少会消耗点CPU。

KSM特性可以让内核查找内存中完全相同的内存页然后将他们合并,并将合并后的内存页打上COW标记。KSM对KVM环境有很重要的意义,当KVM上运行许多相同系统的客户机时,客户机之间将有许多内存页是完全相同的,特别是只读的内核代码页完全可以在客户机之间共享,从而减少客户机占用的内存资源,从而可以同时运行更多的客户机。

CentOS默认没有开启KSM,如果KVM要使用KSM那必要安装:qemu-common。

如果你的环境,内存资源比较丰富,建议这个功能开不开启都无所谓;如果不够,又想跑多一点的虚拟机,那么可以打开这个功能,但是你一定要清楚,这个是一种内存超用的方案,假如你的大部分虚拟机内存变化比较频繁(比如内存使用率一下高,一下低),那么不建议开启,因为内存不够了,就会用到swap,那么这个会严重影响虚拟机性能。

下面有几个命令设置大家要了解:

1
2
3
4
5
首先是开关KSM服务(centos7)
systemctl start|stop ksmd
systemctl start|stop ksmtuned
systemctl enable|disable ksmd
systemctl enable|disable ksmtuned
1
2
3
4
5
6
7
首先是开关KSM服务(centos6)
service ksm start
service ksmtuned start
chkconfig --add ksm
chkconfig ksm on
chkconfig --add ksmtuned
chkconfig ksmtuned on

PzfmeU.png

其次是在宿主机KSM服务打开的情况下,如果不想让虚拟机受宿主机KSM的影响,那么可以这么操作:

编辑虚拟机的XML文件,添加:

1
2
3
<memoryBacking>
<nosharepages/>
</memoryBacking>

这样,这个KSM就不会去合并这个虚拟机的内存了

总的来说,用不用KSM视你自己的生产环境具体情况而定。

通过/sys/kernel/mm/ksm目录下的文件来查看内存页共享的情况,pages_shared文件中记录了KSM共享的总页面数,pages_sharing文件中记录了当前共享的页面数。每个页面的大小为4KB 可计算出共享内在为:4X页面数=内存大小(K)

KSM会稍微的影响系统性能,以效率换空间,如果系统的内存很宽裕,则无须开启KSM,如果想尽可能多的并行运行KVM客户机,则可以打开KSM。

三、优化KVM宿主机(CPU)

1、NUMA技术

在进行优化之前,我们来说说NUMA技术:

NUMA架构设计图:

PzfMFJ.png

从图中我们发现,每个CPU模块之间都是通过互联模块进行连接和信息交互,CPU都是互通互联的,同时,每个CPU模块平均划分为若干个Chip(不多于4个),每个Chip都有自己的内存控制器及内存插槽。

在NUMA中还有三个节点的概念:

1
2
3
4
1、本地节点: 对于某个节点中的所有CPU,此节点称为本地节点。
2、邻居节点:与本地节点相邻的节点称为邻居节点。
3、远端节点:非本地节点或邻居节点的节点,称为远端节点。
邻居节点和远端节点,都称作非本地节点(Off Node)。

这里要注意的是,CPU访问不同类型节点内存的速度是不相同的,访问本地节点的速度最快,访问远端节点的速度最慢,即访问速度与节点的距离有关,距离越远访问速度越慢,此距离称作Node Distance。正是因为有这个特点,所以我们的应用程序要尽量的减少不通CPU模块之间的交互,也就是说,如果你的应用程序能有方法固定在一个CPU模块里,那么你的应用的性能将会有很大的提升。

PzfQY9.png

因此KVM也是一样,我们在CPU优化这块就是要让KVM绑定在指定的CPU上,这样减少跨CPU的交互使用,让KVM的性能提升。现在我们的服务器还有linux操作系统都是默认走NUMA模式,所以我们接下来说说如何去做CPU的绑定。

2、CPU绑定

我们先查看一下CPU的各项信息:

1
lscpu

Pzf8Qx.png

我们可以看到,这台服务器只有1个NUMA node节点,16核,1核两个线程(超线程),1个CPU。

1
numactl --hardware

PzfJOK.png

这台服务器得node0节点有65314MB内存可以使用,大概62G。

1
numastat -c qemu-kvm

PzfdFH.png

查看qemu-kvm这个进程在cpu的NUMA内存使用情况,默认单位是MB,如果有多个CPU,会发现是自动均匀分配的,系统会自动的调配numa的内存使用,以求一个平衡。

当然,这个设置是可以关闭的:

1
2
关闭:echo 0 > /proc/sys/kernel/numa_balancing
开启:echo 1 > /proc/sys/kernel/numa_balancing

好了,到这我们大概查看了NUMA的基本状态和使用情况,废话不多说,接下来进行CPU的绑定操作:

A.绑定之前看看有多少台虚拟机:
1
virsh list --all

Pzf0fA.png

算是7台吧,最后一台只是测试使用,一会就会删除。7台,CPU是16核,那就是16/7=2……大概是一台虚拟机使用两核,这样就好办了,我们进行下一步。

B.查看虚拟机的虚拟vcpu对应宿主机的物理cpu
1
virsh vcpuinfo lianni04

Pzfrlt.png

这个虚拟机是4核的,然后分别跑在物理机的0、1、9、2CPU上,使用的时间3964.3s等,最后一个是CPU的亲和性,这个yyyyy表示使用物理CPU内部的逻辑核,一个y代表其中一个CPU逻辑核。全部是y,那么就说明这台物理机的16个cpu核,这台虚拟机的cpu全部都能调度使用。

C.分别绑定CPU

从上面我们知道,由于没有绑定CPU,所有虚拟机的虚拟vcpu可以任意调度物理机的cpu,这样就无法达到最快的运行速度,所以,我们接下来把虚拟机的运行都绑定到指定的cpu上运行,减少上下文切换等开销,避免NUMA中提到的使用远端节点。

把lianni03这台机器绑定到14-15CPU上:

1
virsh emulatorpin lianni03 14-15 –live

查看是否设置成功:

1
virsh dumpxml lianni03

Pzfs6P.png

把lianni04这台机器绑定到12-13CPU上:

1
virsh emulatorpin lianni04 12-13 --live

把lianni02这台机器绑定到10-11CPU上:

1
virsh emulatorpin lianni02 10-11 –live

把zentaopms7.1这台机器绑定到8-9CPU上:

1
virsh emulatorpin zentaopms7.1 8-9 --live

把gitolite这台机器绑定到6-7CPU上:

1
virsh emulatorpin gitolite 6-7 --live

把svn这台机器绑定到4-5CPU上:

1
virsh emulatorpin svn 4-5 --live

把gitlab这台机器绑定到2-3CPU上:

1
virsh emulatorpin gitlab 2-3 --live

那么有的人会疑问了,一个虚拟机我有两个vCPU, 比如这个Win7 ,它就是双核的,我想让里面的vCPU1和vCPU2分别绑定在不同的物理CPU上可以吗?怎么操作呢?这也是可以的,我们通过下面的方法可以进行相关的vCPU分别绑定

1
2
3
virsh vcpupin Win7 0 22
virsh vcpupin Win7 1 23
virsh dumpxml Win

Pzfcm8.png

OK,这里要注意的是,你把虚拟机用reboot重启,这个绑定配置还是生效的,但是你在宿主机shutdown的话,CPU绑定的效果会失效。我们要让VM关机然后起来也生效,就必须把参数写入到虚拟机的XML里,然后保存,这样关机了也不会失效

1
2
3
4
5
virsh edit lianni02

<cputune>
<emulatorpin cpuset='10-11'/>
</cputune>

PzfWkQ.png

D.其实还可以使用taskset绑定虚拟机的进程到某个或者某几个cpu上

也可以使用这种方式,但是这种方式虚拟机重启之后进程号就变了,之前的设置就无法生效,所以这里不讲解,示范一下即可:

假如kvm虚拟机的进程号是8598,我把它绑定到1号cpu上运行:

1
taskset -cp 1 8598

把它绑定到1号和2号运行,让它只能在这两个cpu之间运行:

1
taskset -cp 1,2 8598

总结

其实KVM的使用,很多需要优化的方面linux内核已经默认都给我们启用了,即使我们再去进行个别小方面的优化,其效果必然也不是特别的大,就比如vmware、vbox这些虚拟化软件,很少有去优化这些软件的,需要优化的,往往是宿主机本身,而不是针对应用或者软件去优化。

本文中提到的优化点有:

1
2
3
4
5
6
7
1)半虚拟化驱动virtio			#优化效果不明显
2)缓存选项writeback #这得看磁盘是raw还是qcow2,效果不明显
3)磁盘I/O调度策略noop #前提是磁盘是ssd固态硬盘
4)硬件辅助内存EPT技术 #默认已开启
5)大页和透明大页 #默认已开启透明大页,无需手动开启大页
6)相同页面内存压缩技术KSM #以效率换内存,如果要效率,则不要打开
7)CPU亲和力绑定 #值得优化

从上边可以看出,整篇文章中提到的优化点,除了第7点,别的地方优化需求可有可无,说到底,需要优化的,还是宿主机本身。

参考文章:

1
https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/6/html/performance_tuning_guide/ch04s04s02
博主QQ:1012405802
技术交流QQ群:830339411
版权声明:网站内容有原创和转载,如有侵权,请联系删除,谢谢!!
感谢打赏,93bok因你们而精彩!!(支付宝支持花呗)
0%