OOM Killerからプロセスを守る oom_adj、実は非推奨だった

  • Linux
  • OOM Killer
  • Kernel

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

メモリ不足でOOM Killerが暴れて、意図しないプロセスが落ちる問題。対策としてoom_adjをいじる方法を調べたので整理しておく。

Kill対象の確認

dstatに--top-oomというプラグインがあって、次にOOM Killerに殺されそうなプロセスとそのkill scoreを表示してくれる。

$ sudo yum install dstat -y
$ dstat --top-oom
--out-of-memory---
kill score
(squid-1) 62
(squid-1) 62
(squid-1) 62

このscoreが高いプロセスほど、メモリ不足時に真っ先に殺される。

oom_adjでKill対象から除外する

/proc/[pid]/oom_adjに-17を書き込むと、そのプロセスをOOM Killerの対象から完全に除外できる。

$ echo "-17" > /proc/[pid]/oom_adj

値の範囲は-16(除外されにくい方向)から+15(狙われやすい方向)で、-17だけ特別扱いで「完全除外」の意味になるらしい。

ただしこれ、非推奨

調べてて分かったんだけど、oom_adjはカーネル2.6.36から非推奨(deprecated)になってる。代わりに/proc/[pid]/oom_score_adjが本命になってて、こっちは-1000〜1000の範囲で調整する。-1000を書けばoom_adjの-17と同じく完全除外扱い。

$ echo "-1000" > /proc/[pid]/oom_score_adj

oom_adjは後方互換のために今のカーネルでも残ってて、書き込むと内部でoom_score_adj側にスケール変換されて反映される仕組みらしい(実機で変換式まで追ってはいない)。なので動くには動くけど、新しく書くスクリプトならoom_score_adjを直接使う方が素直だと思う。

まとめると

  • 古いカーネル(2.6.36より前)はoom_adjしかない
  • 2.6.36以降はoom_score_adjが追加されて、oom_adjは非推奨に
  • 今のカーネルは両方存在するけど、推奨はoom_score_adj

RHEL6系みたいな古い環境の手順ならoom_adjのままで問題ないけど、新しい環境向けに書くならoom_score_adjに置き換えた方がいい。