前期有客户反馈说:计算增强型虚机性能未达预期、Windows虚机跑分性能差别比较大。针对该问题,我们进行了一下分析:
一、容器环境下虚机性能分析
1.Guaranteed的POD
满足以下的条件,POD会被分配Guaranteed的QoS等级:
- POD中的每个容器必须有内存limit和内存request
- 对于pod中的每个容器,内存的limit和内存的request必须相等
- pod中的每个容器必须要有cpu limit和cpu request
- 对于pod中的每个容器,cpu的limit和cpu的request必须相等
简单来说,pod中的每个容器都要有cpu和内存的limit和request,并且limit和request要相等。
3. k8s的cpu管理策略
cpu管理策略有两种:
- none:默认策略,表示现有的调度行为
- static:允许为节点上具有某些资源特征的Pod赋予增强的CPU亲和性和独占性
static策略会针对具有整数型的requests的Guaranteed的Pod,进行CPU亲和性和独占性的配置,当前版本(k8s 1.18)在进行分配时,策略会优先将完整物理核的超线程全部分配给一个pod,其它QoS为BestEffect和Burstable的,以及非整数Guaranteed的Pod的亲和性是从共享池里取,能够共享共享池里所有的cpu
我们集群配置的是static策略
4. 超线程
超线程技术在一个物理核上模拟两个逻辑核,两个逻辑核具有各自独立的寄存器核APIC,但会共享使用物理核的执行资源,包括执行引擎、L1/L2缓存、TLB和系统总线等等。超线程可以并行执行,提升物理核整体的吞吐量,但由于超线程对物理核执行资源的争抢,业务的执行时延会相应增加:
a. 开启超线程后,物理核总计算能力是否提升以及提升的幅度和业务模型相关,平均提升在20%-30%左右
b. 当超线程相互竞争时,超线程的计算能力相比不开超线程时的物理核会下降30%左右
5. 优化方案
根据以上分析可以得出计算增强型虚机性能比普通虚机性能差,是因为:计算增强型虚机能够使用的完整物理核,比普通虚机的要少,当然这种情况成立是在节点上多数资源是非计算增强的
- 升级高版本k8s(1.24?),使用更新的static的策略选项,让每个vCPU分布在不同的numa node上,但该策略也不能完全避免,只是降低了同一虚机使用相同物理核所有超线程的概率,但会增加其它虚机与其抢物理核的概率
- 隔离高性能虚机使用的宿主机,关闭超线程功能
- 隔离宿主机上基础组件使用的进程,避免其被调度到虚机绑定的核上
二、Windows虚机性能分析
1. 通过perf工具分析虚机进程执行情况:
从上图可以看出该虚机大量时间消耗在KVM操作上,主要是:vmx_handle_exit,vmx_handle_external_intr,vmx_save_host_state这3个函数,既然KVM占用了大量时间,那咱们通过 perf kvm stat来看看kvm具体做了什么
2. 跟踪kvm具体行为
从上图可以看出除了VM Entry和VM Exit事件外,最高的就是kvm_pio和kvm_mmio,说明windows有大量的IO Port和MMIO操作;在虚拟化里,IO Port或者NMIO都可能引起VM Exit,甚至是Heavy Exit。如果需要改善性能,一般都会尽量避免这种情况。
3. 分析具体是哪些IO Port和MMIO导致的VM Exit
发现主要是一下两个访问导致:
- IO Port是0x608和0xC050
- MMIO是0xFEE003X
3. 通过qemu info mtree命令查看具体设备
- IO Port
0000000000000608-000000000000060b (prio 0, RW): acpi-tmr 000000000000c040-000000000000c07f (prio 1, RW): virtio-pci
- MMIO
00000000fee00000-00000000feefffff (prio 4096, RW): icc-apic-container
0xC050可以忽略,这个被Virtio Block来做VM Exit。
通过以上分析,可以判断出windows大量读取ACPI Power Manager Timer 以及访问 APIC寄存器,进而导致过多的VM Exit,那么解决思路就是解决两个问题:
- 怎样减少ACPI Power Manager Timer导致的VM Exit
一般而言IO Port类的性能优化就是使用Paravirtulization替换Full-Virtualization,从windows 7 开始,为了使windows在hyper v中有更好的性能表现,微软针对windows进行了优化,其中一项就是HyperV Timer。
qemu和libvirt在2014年时,增加了对HyperV Timer的支持
- 怎样减少APIC MMIO导致的VM Exit
针对APIC 引起的VM Exit,Intel CPU也已经支持apic-v
因此,我们可以通过配置kubvirt的VirtualMachine,针对windows虚机开启hyperv timer和apic-v:
apiVersion: kubevirt.io/v1alpha3
kind: VirtualMachine
spec:
template:
spec:
domain:
features:
acpi: {}
apic: {}
clock:
timer:
rtc:
present: true
tickPolicy: catchup
pit:
present: true
tickPolicy: delay
hpet:
present: false
hyperv:
present: true