openstack中虚拟机CPU与内存布局设计(一)

来源:互联网 发布:java文件上传类 编辑:程序博客网 时间:2024/06/10 05:48

        最近在整理Openstack的一些设计,发现网上找到的一些资料都比较零碎,而官方的设计文档非常详细,但都是英文读起来略吃力,干脆花点功夫做点翻译好了。

        ---------------------------------------------------分割线----------------------------------------------

       VirtDriverGuestCPUMemoryPlacement

        原文链接如下:https://wiki.openstack.org/wiki/VirtDriverGuestCPUMemoryPlacement


适用范围 

   本文档讨论虚拟机的CPU与内存布局与虚拟主机之间的关系。注意,本文档展示的是最初的讨论与研究结果,而关于后续更加详细的设计细节,可以参见以下几方面:

• NUMA placement[1] 

• vCPU topology[2]

• CPU pinning [3]

• Large pages [4]

术语

• vCPU  虚拟CPU,分配给虚拟机的逻辑CPU。根据虚拟机拓扑的不同,一个虚拟机CPU可以是一个CPU封装元件(socket)、一个CPU(core)、或者一个CPU线程(thread)

• pCPU – 物理CPU 虚拟机主机所展示的逻辑CPU,根据主机拓扑的不同,一个物理可以是一个CPU封装元件(socket)、一个CPU(core)、或者一个CPU线程(thread)

• NUMA  非一致内存访问架构,内存访问时间取决于内存页面和处理器核心之间的位置。

• node – 一个包含CPU或者内存(或者二者兼具)NUMA系统单元

• cell – node的通名词,供libvirt API使用

• socket – 包含在NUMA系统单元内的单个独立CPU封装元件

• core – 一个CPU封装元件中的一个处理单元

• thread – 超线程,一个CPU核中的一个超流水线

• KSM – Linux内核内存共享技术(Kernel Shared Memory) 

• THP – 透明巨型页,为进程提前分配巨型页的一种Linux技术 

背景

虚拟CPU拓扑

Openstack中,每一种虚拟化驱动在为虚拟机定义CPU拓扑时,都有各自的方法。Libvirt的驱动将每一个虚拟CPU定义为一个没有超线程(no hyper-threads)只含有一个处理单元(with 1 core)的独立CPU封装原件(socket),当操作系统不能识别所有的虚拟CPU时,将会面临一些问题。

• 许可(Licensing)  操作系统供应商许可规则,可能会严格约束操作系统所支持的CPU封装元件(sockets)的数目。此时,为虚拟机分配的虚拟CPU,应该偏向处理单元(core),而不是封装单元(socket)

• 性能(Performance) – 各种CPU拓扑的性能并不一致。例如,两个主机线程运行在同一个处理单元(core)上时,其性能就会低于运行在不同的处理单元(core)上。而当一个处理单元(core)有多个超线程(thread)时,操作系统调度器将决定线程的具体运行位置。超线程性能的影响,意味着除非指定将虚拟机超线程与虚拟机主机的超线程一一绑定,否则无法为虚拟机指定超线程。如果不绑定虚拟机CPU(vCPU)与物理CPU(pCPU)的关系,则虚拟机应当始终不使用超线程(threads==1),而只是用CPU封装元件(sockets)CPU处理单元(core),而没有必要项用户暴露超线程的配置能力。如果用户的虚拟机对负载比较敏感,那么用户最多会希望他们的镜像不运行在兄弟超线程(同一个处理单元上的超线程)上。

许可的影响,意味着用户在上传镜像到glance时,需要指明一个运行镜像的最佳的CPU拓扑,包含处理单元(core)与封装元件(socket)的分配。云平台管理员也可以修改程序的默认值,以避免用户超出常见的许可限制。也就是说,对于一个4虚拟CPU核的虚拟机,如果使用默认值限制最大的封装元件(socket)数目为2,则可以设置其处理单元为2,此时windows镜像也能够正常处理。

NUMA拓扑

虚拟主机NUMA

现在虚拟化主机都支持NUMA拓扑,会将内存与物理CPU分布在2个或者更多的NUMA单元上。也有些CPU模型引入了两级NUMA的架构,这些在本文档中不做深入讨论。

主要驱动NUMA使用的因素是高存储带宽,有效的缓存效率以及灵活PCIe I/O设备的布局。也就是说,每一个NUMA单元内部都由自己专有的内存总线,用于访问专用内存,而所有NUMA单元使用共享总线访问远端的内存。假如有一个具有4NUMA单元的系统,每一个单元内部有1GB/s的存储带宽,同时共享总线也具有1GB/s的带宽。如果所有的处理器总是使用NUMA单元内部内存,那么系统就拥有了4 GB/s 的存储带宽潜力。如果所有处理器都是用远端存储,那么系统就只有了1 GB/s 的存储带宽潜力。使用共享的总线可能触发NUMA单元之间的缓存异常同步,对于内存密集型工作负载的性能会产生显著影响。当I / O性能至关重要时,加上共享总线上的无效cache资源浪费,连接到远程PCIe总线上的设备(也就是说连接不同NUMA单元)作业性能将会急剧下降。

因此,虚拟机在NUMA单元上的错误布局,或者不正确的PCI设备分配选择,将会导虚拟化主机资源的严重浪费。这点影响将会抹掉任何内存与CPU决策所带来的好处,包括虚拟CPU拓扑,物理CPU与虚拟CPU绑定,以及使用大页内存。因此标准的策略将是一个虚拟机完全局限在单个NUMA节点。

虚拟机 NUMA

如果虚拟机的虚拟CPU或者内存分配大过了NUMA单元,或者NUMA单元可用的PCIe设备不足时,必须针对虚拟机做出合适的策略,或者禁止创建过大NUMA单元的虚拟机,或者允许虚拟机跨越多NUMA运行。在虚拟机迁移时,可以更改这些策略,也就是说,在对主机进行维护而疏散主机时,会选择接受临时降低性能而选择次优的NUMA布局。布局的问题还要考虑到虚拟机的具体使用场景,例如,NFV的部署就要求严格的NUMA布局。

如果一个虚拟机多个NUMA单元,以是的操作系统能够最大化利用其分配到的资源,主机的NUMA拓扑必须暴露给虚拟机。虚拟机的的NUMA单元应该与虚拟化主机的NUMA单元进行映射。这样可以硬着大块的虚拟机内存到虚拟化主机内存节点,设置虚拟CPU与物理CPU的映射。也就是说,如果虚拟机有4个虚拟CPU需要跨越两个虚拟化主机NUMA单元,虚拟CPU0/1绑定到第一个主机NUMA单元,而虚拟CPU2/3将会绑定到第二个主机NUMA单元上,但是并不强制绑定每一个以虚拟CPUNUMA单元内特定物理CPU的关系这将由操作系统调度器指定。此时,如果虚拟主机具有超线程特性,则暴露超线程特性给虚拟机,同时在NUMA单元内绑定虚拟CPU与物理CPU的关系。

虚拟机NUMA拓扑配置不关注虚拟机操作系统。如果虚拟机操作系统不支持NUMAIf a guest OS does not support NUMA, then it would simply ignore the datatables exposed in the virtual BIOS. That said, the guest vCPU topology constraints will influence what particular NUMA topologies are viable to expose. ie if the guest only supports max 2 sockets, then there is little point in setting up 4 NUMA nodes with 1 socket 1 core in each. It would have to have 2 NUMA nodes with 1 socket, 2 cores in each.

大页内存

绝大多数现代CPU支持多种内存页尺寸,从4KB2M/4M,最大可以达到1GB;所有处理器都默认使用最小的4KB页。如果大量的内存可以使用大页进行分配,将会明显减少CPU页表项,因此会增加页表缓存的命中率,降低内存访问延迟。如果操作系统使用默认的小页内存,随着运行时间,系统会出现越来越多的碎片,以至于很难申请到大页的内存。在大页内存大小越大时,该问题越严重。因此,如果有使用大页内存的需求,最好的办法是在系统启动时就预留好内存空间。当前的Linux内核不允许针对特定的NUMA节点进行这样的设定,不过,在不久的将来这个限制将被取消。更进一步的限制是,由于MMIO空洞的存在,内存开始的1GB不能使用1GB的大页。

Linux内核已经支持透明巨型页(THPtransparent huge pages)特性。该特性会尝试为应用程序预分配大页内存。依赖该特性的一个问题是,虚拟机的拥有者,并不能保证给虚拟机使用的是大页内存还是小页内存。

内存块是直接指定给特定的NUMA单元的,这就意味着大页内存也是直接指定在NUMA单元上的。因此在NUMA单元上分配虚拟机时,计算服务需要考虑在NUMA单元或者主机上可能会用到的大页内存。为虚拟机内存启用大页内存时,可以不用考虑虚拟机操作系统是否会使用。

0 0
原创粉丝点击