在线迁移后虚拟机CPU利用率飙升问题分析

提供虚拟机服务的过程中,遇到了如下问题:

  • 现象1:在线迁移前,虚拟机运行正常,迁移之后,虚拟机内用户态程序CPU占用飙升,甚至打满整个虚拟机。
  • 现象2:虚拟机内CPU占用集中在用户态,关闭程序后虚拟机CPU使用率下降,启动程序可复现问题。
  • 现象3:冷启动虚拟后,启动程序,问题消失。

该问题多次出现,升级宿主机到高版本内核问题消失,最终通过缩小范围,发现打入如下内核Patch后问题解决。

1
d1fe9219551e914f26219afaca1063b280f25963 KVM: x86: reintroduce kvm_is_mmio_pfn

该Patch修复了在设置EPT 页表项时,将 "Zero Page" 当做MMIO Page处理导致页面无法缓存的问题:

Zero PFN EPT PTE 缓存类型 说明
修复前 0x1c2a 0x1c2a105 UC uncacheable
修复后 0x1c2a 0x1c2a075 WB writeback
  • 注意不同内核”Zero Page”的PFN可能不同,上表中仅为示例

可以看到未修复前,"Zero Page" 不能被缓存,为何这会导致迁移场景的问题,下面进行详细的分析。

什么是 "Zero Page"

"Zero Page" 是内容全部为0的特殊只读页面。在x86体系结构下,"Zero Page" 存储在内核BSS段中并在内核启动时清零。"Zero PFN" 是 "Zero Page" 对应的物理页帧号。

1
__PAGE_ALIGNED_BSS NEXT_PAGE(empty_zero_page) .skip PAGE_SIZE EXPORT_SYMBOL(empty_zero_page)

什么场景下会使用 "Zero Page"

最典型的场景:当读取未分配的匿名页时,会映射 "Zero Page" 到访问地址,如下图所示:

如果写入映射 "Zero Page" 的虚拟地址,会触发COW,分配新的页面。

虚拟机在线迁移和 "Zero Page" 有什么关联?

虚拟机在线迁移过程中,会持续传输内存修改数据至目的端虚拟机,其中有如下判断。

在线迁移过程中,不传输内容为0的内存页。这可能造成 "Zero Page" 变多,如下所示: * 在线迁移前,虚拟机存在内容为0的内存页。

  • 在线迁移后,由于未传输内容为0的内存页,对这些页面的读访问将映射到 "Zero Page"

  • 如果 "Zero Page" 无法缓存,对其的读访问会有较大开销,实际测试结果(仅供参考)。

(分配6GB内存空间并清零,顺序遍历读取整个6GB空间并统计完成时间)

总结

该问题出现的根本原因是在线迁移之后,对 "Zero Page" 的缓存类型设置有误,导致用户态程序访存能力下降,从而导致问题。

需要注意的是,如果开启了透明大页,该问题的出现概率将大幅降低,具体原因和THP的 "Zero Page" 实现有关,这里不做分析了。