前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于KVM虚拟化的混合部署

基于KVM虚拟化的混合部署

作者头像
皮振伟
发布2019-11-12 18:16:14
1.9K0
发布2019-11-12 18:16:14
举报
文章被收录于专栏:皮振伟的专栏皮振伟的专栏

前言

KVM forum 2019上,作者和同事的演讲主题是《How KVM-based Hybrid Deployment Powers Bytedance’s Biggest Day Ever》。 在这里详细展开一下,介绍一下基于KVM虚拟化的混合部署。下文的脉络大约是: 1,业务背景 2,为什么使用KVM虚拟化方案 3,在使用KVM虚拟化方案的过程中,我们做了那些改进 4,基于KVM虚拟化的混合部署方案取得了怎样的效果

业务背景

对象存储服务(OSS)是典型的IO密集型的业务,对CPU&MEM、甚至是网络消耗都比较低,在存放冷数据的服务器上,CPU的使用率甚至不足5%。 典型的在线业务一般是网络应答式,接收网络请求,处理后返回结果,一般是CPU/MEM密集型,IO消耗一般是业务写log,网络流量一般也不高。 可见,二者的业务特征具有一定的互补性,可以尝试把两种业务进行混合部署。

为什么选择虚拟化

混合部署一直以来都是一个长期讨论、实践的主题。之前,有很多基于cgroup/docker的混合部署的文章和总结也给我们提供了大量的参考,其中有技术改进、最佳实践以及对未来的思考等等。然而,作者所在的团队最终选择了KVM虚拟化方案,原因是KVM虚拟化提供了更高的隔离性,总结如下。

CPU的隔离性问题

写一段代码,16线程并行执行,配置cgroup为4 CPU的quota。使用top -d 1查看,可以发现CPU的消耗基本在400%左右。我们使用脚本收集数据,以1s为粒度,可以看到效果如下:

如果把时间粒度改成10ms收集一次,可以看到如下效果:

由此可见,Linux本身的调度基于tick实现,cgroup可以保证在一个相对较长的实践范围内实现比较好的CPU限制,但是在较细的粒度上是无法保证的。(详细代码和数据可以参考前文《Cgroup CPU Quota技术的不足》)。 我们继续以MySQL为例,在server端启动mysqld进程,在client端启动sysbench压测。同时启动上述的示例代码,设置quota是4 CPU,理论上来说,在12 CPU的服务器上,应该不会对mysql的性能产生非常大的影响。然而实验效果如下:

在19s ~ 29s之间,mysqld的TPS发生了比较剧烈的抖动。 对比实验KVM,启动一台4 vCPU的虚拟机,在虚拟机内部运行上述的示例进程,监控qemu进程的CPU消耗,无论在1s还是10ms级别,CPU消耗始终不会超过400%。TPS有所降低,但是非常稳定。 收集延迟的PCT99在虚拟机中更加稳定,对比如下:

调度模型对比

作者知道的几种在线业务模型:

python业务:由于python是单线程模型,有的业务会选择使用CGI模型,fork起来多个进程(通常是1K量级)。也有python框架实现了异步IO,会启动较少的进程。还有会调用c库,创建起来多个线程。 golang业务:多协程下面有多线程。 java业务:多线程,锁住大块内存。 C/C++业务:多线程,有可能伴随着大量的内存分配/回收。 当然还有更多的不知道的业务场景,由于无法预测在线业务的类型,也无法预测在线业务的workload,就很难有一种适配所有场景的进程隔离方式和内核调度策略。在虚拟化场景下,调度模型就会变得非常简单:在宿主机上仅仅有有限的vCPU线程,通常一个36核的虚拟机仅仅有36个vCPU线程、一个QEMU主线程、有限个数的IO thread、vnc thread等不到50个thread。取得的效果是把大约1K以上的业务Task转换成了大约50个虚拟机的Task。 把复杂的业务调度模型放到虚拟机内部中去,在通过一定的CPU亲和性隔离,宿主机上运行的OSS业务的QoS很容易获得了调度上的保证。

内存模型对比

在Linux服务器上,通常有文件映射(page cache)、匿名映射、free memory、slab内存,内核管理这些内存,维持着各个NUMA node的各个zone的内存分配/回收。且有了cgroup的内存管理之后,内存管理的复杂度进一步提升。 在cgroup/容器隔离的场景下,由于上文提到的业务类型很多,导致服务器上的内存模型相当复杂,且难以预测。

在KVM虚拟化场景下,则会变得简单,对于一台虚拟机,仅仅使用匿名映射,且PC-RAM内存可以使用大页,尤其是HugeTLB隔离出来的内存不再受到Host上的buddy system管理,Host上的内存管理成本几乎没有任何的影响。

磁盘IO的隔离对比

Linux目前无法很好的支持page cache隔离(最新的Linux upstream上开始有些支持,但是效果不好。且目前的LTS版本中都没有支持),page cache隔离不好就很难做好磁盘的IO隔离。 另外,还有一些隐式的竞争,在mysql使用的数据库的分区(EXT4)上,删除一个较大的文件,mysql的TPS会发生一次抖动,效果如下:

尽管删除一个文件,不会涉及到文件的数据IO,但是因为删除inode,修改了meta data,EXT4会记录journal,而一个文件系统分区只有一个journal线程,这里是串行执行会成为瓶颈。大一些的文件通常会大一点的meta data,会使用较长的时间。在这段时间内,mysql的Create/Update/Delete操作都可能涉及到meta操作,就会产生抖动。 在虚拟化的场景,可以使用裸磁盘分区通过Block访问的方式提供给虚拟机使用。Host上将不再需要文件系统的参与,甚至可以给虚拟机挂载远程盘。同时QEMU对虚拟块设备的IO限速有很好的支持,通过bandwidth和IOPS两个维度的限速,可以让Host进程对盘的访问依然稳定。 同样的测试场景在虚拟机中的表现很好,mysql的TPS和延迟几乎看不到差异。

网络IO的隔离对比

在cgroup/容易的场景下,OSS和业务进程共享整个Host服务器的内核和网卡硬件。目前内核还不能有效的控制每个进程/一组进程的网络IO的bandwidth和PPS。例如在线业务在拉取docker镜像的时候,会有一个大的网络IO的突刺,OSS的QoS有可能会受到影响。甚至在线业务使用过多的本地端口会影响OSS对外部服务的访问。 在虚拟化场景下,使用SR-IOV的方式分配出来一个网卡的virtual function,把VF透传给虚拟机,对VF进行硬件的bandwidth和PPS限速,且Host和Guest分别是两个完全独立的网络协议栈,二者之间没有任何干扰。稍微麻烦一点的地方就是需要额外配置TOR,控制好分配的IP。当然,使用overlay网络也是可行的。

内核版本的差异对比

在cgroup/容器场景下,因为共享同一个内核,所以必须使用相同的内核版本。对于OSS,一般对kernel版本要求不高,且希望稳定不间断的运行。而对于在线业务,尤其是涉及到cgroup/容器之后,对内核版本通常有更高版本的要求。 在虚拟化场景下,Host可以在不做改动的情况下,动态加载kvm的kmod到内核中,启动虚拟机。在虚拟机中,可以运行任何版本的内核,甚至windows。

对虚拟化的改进 --- kvm-utils

在混合部署的场景下,Host通常是在线运行的,且不能升级内核/kmod。但是debug依然是必要的,为此,开发了kvm-utils工具,用来分析虚拟化的性能问题。kvm-utils的debug功能基于kprobe,可以动态的安装/卸载。分析vm-exit功能的效果如下:

分析wrmsr exit的效果如下:

kvm-utils还包含microbenchmark功能,能够测试PIO/MMIO/TIMER/IPI的消耗的时钟周期。软件很快将会开源在https://github.com/bytedance。

使用kvm-utils可以帮助分析很多性能问题,例如: 例子一,业务侧反馈说gettimeofday消耗的时间比正常偏高,kvm-utils可以发现PIO变多了。分析下来发现Guest内部的时钟源异常导致。因为关掉了kvm-clock,希望使用tsc作为默认时钟源,但是因为缺少了tsc reliable的参数,导致guest里面误认为tsc不稳定,自动切换到了acpi-pm导致的问题。

例子二,虚拟机内部的业务的QPS低于物理机,kvm-utils发现wrmsr TSC DEADLINE vm-exit超过了1M/s。后来发现是tcp的拥塞算法使用了bbr设置了太多的timer导致。

对虚拟化的改进 --- nohlt_list

作者使用的环境下,Host上有48个CPU,其中12个预留给OSS业务,于是启动了36 vCPU的虚拟机。 网卡VF有8队列,在虚拟机内部通常把中断亲和性绑定到CPU 0~7上。每秒钟大约150K ~ 500K左右的网络中断。那么平均单核每秒的中断数量大约在20K~60K左右,这样的数据量不足以让vCPU 0~7一直处于忙碌状态,所以vCPU进程需要执行idle任务,从而运行HLT指令而发生vm-exit。下一个网络报文到达VF后,vCPU将会被Posted-Interrupt Wakeup Event唤醒,重新进入none-root模式。

不断的HLT退出到PIW唤醒导致虚拟机处理中断的延迟不稳定,业务的延迟也会有偶尔的抖动。 当前内核中支持nohlt或者idle=poll模式,就会让所有的vCPU一直处理polling模式,不会执行HLT指令退出,但是这也意味着在Host上看到所有的vCPU thread都是100%的CPU消耗状态,这对于混合部署来说是不友好的。同时,这种polling会损害 CPU的另外Hyper-Thread的性能。

为此,作者开发了nohlt_list功能:允许一部分CPU跑在polling模式,配置内核启动参数如下: linux ... irqaffinity=0-7 nohlt_list=0-7 只配置处理网卡中断的vCPU(0~7)跑在polling模式,在Host上只看到8个vCPU线程跑在800%,对于整机的48个CPU来说,不是太大的问题,同时虚拟机内部处理网络中断的延迟是稳定的。业务表现上PCT99也有所改善。 Patch: https://lkml.org/lkml/2019/5/22/164 PIW数据的测试效果,随机选择1K的服务器,对于没有启用nohlt_list的情况,多数服务器每秒会产生20K~100K的PIW:

对于启用了nohlt_list的场景,所有的服务器上都只有很少的PIW,实际上多数都是0。

对虚拟化的改进 --- 用户进程

例子一,atop是Linux上一个监控软件,在作者的工作环境中,深受大家喜爱。然而atop会自动收集Instruction Per Cycle的信息。收集IPC信息需要使用PMU,在虚拟化场景下,虚拟机中使用vPMU会造成wrmsr/rdpmc的vm-exit,就会看到虚拟机的vm-exit每隔一段时间就会发生一次抖动(默认是10s)。为此,作者修改了atop程序,让atop在启动阶段自动检测运行环境,如果是在虚拟机中,则默认关闭IPC收集功能,当然也可以通过配置强制enable/disable。 patch在https://github.com/Atoptool/atop/commit/16abcac132eec4755373aa673389e67219488844 例子二,jemalloc是一个高性能的用户态内存管理库,有一些cache型的业务会使用jemalloc代替glibc的ptmalloc。但是jemalloc的decay特性会调用madvise(void *addr, size_t length, MADV_DONTNEED),而这个操作会触发TLB shootdown(上文《[Linux][mm]TLB shootdown和读取smaps对性能的影响》一文中有更多的描述),TLB shootdown在虚拟化上的成本要高于物理机,所以cache型的业务的QPS和延迟通常要略差于物理机上的表现。简单粗暴的办法是最好关闭掉decay功能,性能会接近物理机。

取得的效果

如上文所说,OSS服务器的CPU利用率普遍不高,随机选择了7K服务器,在晚高峰九点到十点左右收集CPU数据绘制分布图,大部分的服务器的CPU使用率在10%以内,还有部分服务器的CPU使用率在20%以内:

使用了KVM虚拟化混合部署的方案之后,几乎所有的CPU使用率都得到了很大的提升:

在CPU利用率提高的同时,额外超分配出来的百万量级的CPU得到了充分的使用。得益于KVM虚拟化的强隔离性,Host上的OSS业务几乎没有任何的损耗,而Guest内部的在线业务的性能也逐渐接近物理机,在性能调优之后,性能在一些场景下要好于某云计算大厂的虚拟机。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AlwaysGeek 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 业务背景
  • 为什么选择虚拟化
  • CPU的隔离性问题
  • 调度模型对比
    • 作者知道的几种在线业务模型:
      • 内存模型对比
        • 磁盘IO的隔离对比
          • 网络IO的隔离对比
            • 内核版本的差异对比
            • 对虚拟化的改进 --- kvm-utils
            • 对虚拟化的改进 --- nohlt_list
            • 对虚拟化的改进 --- 用户进程
            • 取得的效果
            相关产品与服务
            云数据库 SQL Server
            腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档