
# 内核memory的OOM进程控制策略
#### 背景信息
现有操作系统中，支持配置离线业务和在线业务。当内存发生OOM时，会优先选择离线业务控制组中的消耗内存最多的进程，结束进程回收内存，但是对于某些离线业务也有核心业务，因此会造成很大的影响。
针对这个问题，HCE调整了OOM时回收内存的策略，增加了配置cgroup优先级的功能。内存紧张情况下内核会遍历cgroup，对低优先级的cgroup结束进程，并回收内存，使离线业务中重要的业务可以存活下来。
#### 前提条件
vm.panic_on_oom默认关闭配置为0，系统OOM时不会发生panic。在使用memcg OOM优先级配置时（即memcg_qos_enable配置为1或2），如果vm.panic_on_oom接口被打开，需先执行**sysctl -w vm.panic_on_oom=0**命令，关闭系统参数vm.panic_on_oom。
#### memcg OOM优先级接口功能说明
表1接口功能说明 
| 接口               | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | 取值                           |
|:---|:---|:---|
| memcg_qos_enable | memcg OOM优先级策略开关。 - 0：不开启优先级配置。当OOM时，按照系统原有的OOM操作结束进程，结束内存消耗最大的进程，回收内存。  - 1：开启优先级配置并以cgroup为粒度。当OOM时，结束优先级低的cgroup所有进程，并回收内存。  - 2：开启优先级配置并以单个进程个为粒度。当OOM时，结束优先级低的cgroup中的最大的一个进程，并回收内存。                                                                                                                                                                                                                                                                                                                             | 整数形式，取值范围为0\~2，默认值为0。        |
| memory.qos_level | 配置cgroup组优先级。值越小cgroup组优先级越低。 - 当memcg OOM时，会以当前cgroup组为父节点，查找子节点优先级最低的cgroup组中内存使用最大的进程，结束该进程，回收内存。  - 当OOM时，对于优先级相等的cgroup组，会根据组的内存使用量进行二次排序，选择内存使用最大的进行OOM操作。   说明： - 使用memory.qos_level的前提条件为memcg_qos_enable取值须为1或2。  - 新创建的cgroup组的memory.qos_level值默认会继承父节点的memory.qos_level的值，但是子节点的优先级不受父节点的限制。  - 如果修改cgroup组父节点的优先级，子节点的优先级会自动调整，和父节点保持一致。   | 整数形式，取值范围为-1024\~1023，默认值为0。 |
   
#### 接口配置示例
按如下所示创建6个cgroup子节点A、B、C、D、E、F，配置memcg_qos_enable接口，并通过memory.qos_level接口设置OOM的优先级，优先级取值如图所示。
图1优先级取值   
![](https://support.huaweicloud.com/usermanual-hce/zh-cn_image_0000002512128903.png "点击放大")
表2数据规划 
| cgroup组 | memory.qos_level取值 | 说明                                                                                                                                                                                                                                                                                                                                                                                                        |
|:---|:---|:---|
| **A**   | **-8**             | 当在root中进行OOM操作时，内核遍历root所有cgroup组，最终选择优先级最低的A、E。由于A和E优先级相同，内核继续对A和E使用的内存进行比较。 - 如果设置memcg_qos_enable=1，优先对A/E中内存使用量大的一个cgroup组回收内存，结束cgroup组中的所有进程，并回收内存。  - 如果设置memcg_qos_enable=2，优先对A/E中内存使用量最大的一个进程回收内存。   |
| B       | 10                 | 当在root中进行OOM操作时，内核遍历root所有cgroup组，最终选择优先级最低的A、E。由于A和E优先级相同，内核继续对A和E使用的内存进行比较。 - 如果设置memcg_qos_enable=1，优先对A/E中内存使用量大的一个cgroup组回收内存，结束cgroup组中的所有进程，并回收内存。  - 如果设置memcg_qos_enable=2，优先对A/E中内存使用量最大的一个进程回收内存。   |
| C       | 1                  | 当在root中进行OOM操作时，内核遍历root所有cgroup组，最终选择优先级最低的A、E。由于A和E优先级相同，内核继续对A和E使用的内存进行比较。 - 如果设置memcg_qos_enable=1，优先对A/E中内存使用量大的一个cgroup组回收内存，结束cgroup组中的所有进程，并回收内存。  - 如果设置memcg_qos_enable=2，优先对A/E中内存使用量最大的一个进程回收内存。   |
| D       | 2                  | 当在root中进行OOM操作时，内核遍历root所有cgroup组，最终选择优先级最低的A、E。由于A和E优先级相同，内核继续对A和E使用的内存进行比较。 - 如果设置memcg_qos_enable=1，优先对A/E中内存使用量大的一个cgroup组回收内存，结束cgroup组中的所有进程，并回收内存。  - 如果设置memcg_qos_enable=2，优先对A/E中内存使用量最大的一个进程回收内存。   |
| **E**   | **-8**             | 当在root中进行OOM操作时，内核遍历root所有cgroup组，最终选择优先级最低的A、E。由于A和E优先级相同，内核继续对A和E使用的内存进行比较。 - 如果设置memcg_qos_enable=1，优先对A/E中内存使用量大的一个cgroup组回收内存，结束cgroup组中的所有进程，并回收内存。  - 如果设置memcg_qos_enable=2，优先对A/E中内存使用量最大的一个进程回收内存。   |
| F       | 3                  | 当在root中进行OOM操作时，内核遍历root所有cgroup组，最终选择优先级最低的A、E。由于A和E优先级相同，内核继续对A和E使用的内存进行比较。 - 如果设置memcg_qos_enable=1，优先对A/E中内存使用量大的一个cgroup组回收内存，结束cgroup组中的所有进程，并回收内存。  - 如果设置memcg_qos_enable=2，优先对A/E中内存使用量最大的一个进程回收内存。   |
   
1. 关闭系统参数vm.panic_on_oom。
   ```
   sysctl -w vm.panic_on_oom=0
   ```
   
2. 开启memcg OOM优先级策略功能。
   ```
   echo 1 > /proc/sys/vm/memcg_qos_enable
   ```
   
3. 运行以下命令创建两个cgroup节点 A、B，并分别设置A、B节点的memcg OOM优先级值为-8、10。注意cgroupV2与V1默认层级有略差异，以下是v1示例：
   ```
   mkdir /sys/fs/cgroup/memory/A
   mkdir /sys/fs/cgroup/memory/B
   cd /sys/fs/cgroup/memory/A
   echo -8 > memory.qos_level
   cd /sys/fs/cgroup/memory/B
   echo 10 > memory.qos_level
   ```
   
4. 运行以下命令分别在A节点下创建C、D子节点，在B节点下创建E、F子节点， 并分别设置C、D、E、F子节点的memcg OOM优先级值为1、2、-8、3。
   ```
   mkdir /sys/fs/cgroup/memory/A/C
   mkdir /sys/fs/cgroup/memory/A/D
   mkdir /sys/fs/cgroup/memory/B/E
   mkdir /sys/fs/cgroup/memory/B/F
   cd /sys/fs/cgroup/memory/A/C
   echo 1 > memory.qos_level
   cd /sys/fs/cgroup/memory/A/D
   echo 2 > memory.qos_level
   cd /sys/fs/cgroup/memory/B/E
   echo -8 > memory.qos_level
   cd /sys/fs/cgroup/memory/B/F
   echo 3 > memory.qos_level
   ```
   
 
