全部產品
Search
文件中心

Alibaba Cloud Linux:出現OOM Killer的原因及解決方案

更新時間:Jul 17, 2024

Linux作業系統記憶體不足時,會先觸發記憶體回收機制釋放記憶體,並將這部分被釋放的記憶體配置給其他進程。如果記憶體回收機制不能處理系統記憶體不足的情況,則系統會觸發OOM Killer(Out of Memory Killer)強制釋放進程佔用的記憶體,達到給系統解壓的目的。本文介紹Alibaba Cloud Linux作業系統出現OOM Killer的可能原因及解決方案。

問題現象

Alibaba Cloud Linux作業系統出現OOM Killer的部分日誌資訊樣本如下,表示test進程引發了OOM Killer。

565 [六 9月 11 12:24:42 2021] test invoked oom-killer: gfp_mask=0x62****(GFP_HIGHUSER_MOVABLE|__GFP_ZERO), nodemask=(null), order=0, oom_score_adj=0
566 [六 9月 11 12:24:42 2021] test cpuset=/ mems_allowed=0
567 [六 9月 11 12:24:42 2021] CPU: 1 PID: 29748 Comm: test Kdump: loaded Not tainted 4.19.91-24.1.al7.x86_64 #1
568 [六 9月 11 12:24:42 2021] Hardware name: Alibaba Cloud Alibaba Cloud ECS, BIOS e62**** 04/01/2014

可能原因

系統出現OOM Killer表示記憶體不足,記憶體不足可以分為執行個體全域記憶體不足和執行個體內cgroup的記憶體不足。目前常見的出現OOM Killer的情境及原因說明如下:

原因類型

情境樣本

cgroup記憶體不足

如下日誌記錄的出現OOM Killer情境樣本中,test進程所在的cgroup /mm_test發生了OOM Killer。

[Wed Sep  8 18:01:32 2021] test invoked oom-killer: gfp_mask=0x240****(GFP_KERNEL), nodemask=0, order=0, oom_score_adj=0
[Wed Sep  8 18:01:32 2021] Task in /mm_test killed as a result of limit of /mm_test
[Wed Sep  8 18:01:32 2021] memory: usage 204800kB, limit 204800kB, failcnt 26

原因:cgroup /mm_test的記憶體使用量率達到上限(200 MB),因此觸發了OOM Killer。

父cgroup記憶體不足

如下日誌記錄的出現OOM Killer情境樣本中,test進程屬於cgroup /mm_test/2,而發生OOM Killer的cgroup為/mm_test

[Fri Sep 10 16:15:14 2021] test invoked oom-killer: gfp_mask=0x240****(GFP_KERNEL), nodemask=0, order=0, oom_score_adj=0
[Fri Sep 10 16:15:14 2021] Task in /mm_test/2 killed as a result of limit of /mm_test
[Fri Sep 10 16:15:14 2021] memory: usage 204800kB, limit 204800kB, failcnt 1607

原因:cgroup /mm_test/2的記憶體使用量率沒有達到上限,但父cgroup /mm_test的記憶體使用量率達到上限(200 MB),因此觸發了OOM Killer。

系統全域記憶體不足

如下日誌記錄的出現OOM Killer情境樣本中,limit of host表示執行個體的全域記憶體出現了不足。在日誌記錄的資料中,記憶體節點Node 0的空閑記憶體(free)已經低於了記憶體最低水位線(low)。

[六 9月 11 12:24:42 2021] test invoked oom-killer: gfp_mask=0x62****(GFP_HIGHUSER_MOVABLE|__GFP_ZERO), nodemask=(null), order=0,
[六 9月 11 12:24:42 2021] Task in /user.slice killed as a result of limit of host
[六 9月 11 12:24:42 2021] Node 0 DMA32 free:155160kB min:152412kB low:190512kB high:228612kB
[六 9月 11 12:24:42 2021] Node 0 Normal free:46592kB min:46712kB low:58388kB high:70064kB

原因:由於執行個體的空閑記憶體低於記憶體最低水位線,無法通過記憶體回收機制解決記憶體不足的問題,因此觸發了OOM Killer。

記憶體節點(Node)的記憶體不足

如下日誌記錄的出現OOM Killer情境樣本中,部分日誌記錄說明:

  • limit of host表示記憶體節點的記憶體出現了不足。

  • 執行個體存在Node 0和Node 1兩個記憶體節點。

  • 記憶體節點Node 1的空閑記憶體(free)低於記憶體最低水位線(low)。

  • 執行個體的空閑記憶體還有大量剩餘(free:4111496)。

[Sat Sep 11 09:46:24 2021] main invoked oom-killer: gfp_mask=0x62****(GFP_HIGHUSER_MOVABLE|__GFP_ZERO), nodemask=(null), order=0, oom_score_adj=0
[Sat Sep 11 09:46:24 2021] main cpuset=mm_cpuset mems_allowed=1
[Sat Sep 11 09:46:24 2021] Task in / killed as a result of limit of host
[Sat Sep 11 09:46:24 2021] Mem-Info:
[Sat Sep 11 09:46:24 2021] active_anon:172 inactive_anon:4518735 isolated_anon:
    free:4111496 free_pcp:1 free_cma:0
[Sat Sep 11 09:46:24 2021] Node 1 Normal free:43636kB min:45148kB low:441424kB high:837700kB
[Sat Sep 11 09:46:24 2021] Node 1 Normal: 856*4kB (UME) 375*8kB (UME) 183*16kB (UME) 184*32kB (UME) 87*64kB (ME) 45*128kB (UME) 16*256kB (UME) 5*512kB (UE) 14*1024kB (UME) 0     *2048kB 0*4096kB = 47560kB
[Sat Sep 11 09:46:24 2021] Node 0 hugepages_total=360 hugepages_free=360 hugepages_surp=0 hugepages_size=1048576kB
[Sat Sep 11 09:46:24 2021] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[Sat Sep 11 09:46:24 2021] Node 1 hugepages_total=360 hugepages_free=360 hugepages_surp=0 hugepages_size=1048576kB
[Sat Sep 11 09:46:25 2021] Node 1 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB

原因:在NUMA儲存模式下,作業系統可能存在多個記憶體節點(可運行cat /proc/buddyinfo命令查看相關資源資訊)。如果通過cpuset.mems參數指定cgroup只能使用特定記憶體節點的記憶體,則可能導致執行個體在具備充足的空閑記憶體的情況下,仍出現OOM Killer的情況。

記憶體片段化時夥伴系統記憶體不足

如下日誌記錄的出現OOM Killer情境樣本中,部分日誌記錄分析說明:

  • 作業系統在記憶體配置的order=3階段出現了OOM Killer。

  • 記憶體節點Node 0的空閑記憶體(free)仍高於記憶體最低水位線(low)。

  • 記憶體節點Node 0對應的夥伴系統記憶體為0(0*32kB (M))。

[六 9月 11 15:22:46 2021] insmod invoked oom-killer: gfp_mask=0x60****(GFP_KERNEL), nodemask=(null), order=3, oom_score_adj=0
[六 9月 11 15:22:46 2021] insmod cpuset=/ mems_allowed=0
[六 9月 11 15:22:46 2021] Task in /user.slice killed as a result of limit of host
[六 9月 11 15:22:46 2021] Node 0 Normal free:23500kB min:15892kB low:19864kB high:23836kB active_anon:308kB inactive_anon:194492kB active_file:384kB inactive_file:420kB unevi    ctable:0kB writepending:464kB present:917504kB managed:852784kB mlocked:0kB kernel_stack:2928kB pagetables:9188kB bounce:0kB
[六 9月 11 15:22:46 2021] Node 0 Normal: 1325*4kB (UME) 966*8kB (UME) 675*16kB (UME) 0*32kB (M) 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB =

原因:作業系統的記憶體在進行記憶體配置的過程中,如果夥伴系統的記憶體不足,則系統會通過OOM Killer釋放記憶體,並將記憶體提供至夥伴系統。

說明

在Linux作業系統中,夥伴系統(Buddy System)是核心記憶體管理的一種機制,它能夠減輕記憶體片段問題,並且高效地分配和釋放不同大小的記憶體塊。

解決方案

請您結合實際出現的OOM Killer情境,按照以下步驟排查並解決問題:

子cgroup或父cgroup記憶體不足

建議您自行評估執行個體內當前佔用記憶體的進程情況,及時清理不需要的進程,以釋放記憶體。如果您的業務所需的記憶體較大,當前執行個體規格不滿足您對記憶體的需求,可以升配執行個體以提升執行個體的記憶體容量。

  1. 升配執行個體。

    更多資訊,請參見升降配方式概述

  2. 根據記憶體實際的提升情況,手動調整cgroup的記憶體上限。

    sudo bash -c 'echo <value> > /sys/fs/cgroup/memory/<cgroup_name>/memory.limit_in_bytes'

    其中,<value>為您為cgroup設定的記憶體上限、<cgroup_name>為您實際的cgroup名稱,請根據實際情況替換。

系統全域記憶體不足

如果出現系統全域記憶體不足,請您重點排查以下幾項:

  • 查看slab_unreclaimable記憶體使用量情況。

    cat /proc/meminfo | grep "SUnreclaim"

    slab_unreclaimable記憶體為系統不可回收的記憶體,當佔用總記憶體的10%以上時,表示系統可能存在slab記憶體泄露。如果存在記憶體泄露問題,您可以手動排查並解決,具體操作,請參見如何排查slab_unreclaimable記憶體佔用高的原因?。如果問題始終未解決,可以提交工單尋求支援人員。

  • 查看systemd記憶體使用量情況。

    cat /proc/1/status | grep "RssAnon"

    核心發生OOM Killer時,會跳過系統的1號進程。此時您查看systemd記憶體使用量情況時,一般不會超過200 MB。如果出現異常,您可以嘗試自行更新systemd工具的版本。

  • 查看透明大頁THP的效能。

    開啟THP會出現記憶體膨脹(memory bloating),從而導致OOM Killer,您可以對THP進行調優。具體操作,請參見Alibaba Cloud Linux系統中與透明大頁THP相關的效能調優方法

記憶體節點(Node)的記憶體不足

記憶體節點(Node)的記憶體不足導致的OOM Killer,您需要重新設定cpuset.mems介面的值,使cgroup能夠合理使用記憶體節點的記憶體。

  1. 運行以下命令,確定系統中記憶體節點(Node)的數量資訊。

    cat /proc/buddyinfo
  2. 配置cpuset.mems介面。

    sudo bash -c 'echo <value> > /sys/fs/cgroup/cpuset/<cgroup_name>/cpuset.mems'

    其中,<value>為對應的記憶體節點號、<cgroup_name>為您實際的cgroup名稱,請根據實際情況替換。

    例如,系統中存在三個Node,分別為Node 0、Node 1、Node 2。您需要讓cgroup使用Node 0和Node 2兩個節點的記憶體。則<value>取值為0,2

記憶體片段化時夥伴系統記憶體不足

記憶體片段化時導致的OOM Killer,建議您定期在業務空閑時間段,進行記憶體整理。開啟記憶體整理功能的命令為:

sudo bash -c 'echo 1 > /proc/sys/vm/compact_memory'