モーグルとカバとパウダーの日記

モーグルやカバ(EXカービング)山スキー(BC)などがメインの日記でした。今は仕事のコンピュータ系のネタが主になっています。以前はスパム対策関連が多かったのですが最近はディープラーニング関連が多めです。

Linuxでファイルディスクリプタが足りなくなりサービス停止障害

今日、Web/メール等のサービスを稼働させてる自社のLinuxサーバが、突然サービスが停止してしまう障害が発生した。


特にメールでトラブルが広がっており、プロセス見るとdovecot deliverとpop3が多数止まっている状況だった。
ログを見ると、deliverは「still being delivered」というエラー、pop3は「Too many open files in system」等のエラーを吐いていた。


最初はメールだけのトラブルと思い、とりあえずdovecotpostfixの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_

無理矢理リブートする前に、とりあえず今まだ走ってるデーモン達を殺して回る。
apacheMySQL、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」で設定出来る