内存虚拟化技术-POD和Ballooning
在云计算领域,CPU资源一般是被认为可超分资源,而内存是不可超分资源。我们在云厂商上购买虚拟机时可选择CPU超分的实例,但是却很少能选择内存超分实例,这是因为内存的分配在虚拟机发放的时候就分配了用户,但是CPU却是可争抢的。将多个4U8G实例都发放在0-3核区间上就可以实现超分。但是Xen提供了两个技术POD和Ballooning,给我们提供了重复售卖内存的机会。
虚拟化内存基础
在真实硬件上,实际的硬件内存称为物理内存;它通常分为称为物理帧的 4k 块。这些帧由它们的物理帧号或 pfn 寻址。在 x86 系统中,pfns 通常从 0 开始,并且大部分是连续的(IO 设备偶尔会出现“漏洞”)。当我们进行虚拟化时,我们需要为guest提供虚拟的“物理地址空间”,这些被称为guest物理帧号,或 gpfns。但是当然还有真正的硬件支持这个内存。在虚拟化世界中,通常将这些称为mfns。每个可用的 gpfn 后面都必须有一个 mfn。但是 gpfns 必须从 0 开始并且是连续的,而支持它们的 mfns 可能来自 Xen 内存中的任何位置。所以每个虚拟机都有一个物理到机器的转换表,称之为p2m 表,它将 gpfn 空间映射到 mfn 空间。每个 gpfn 在表中都有一个条目,并且每个可用的 RAM 位都有一个 mfn。通常这是由domain 0 中的domain构建器完成的,需要 Xen填充 p2m 表。
名词含义
- gpfn/gfn: guset page frame number
客户物理页面号(客户操作系统使用gpfn/gfn对客户物理地址空间寻址) - mfn: machine page frame number 机器页面号
Ballooning-气球
Xen 的一个功能,你可能没有听说过,但可能在不知情的情况下实际使用过。ballooning是一种用于动态调整guest使用的物理内存的技术。需要在客户操作系统中有一个驱动程序,称为气球驱动程序,从guest操作系统提取内存,然后将这些gpfn 后面的内存交还给 Xen。Xen 会将 gpfn 空间中的 mfn 替换为“无效条目”,并将 mfn 放在它自己的空闲列表中(可提供给另一个 VM)。如果guest现在尝试读取或写入此部分内存,它会崩溃;但它不会,因为操作系统认为该页面正在被气球驱动程序使用。气球驱动程序不会碰它,操作系统也不会将它用于其他任何事情。为了给气球放气,气球驱动程序将在其列表中选择它已分配的页面之一,然后要求 Xen 将一些内存放在 gpfn 后面。如果 Xen 确定允许guest增加它的内存,并且有可用的空闲内存,那么它将分配一个 mfn 并将其放入该 gpfn 的 p2m 表中。现在 gpfn 又可以使用了;然后气球驱动程序将页面释放回guest操作系统,它将把它放在自己的空闲列表中,以用于任何需要内存的东西。
从guest操作系统的角度来看,它仍然拥有它开始使用的所有内存;它只是有一个真正消耗内存的设备驱动程序。虽然Ballooning可以用来缩小guest内存然后再次扩展它,但这种技术有一个重要的限制:它永远不能将内存增长到超过 VM 的起始大小。这是因为增加guest内存的唯一方法是“放气”气球。一旦它恢复到 VM 的起始大小,气球就会完全放气,并且气球驱动程序不能添加额外的内存。
充气时:
放气时:
如上文所说,balloon最大的问题就是无法给VM扩大内存,最多就是完全放气把内存还给VM。这时候就需要POD技术了。
POD-POPULATE ON DEMAND
POD,也就是按需填充。顾名思义,就是说我们在给guest分配内存的时候并不是一次性按照规格将物理内存分配给guest,而是按照guest的不断请求量逐次分配。创建虚拟机时可以把规格设置大一点,VM按需申请内存。背后的实现逻辑是这样的,由于guest并不需要其所有内存来启动,它只需要其中的一小部分。xen会将mfns 分配到一个特殊的池中,我们将其称为 POD 池,具体取决于 memory 参数中指定的内存量。然后它像以前一样创建guest的 p2m 表,但不是用 mfns 填充它,而是用一个特殊的 POD 条目填充它。 POD条目是无效条目;因此,当guest启动时,只要它接触到由 POD 条目支持的 gpfn,它就会反馈 Xen。当 Xen 看到 POD 条目时,它会从 POD 池中取出一个 mfn 并将其放入该 gpfn 的 p2m 中。然后它将返回给guest,此时内存访问将成功。
因此,不是在构建domain时填充 p2m 表,而是按需填充 p2m 表。拥有 POD 池的关键原因是内存已经分配给domain,它会显示为domain所有,并且不能分配给不同的domain。如果改为按需分配,当您遇到无效条目时,实际上从 Xen 分配了内存,那么在气球驱动程序可以运行之前您需要启动的内存可能已经分配给不同的domain.但是,guest不能长时间这样跑。 p2m 表中的 POD 条目比 POD 池中的 mfns 多得多——这就是重点。但是guest操作系统不知道这一点;就它而言,它可以使用 maxmem。如果气球驱动程序没有启动,没有什么可以阻止它尝试使用所有内存。如果它用尽了 POD 池中的所有内存,那么下次 Xen 命中一个 POD 条目时,POD 池中将没有任何 mfns 来填充该条目。到了那个时候,Xen别无选择,只能kill虚拟机。
Ballooning和POD共存
气球驱动程序与guest操作系统一样,并不知道POD的存在。它只知道它有 maxmem gpfn 空间,它需要将 maxmem–memory 交还给 Xen。因此它开始从guest操作系统分配页面,并将 gpfns 释放回 Xen。 Xen 下一步做什么取决于几件事。 Xen 跟踪 p2m 表中的 POD 条目数和 POD 池中的 mfns 数。 如果 gpfn 是 POD 条目,Xen 将简单地将 POD 条目替换为正常的无效条目并返回。这减少了池中未完成的 POD 条目的数量。 如果 gpfn 后面有一个真正的 mfn,并且 p2m 表中剩余的 POD 条目数大于 POD 池中的 mfn 数,Xen 会将该条目替换为无效条目,并将 mfn 放回POD 池。这会增加池的大小。 如果 gpfn 后面有一个真正的 mfn,但 p2m 表中剩余的 POD 条目数等于池中的 mfn 数,它将把 mfn 放回空闲列表,准备被另一个domain使用. 最终,未完成的 POD 条目数等于 POD 池中的条目数,系统现在处于稳定状态。不再存在guest访问POD 条目而在池中找不到内存的风险;对于一个VM,最终所有页面都会被触及,并且虚拟机将与不是POD 模式下启动的虚拟机相同。文章来源:https://www.toymoban.com/news/detail-789548.html
我们能做什么
我们可以借助POD和Ballooning技术将VM未使用的内存拿去二次售卖文章来源地址https://www.toymoban.com/news/detail-789548.html
面临的问题
- POD带来的问题
由于物理机内存是大页内存,VM内部使用都是4K小页。当VM需要申请内存时,Xen会分配一块2M大页内存给VM,当VM内部空白的内存不是连续的大块时,而VM又需要大块内存时就会向物理机申请一块新大页内存。频繁申请和释放就会导致VM内部有很多碎片,造成资源浪费,长时间运行必然会导致VM申请的内存量达到规格,依赖于内存整理技术。 - VM的OOM和主机OOM风险
POD场景下,VM未申请的内存被拿去二次复用,当VM需要申请内存时,主机没有多余内存时就必须kill虚拟机释放内存,否则主机OOM。如果主机没有及时给VM调度内存,VM就会OOM。不管是删除还是迁移走虚拟机来释放内存的速度都小于VM使用内存的速度。Ballooning倒不至于主机OOM,由于偷出去的内存在VM看来是已经占用的,如果在VM deflate阶段主机没有内存还给VM时就会导致虚拟机内OOM。
到了这里,关于内存虚拟化技术-POD和Ballooning的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!