OOM Killer(Out of Memory Killer)とは?
Linuxは、メモリ不足でOS自体が安定稼働できない場合、メモリリソースを多く消費しているプロセスを強制的に停止(Kill)します。
これをOOM Killerといいます。
Out of Memory(メモリを確保できない)ので Kill(プロセスを殺す)する名称通りの機能ですね。
rootで実行されているシステム系のプロセスは、Killされることはありませんが、一般ユーザ権限のプロセスがKillの対象になります。
OSのメモリ管理
OSは以下の挙動をします。
(1)物理メモリを使用
(2)物理メモリが足りなくなったら、スワップ領域(ストレージ)を使用
(3)更にメモリが足りなくなったら、OS自体が稼働不可になることを防ぐために、OOMKiller(Out of Memory Killer)機構によりメモリを多く使用しているプロセスを強制停止し空きメモリを作ります。
OOM Killerを再現させる
実験環境
Ubuntu 22.04 server: 物理メモリ8GB、スワップ領域4GB
メモリ管理とデータ分析方法と、利用したプログラムのソースファイルに関しては以下の記事を参照ください。
https://relax-tech.net/linux-os-swap/
検証プログラム
Java 、C言語の2パターン
物理メモリとスワップ領域が不足するまで、複数実行して確認。
現象確認 javaアプリ
リアルタイムでメモリ利用状況とOOM Killerの動作を確認する方法を紹介します。
以下を複数のコンソールを開いて実行して、メモリの使用状況を確認します。
a)free –h (10秒間隔)
b)topコマンドで VIRT/RESなど確認
c)dstatコマンドでpage IN/OUTを確認
e)プログラムの実行。バックジョブで複数実行
$ java MemoryFileRead &
$ java MemoryFileRead &
$ java MemoryFileRead &
:
現象確認 C言語アプリ
リアルタイムでメモリ利用状況とOOM Killerの動作を確認する方法を紹介します。
Javaアプリと同じ手順です。プログラミング言語による違いがないことの確認のため。
以下を複数のコンソールを開いて実行して、メモリの使用状況を確認します。
a)free –h (10秒間隔)
b)topコマンドで VIRT/RESなど確認
c)dstatコマンドでpage IN/OUTを確認
e)プログラムの実行。バックジョブで複数実行
$ ./program1 &
$ ./program1 &
$./program1 &
:
OOM Killer発生時の確認方法
OOM Killerが発生した場合、以下のログファイルに情報が出力されます。
Ubuntu系:/var/log/syslog
RHEL系:/var/log/messages
grep -i kill /var/log/syslog
grep -i kill /var/log/messages
以下のようなログが出力されています
どのプロセスを停止させて、他にどのようなプロセスが実行中だったかがログに出力されます。
これをもとに原因を調査します。
自分のプログラムがメモリを確保しすぎただけであれば、自分のプログラムを適切なメモリ量で動作するように修正すればいいのですが
たまに、他のプロセスがメモリを確保しすぎて被害者としてKillさせられることがあります。
Feb 2 10:43:54 ubuntu2204 kernel: [ 2165.927697] Out of memory: Killed process 15562 (java) total-vm:5688392kB, anon-rss:768kB, file-rss:2464kB, shmem-rss:0kB, UID:1000 pgtables:2584kB oom_score_adj:0
Feb 2 10:43:55 ubuntu2204 systemd[1]: session-7.scope: A process of this unit has been killed by the OOM killer.
■C言語のプログラム(program1)がKILLされたときのログ1
■C言語のプログラム(program1)がKILLされたときのログ2
OOM Killer(Out of Memory Killer)のログに表示される各項目の意味は以下の通りです。この情報は、メモリ不足が発生した際に、どのプロセスがどれだけメモリを使用していたか、どのプロセスが終了対象となったかを分析するのに役立ちます。
oom_score_adjのスコアが高く、RSS(物理メモリ使用量)が高く、swapents(スワップ使用量)が高いプロセスがKILLの対象になるようです。total_vmのサイズが関係する場合もあるようです。
シスログ(/var/log/syslog , /var/log/messages)のOOMkillerの関する項目の説明
OOM killerを防ぐ方法
OOM Killerを未然に防ぐためには、以下の対策が考えられます。
1. メモリ増設:
最も根本的な対策は、物理メモリを増設することです。メモリ容量が増えることで、より多くのプロセスを同時に実行できるようになり、OOM Killerが発動する可能性を減らすことができます。
2. スワップ領域の調整:
スワップ領域は、物理メモリが不足した場合に、一時的にデータを保存するために使用されるディスク上の領域です。適切なサイズのスワップ領域を確保することで、物理メモリ不足を緩和することができます。ただし、スワップ領域は物理メモリよりもアクセス速度が遅いため、過度な使用はパフォーマンス低下につながる可能性があります。
3. メモリ使用量の最適化:
不要なプロセスの停止: 実行中のプロセスの中で、不要なものを停止することで、メモリ使用量を減らすことができます。
メモリリークの調査: メモリリークが発生している場合、プログラムのバグを修正することで、メモリ使用量を削減できます。
アプリケーションの設定見直し: アプリケーションの設定を見直し、メモリ使用量を抑えることができる場合があります。例えば、キャッシュサイズや同時接続数などを調整することで、メモリ使用量を削減できることがあります。
4. OOM Killerの設定調整:
OOM Killerは、どのプロセスを優先的にkillするかを決定するために、各プロセスにスコアを割り当てます。このスコアを調整することで、特定のプロセスがOOM Killerにkillされるのを防ぐことができます。
そもそもシステム全体でメモリが足りていないので、これはやらないほうがいいと思います。
最後に
OOM killerは、Linuxサーバでいろいろなアプリが動作していると、行儀の悪いプログラムやメモリのサイジングのミスでたまに発生しますが、本番システムで発生するとビビります。
今回のOOM Killerの知識はいざという時に必要な知識になります。あまり経験したくありませんが。。。
なお、メモリ管理とメモリの調査方法については以下の記事も役に立ちます。
https://relax-tech.net/linux-os-swap/