Linux性能优化9:KVM环境

这一篇看KVM环境的性能优化技巧。我没有怎么做过KVM环境的调优,但后面就要开始做了,所以这一篇也只是把资料整合一下,后面会逐步补充。

KVM和Docker不同,KVM是有Hypervisor的。也就是说,一旦KVM陷入Guest中,Host是完全看不见被占用的CPU的。

这个执行模型类似这样:

这里的横坐标是CPU时间。我做了很多的简化,以便读者更容易基于一个相对稳固的模型思考相关变化。

从这个图上我们可以看到,除了掌握更多的资源(IO资源),Host的地位和Guest地位几乎是对等的。这造成一个很有趣的现象:如果我们在host上用top来看进程的CPU的占用率,Guest占掉的CPU是算在qemu头上的,因为从时间上来说,host确实看到CPU进入qemu后,就没有出来了。但如果用perf top来看,你却看不见qemu占用CPU,因为PMU的中断打进来后,如果调度到Guest中,Host是看不到这个打的点的。所以perf top的报告是qemu占用并不高。

反过来,如果我们在Guest看,top看不见Host抢去的CPU,Guest从这个角度是看不到Host或者其他Guest抢去的CPU的时间的。Perf top同样看不到,因为Guest的中断基本上都是Host种进去的,它只能统计它自己看到的点。

同时我们要知道,很多平台都没有实现Guest一侧的PMU事件,所以perf的功能在Guest中相当受限。

不过,新版本的top和vmstat都支持steal time功能了,注意一下CPU占用率中那个st的值,它表示了本VM有多少时间被Hypervisor“偷走了”:

同时,绝对时间是可以被Guest感知的,所以,如果其他Guest很忙,本Guest的执行时间会延长,感觉就好像某些指令被降低了执行速度一样。

从Host一侧跟踪KVM的行为,我们可以跟踪到进入和离开guest的时间,这个可以通过跟踪ftrace的kvm:*事件得到:

kvm_entry就是进入虚拟机的入口点,kvm_exit是离开点,里面会给出离开的原因,很大一部分会是因为中断或者IO,一旦进入IO,这部分处理的性能就是可以被Host系统监控到了,就成为我们进行性能分析的基础了。

所以,如果你处理得好,保证Guest不会做无意义的死循环,你监控Host一侧的性能,就可以监控到整个系统的性能。前面有读者问到如何分析多虚拟机情况下的性能瓶颈。我没有干过这个工作,但我想如果监控虚拟机的切换频度(用perf的ftrace event来跟,频度可以通过比如virt-io或者SR-IOV一类的方法来降低的),以及Host本地的磁盘跟踪,应该就大概可以监控到位置了。

perf(在host一侧)提供了完整的KVM跟踪功能(但很可惜,这还在开始阶段,不是所有平台都支持得好,所以,不要太以来这个特性),通过perf kvm命令提供,这个命令后面带的子命令和标准的perf一样,支持独立perf的stat, top, record, report等命令。不同的是,如果你可以指定单独跟踪host还是guest(通过--host和--guest来指定,默认是--guest)。如果跟踪的是guest,我们需要通过--guestmodules,--guestksymbols,--guestvmlinux指定Guest一侧的符号信息。前面两个可以直接从guest的/proc文件系统中取,后面是编译内核的时候生成的基础elf文件,部分发行版会提供,部分没有,你要找发行版提供商要,要不自己编译一个内核好了。

比如,这样可以启动一个完整的3秒跟踪:

sudo perf kvm --guestmodules the_modules --guestkallsyms the_kallsyms --guestvmlinux the_vmlinux --guest --host record -a -- sleep 3

如何报告,估计也不需要我来解释了。

上面这个record的例子,指定了很多符号,但并没有指定用户态程序的符号,要指定这个符号,你需要用 --guestmount指定整个guest的根文件系统,用了这个你也就不需要--guestmodules和--guestkallsyms了。一般的操作方法是通过sshfs把guest文件系统整个牟尼它到本地:

sudo sshfs -o allow_other,direct_io ken@192.168.122.84:/ /tmp/sshfs

之后指定这个/tmp/sshfs就可以了。

编辑于 2016-09-19

文章被以下专栏收录