Linux オペレーティングシステムでメモリが不足すると、システムはメモリを回収し、回収したメモリを他のプロセスに割り当てます。メモリ回収でメモリ不足の問題が解決しない場合、システムは Out of Memory Killer (OOM Killer) をトリガーして、プロセスが占有しているメモリを強制的に解放します。これにより、メモリプレッシャーが軽減されます。このトピックでは、Alibaba Cloud Linux で OOM Killer がトリガーされる問題の考えられる原因と、その解決方法について説明します。
現象
次のログサンプルは、Alibaba Cloud Linux で test プロセスが OOM Killer をトリガーしたことを示しています。
565 [Sat Sep 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 [Sat Sep 11 12:24:42 2021] test cpuset=/ mems_allowed=0
567 [Sat Sep 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 [Sat Sep 11 12:24:42 2021] Hardware name: Alibaba Cloud Alibaba Cloud ECS, BIOS e62**** 04/01/2014
考えられる原因
OOM Killer は、システムのメモリが不足したときにトリガーされます。このメモリ不足は、インスタンス全体に影響を与えるグローバルなものの場合もあれば、特定の cgroup に限定される場合もあります。一般的なシナリオと原因は次のとおりです。
原因タイプ | シナリオ例 |
cgroup のメモリ不足 | 次のログ例では、test プロセスを含む /mm_test cgroup で 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
原因:/mm_test cgroup のメモリ使用量が上限 (200 MB) に達したため、OOM Killer がトリガーされました。 |
親 cgroup のメモリ不足 | 次のログ例では、test プロセスは /mm_test/2 cgroup に属していますが、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
原因:/mm_test/2 cgroup のメモリ使用量は上限に達していませんでしたが、親 cgroup の /mm_test のメモリ使用量が上限 (200 MB) に達したため、OOM Killer がトリガーされました。 |
システム全体のメモリ不足 | 次のログ例では、limit of host はインスタンス上のグローバルなメモリ不足を示しています。ログデータは、ノード 0 の空きメモリ (free) が低ウォーターマーク (low) を下回ったことを示しています。 [Sat Sep 11 12:24:42 2021] test invoked oom-killer: gfp_mask=0x62****(GFP_HIGHUSER_MOVABLE|__GFP_ZERO), nodemask=(null), order=0,
[Sat Sep 11 12:24:42 2021] Task in /user.slice killed as a result of limit of host
[Sat Sep 11 12:24:42 2021] Node 0 DMA32 free:155160kB min:152412kB low:190512kB high:228612kB
[Sat Sep 11 12:24:42 2021] Node 0 Normal free:46592kB min:46712kB low:58388kB high:70064kB
原因:インスタンスの空きメモリ量が空きメモリの下限値を下回り、メモリ回収ではメモリ不足の問題を解決できません。 |
メモリノードのメモリ不足 | 次のログに記録されているように OOM Killer がトリガーされたシナリオでは、ログデータは次の情報を提供します。 limit of host はメモリノードのメモリ不足を示します。
インスタンスには、ノード 0 とノード 1 の 2 つのメモリノードがあります。 ノード 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 (Non-Uniform Memory Access) アーキテクチャでは、オペレーティングシステムは複数のメモリノードを持つことができます。cat /proc/buddyinfo コマンドを実行して、ノードに関する情報を表示できます。cpuset.mems パラメーターが cgroup を特定のノードからのメモリのみを使用するように制限している場合、インスタンスに十分な空きメモリが全体的にあっても OOM Killer がトリガーされる可能性があります。 |
バディシステムは、メモリの断片化が発生した場合、十分なメモリが不足します。 | 次のログに記録されているように OOM Killer がトリガーされたシナリオでは、ログデータは次の情報を提供します。 OOM Killer は order=3 のメモリ割り当てフェーズでトリガーされます。 ノード 0 の空きメモリ (free) は、まだ低ウォーターマーク (low) を上回っています。 バディシステム内のノード 0 に対応するメモリは 0 (0*32kB (M)) です。
[Sat Sep 11 15:22:46 2021] insmod invoked oom-killer: gfp_mask=0x60****(GFP_KERNEL), nodemask=(null), order=3, oom_score_adj=0
[Sat Sep 11 15:22:46 2021] insmod cpuset=/ mems_allowed=0
[Sat Sep 11 15:22:46 2021] Task in /user.slice killed as a result of limit of host
[Sat Sep 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
[Sat Sep 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 のカーネルメモリ管理メカニズムであり、メモリの断片化を軽減し、さまざまなサイズのメモリブロックを効率的に割り当て、解放します。 |
ソリューション
シナリオに基づいて次の手順を実行し、問題をトラブルシューティングします。
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 メモリは、システムによって回収できないメモリです。slab_unreclaimable メモリが総メモリの 10% 以上を占める場合、システムに slab メモリリークがある可能性があります。メモリリークのトラブルシューティング方法については、「インスタンスの slab_unreclaimable メモリの割合が高い場合の対処方法」をご参照ください。問題が解決しない場合は、するか、チケットを送信してください。
systemd メモリの使用量
cat /proc/1/status | grep "RssAnon"
カーネルで OOM Killer がトリガーされると、システムの最初のプロセス (PID 1) はスキップされます。この場合、systemd のメモリ使用量は 200 MB を超えません。例外が発生した場合は、systemd のバージョンを更新できます。
THP (Transparent Enormous Pages) 機能の使用
THP 機能が有効になっている場合、メモリ肥大化が発生し、OOM Killer がトリガーされることがあります。THP のパフォーマンスを最適化できます。詳細については、「Alibaba Cloud Linux で THP を使用してパフォーマンスをチューニングする方法」をご参照ください。
メモリノードのメモリ不足
メモリノードのメモリ不足が原因で OOM Killer がトリガーされた場合は、cpuset.mems パラメーターを再設定します。これにより、cgroup が正しいノードからメモリを使用できるようになります。
次のコマンドを実行して、システム内のメモリノードの数をクエリします。
cat /proc/buddyinfo
cpuset.mems パラメーターを設定します。
sudo bash -c 'echo <value> > /sys/fs/cgroup/cpuset/<cgroup_name>/cpuset.mems'
このコマンドでは、<value> を対応するメモリノードの番号に、<cgroup_name> を実際の cgroup 名に置き換えます。
たとえば、システムに 3 つのノード (ノード 0、ノード 1、ノード 2) があり、cgroup がノード 0 とノード 2 からメモリを使用できるようにする場合は、<value> を 0,2 に設定します。
メモリ断片化によるバディシステムのメモリ不足
メモリの断片化が原因で OOM Killer がトリガーされた場合は、オフピーク時に定期的にメモリのデフラグを実行します。次のコマンドを実行して、メモリの断片化を解消できます。
sudo bash -c 'echo 1 > /proc/sys/vm/compact_memory'