今日、Web/メール等のサービスを稼働させてる自社のLinuxサーバが、突然サービスが停止してしまう障害が発生した。
特にメールでトラブルが広がっており、プロセス見るとdovecot deliverとpop3が多数止まっている状況だった。
ログを見ると、deliverは「still being delivered」というエラー、pop3は「Too many open files in system」等のエラーを吐いていた。
最初はメールだけのトラブルと思い、とりあえずdovecotとpostfixのstopを掛けたのだが、デーモンの親プロセスは死ぬもののdeliverもpop3もSTATが「D」や「Ds」となっていたため「# kill -9」しても死なず。
いくつかログを見たところ、ファイルシステムの障害は考えにくかったため、リブートするしかなかろうということで「# shutdown -r now」することにした。
…が、shutdownもできず。
「shutdown -r 0」のプロセスまでSTATが「D」で待っている状況となってしまった。
だいぶ泣ける状況だったが、逆にターミナルは生きていたため、仕方ないのでもう少し調べてみることにした。
メールが怪しいと思ったためメールログを調べていくと、前記の特徴的なエラーメッセージより、この障害が発生した時間が特定できた。
そこで /var/logを「ls -lt」してみてその時間あたりに吐かれたログファイルを見つけた。
kern.logだった。
/var/log/kern.log を見ると、そこには見慣れないエラーが…
kernel: VFS: file-max limit 8192 reached
ぐぐったところこれは、ファイルディスクリプタが足らなくなった場合にでるエラーとのことだった。
とりあえずこれで、デーモンが軒並み動けなくなった理由は判明。
なぜファイルディスクリプタが足らなくなったかは置いといて、まず復旧を考える。
Linuxあれこれ
http://www1.ocn.ne.jp/~baba/linuxarekore/linuxarekore_body.html#F_LABEL0
linuxでヘビーなサイトを運用していると
kernel: VFS: file-max limit 4096 reached
が表示されることがあります。echo 32768 > /proc/sys/fs/file-max
により動的にリブートすることなく解決できます。
とのことだったので、早速これを試してみたのだがデーモンたちは相変わらず死体のまま転がっている。
twitterでshutdownでリブートできない場合の対処を聞いたところ、早速いろいろレスをいただく。
@eggles さんから
sync;sync; halt
@matchy2 さんから
reboot -f
@ttkzw さんから
rebootコマンドでもどうしようもないときには、"echo b > /proc/sysrq-trigger"をするとハードウェアリブートします。アンマウントとかsyncとかの処理は一切しないので、色々要注意ですが。
といった具合。
アドバイスいただいた皆様、ありがとうございます _o_
無理矢理リブートする前に、とりあえず今まだ走ってるデーモン達を殺して回る。
apacheやMySQL、postgrey、bindといったあたりを停止していくが、bindを止めようとしている段階でターミナルが反応しなくなってしまった… orz
リモートで利用しているサーバなので、しょうがないのでサポートに電話してリブートの処理をしていただく。sakuraのサポートさんありがとう。
結果、無事リブートしてきた。ちなみにサポートの方曰く、コンソールは生きてて、反応が悪いというだけの状況だったように思う、とのこと。
リブートして設定が戻っているため、再度 file-max の値を修正。
永続的に修正するため、下記ページを参考に設定変更。
システム関連/Linux - 180.style Wiki
http://180.style.coocan.jp/wiki/?%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E9%96%A2%E9%80%A3%2FLinux
/etc/sysctl.conf に設定を追加する。
fs.file-max=32768
また、これまでにオープンしたファイル最大数も確認してみた。
# cat /proc/sys/fs/file-nr
3425 1660 32768
3425がOS起動後これまでの最大数。
結構思ってた以上に使ってていたので、このくらいは設定しておいたほうが無難だろう。
というわけで今回の障害で学んだことまとめ。
- ファイルディスクリプタが足らなくなるとデーモンがみなこける
- するとSTATが「D」で止まってしまい、こうなるとkill -9でも死なないのでリブートするしかない
- /var/log/kern.logに「kernel: VFS: file-max limit 8192 reached」というログが吐かれる
- この状態のままリブート掛けるとshutdownまで刺さってしまう(設定増やしてからならいける?)
- 「sync;sync;reboot -f」は可能?ダメなら「echo b > /proc/sysrq-trigger」でハードリセット
- 最大ファイルディスクリプタ数は「echo 32768 > /proc/sys/fs/file-max」で動的に変更可能
- /etc/sysctl.confに「fs.file-max=32768」で設定出来る