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內存不足
建議您自行評估實例內當前占用內存的進程情況,及時清理不需要的進程,以釋放內存。如果您的業務所需的內存較大,當前實例規格不滿足您對內存的需求,可以升配實例以提升實例的內存容量。
升配實例。
更多信息,請參見升降配方式概述。
根據內存實際的提升情況,手動調整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能夠合理使用內存節點的內存。
運行以下命令,確定系統中內存節點(Node)的數量信息。
cat /proc/buddyinfo
配置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'