oom-killerについて




投稿日:

サーバが急激なload負荷で固まってしまった現象に出会った際に見つけたoom-killer。
その時のことをまとめておきます。

現象としては、メモリを大量消費するプロセスが発生して、iowaitが発生。load負荷上昇が確認できました。

# sar
02時30分01秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
02時35分01秒       all     11.77      0.00      1.21      0.04      0.08     86.91
02時40分01秒       all     10.87      0.00      1.15      0.01      0.08     87.88
02時45分01秒       all      9.44      0.00      1.14      0.03      0.09     89.30
02時55分02秒       all      2.89      0.00     62.36     10.40      0.02     24.32
03時00分01秒       all      0.30      0.00      0.42      1.13      0.02     98.13
03時05分01秒       all      0.74      0.00      0.63      0.62      0.03     97.98

それぞれの項目は以下のようです。

%user	アプリケーション実行による   ※ /user/領域配下
%nice	niceコマンドで優先度変更したアプリケーション実行による
%system	カーネル実行による
%iowait	CPUのディスクIO待ち状態(アイドル状態)
%steal	ゲストOSのリソース要求にも関らず、割当てられなかった時間
%idle	CPUのディスクIO待ちを除くアイドル状態

2:55には、%systemと%iowaitが高くなっています。
%systemが高い場合には、「I/O待ちでCPU時間を消費している」ことや「大きめのプロセスを頻繁にforkしている」ことが考えられるそうです。

アプリ側ではなく、カーネル関係で何かありそうです。

# sar -r
02時30分01秒 kbmemfree kbmemused  %memused kbbuffers  kbcached kbswpfree kbswpused  %swpused  kbswpcad
02時35分01秒    486132   3708172     88.41    162944    420820    526140    526108     50.00    274460
02時40分01秒    338764   3855540     91.92    163196    560968    526140    526108     50.00    274460
02時45分01秒    260660   3933644     93.79    163424    648044    526140    526108     50.00    274460
02時55分02秒   2566324   1627980     38.81      4452     72572    243608    808640     76.85     16544
03時00分01秒   2560564   1633740     38.95      5648     73744    246920    805328     76.53     19796
03時05分01秒   2551400   1642904     39.17      7024     78804    248848    803400     76.35     21148


kbmemfree: 物理メモリの空き容量
kbmemused: 使用中の物理メモリ量
%memused: 物理メモリ使用率
kbbuffers: カーネル内のバッファとして使用されている物理メモリの容量
kbcached: カーネル内のキャッシュ用メモリとして使用されている物理メモリの容量
kbswpfree: スワップ領域の空き容量
kbswpused: 使用中のスワップ領域の容量
%swpused: スワップ領域の使用率



詳細はこちらのブログが分かりやすいです。
http://b.l0g.jp/dev/finding-bottleneck-with-sar2/

2:55を境に、スワップの利用率がアップしています。
スワップの利用率があがっていることから、物理メモリ不足な事態に陥ったことが分かります。
今回は%swpusedが高く%iowaitも発生しているので、スワップ領域へのアクセスによって、ioが遅くなっている事が分かります。

というわけで、2:55前後にスワップを利用するにまで至らせたプロセスがいたはずだ。というところまで来ました。
しかもその後、物理メモリ自体の消費もおさえられたので消えた?かもというのが分かります。

次に/var/log/messagesの確認です。

02:53:56 xxxxx1 kernel: crond invoked oom-killer: gfp_mask=0x200d2, order=0, oomkilladj=0



ここに出ていました。oom-killer。
これが、該当プロセスを切っていたようです。

02:53:58 xxxxx1 kernel: Out of memory: Killed process 28036, UID 80, (xmllint).



ちなみに、oom-killerを調べてみると、死神さんでした。

こちらから引用させて頂くと、
http://itpro.nikkeibp.co.jp/article/COLUMN/20061117/254053/

 OOM Killer(Out of Memory Killer)は、システムが実メモリーと仮想メモリー空間(スワップ領域)を使い切り、必要なメモリー領域を新たに確保できない場合に、プロセスを強制終了させて空きメモリーを確保する、Linuxカーネルの仕組みです。OOM Killerは、空きメモリーが確保できないことによりシステム自体が停止するという最悪の事態を避けるために用意されています。

 OOM Killerは、空きメモリーを十分確保でき、システム上損失のなるべく少ないプロセスを選んで、強制終了します。また、強制終了するプロセスの数がなるべく少なくなるようにしています。実際に、どのプロセスを強制終了するかは、カーネル内部のbadness()関数が決めます。

 ただし、OOM Killerにより、システム上大切なプロセスが強制終了させられることもあります。システム・トラブルの原因に成り得ることから、大切なプロセスに対しては/proc/〈プロセスID〉/oom_adjファイルに「-17」を書き込んで、OOM Killerの対象から除外しておきます。具体的には、次のように実行します。
# echo -17 > /proc/〈プロセスID〉/oom_adj


これは、ダウンは防御できるのでうれしいですが、サービス関係が止まると思うと怖いですね。
これを発動させない方法などがあるようですが、まずは、メモリを割り当て出来そうだったのでメモリ割当で対応しました。

OOM Killerは別途確認すると共に、OOM Killerを利用した攻撃もあるそうなので勉強したいと思います。
fork bombも一緒に。

この本では、OOM Killerも解説しています。