サーバが急激なload負荷で固まってしまった現象に出会った際に見つけたoom-killer。
その時のことをまとめておきます。
現象としては、メモリを大量消費するプロセスが発生して、iowaitが発生。load負荷上昇が確認できました。
[html]
# 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
[/html]
それぞれの項目は以下のようです。
[html]
%user アプリケーション実行による ※ /user/領域配下
%nice niceコマンドで優先度変更したアプリケーション実行による
%system カーネル実行による
%iowait CPUのディスクIO待ち状態(アイドル状態)
%steal ゲストOSのリソース要求にも関らず、割当てられなかった時間
%idle CPUのディスクIO待ちを除くアイドル状態
[/html]
2:55には、%systemと%iowaitが高くなっています。
%systemが高い場合には、「I/O待ちでCPU時間を消費している」ことや「大きめのプロセスを頻繁にforkしている」ことが考えられるそうです。
アプリ側ではなく、カーネル関係で何かありそうです。
[html]
# 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
[/html]
[html]
kbmemfree: 物理メモリの空き容量
kbmemused: 使用中の物理メモリ量
%memused: 物理メモリ使用率
kbbuffers: カーネル内のバッファとして使用されている物理メモリの容量
kbcached: カーネル内のキャッシュ用メモリとして使用されている物理メモリの容量
kbswpfree: スワップ領域の空き容量
kbswpused: 使用中のスワップ領域の容量
%swpused: スワップ領域の使用率
[/html]
詳細はこちらのブログが分かりやすいです。
http://b.l0g.jp/dev/finding-bottleneck-with-sar2/
2:55を境に、スワップの利用率がアップしています。
スワップの利用率があがっていることから、物理メモリ不足な事態に陥ったことが分かります。
今回は%swpusedが高く%iowaitも発生しているので、スワップ領域へのアクセスによって、ioが遅くなっている事が分かります。
というわけで、2:55前後にスワップを利用するにまで至らせたプロセスがいたはずだ。というところまで来ました。
しかもその後、物理メモリ自体の消費もおさえられたので消えた?かもというのが分かります。
次に/var/log/messagesの確認です。
[html]
02:53:56 xxxxx1 kernel: crond invoked oom-killer: gfp_mask=0x200d2, order=0, oomkilladj=0
[/html]
ここに出ていました。oom-killer。
これが、該当プロセスを切っていたようです。
[html]
02:53:58 xxxxx1 kernel: Out of memory: Killed process 28036, UID 80, (xmllint).
[/html]
ちなみに、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も解説しています。