内存碎片调整

在某些高内存压力场景下,内存短缺会导致高阶页难以分配,并且由于默认的 min<->low<->high 之间的间隙过小,无法提前唤醒 kswapd(异步回收),导致页面分配频繁地进入同步回收。

问题描述

在 OpenStack 计算节点中,特别是使用大量页面缓存的 Ceph OSD 的融合机器中,很容易出现内存分配停滞的问题。这个问题会导致多个问题:无法启动新的实例(KVM 需要分配 order sixth 页面)或 VM 卡住等。原因如下:

1). 大订单页面的压缩 如果 VM 使用 THP(Transparent Huge Page),那么情况会比为 VM 专用用途保留的持久大页面更严重。THP 需要在运行时分配 2MB(x86)的大页面。此外,这是 order 9 (2^9 * 4K = 2MB)。在运行系统中,根据 /proc/pagetypeinfo,很难获得连续的 512 (2^9) 4K 页面。

2). 同步回收。系统内部有三个水位线:1). min 2). low 3). high。当空闲页数降低到 low 水位线时,kswapd 将被唤醒以执行异步回收。此外,它不会停止,直到空闲页数达到 high 水位线。但是,当内存分配足够强时,空闲页数将继续降低到 min 水位线。此时,min 页数保留用于紧急用途,分配将进入直接回收(同步)模式。这将导致进程停滞。

提议的变更

根据以往经验,min<->low<->high 水位线之间的 1GB 间隙是在服务器环境中一种良好的实践。更大的间隙可以更早地唤醒 kswapd 并避免同步回收。此外,这可以减轻延迟。与水位线间隙计算相关的 sysctl 参数:

vm.min_free_kbytes vm.watermark_scale_factor

对于 Ubuntu 内核 4.15 之前的版本(Bionic),调整水位线的唯一方法是修改 vm.min_free_kbytes。间隙将是 vm.min_free_kbytes 的 1/4。但是,增加 min_free_kbytes 会增加最小水位线保留,从而减少运行时系统可以使用的实际内存。

对于 Ubuntu 内核 4.15 之后,可以使用 vm.watermark_scale_factor 来增加间隙,而无需增加最小水位线保留。间隙的计算方式为“watermark_scale_factor/10000 * managed_pages”。

建议的解决方案是在计算节点重新启动时,使用上述两个参数设置 1GB 的水位线间隙。

该功能将以灵活的方式设计:1). 将有一个开关来启用/禁用该功能。默认情况下,它是关闭的。对于一些小内存计算节点(<32GB),1GB 的低内存太多了。

2). 手动配置具有更高的优先级来覆盖默认计算。

备选方案

可以使用以下命令在运行时设置配置:juju deploy cs:sysconfig-2 juju add-relation sysconfig nova-compute juju config sysconfig sysctl=”{vm.extfrag_threshold: 200, vm.watermark_scale_factor: 50}”

但是,每个系统可能具有不同的内存容量。需要手动计算 watermark_scale_factor。

实现

负责人

主要负责人:- Gavin Guo <gavin.guo@canonical.com>

Gerrit Topic

对于与此规范相关的所有补丁,请使用 Gerrit 主题“memory-fragmentation-tuning”。

git-review -t memory-fragmentation-tuning

工作项

实现 watermark_scale_factor 值的计算,以将间隙设置为 1GB。

仓库

不需要新的 git 仓库。

文档

文档需要包含启用/禁用该功能的开关。

安全性

使用此功能不会暴露其他安全攻击面。

测试

为了验证计算出的水位线值是否正确。此外,在不同的内核版本中,应使用不同的参数(min_free_kbytes 与 watermark_scale_factor)。

依赖项