rsyslogdのエラー(Too many open files)について


1. 概要

rsyslogdプロセスのファイルディスクリプタ数が設定値を超えた場合、ローカルファイルへの書き込みなどができなくなってしまう。
主な原因として、rsyslogdプロセスにおいてログをTCPで受け取っている場合、ログの送信元と送信先の経路上にあるFWなどが勝手にセッションを破棄してしまい、ハーフコネクション状態に陥るためである。
要するに、FWが勝手にそのセッション(サーバ間ではコネクション)でパケットのやり取りが発生していないため、ドロップしてしまう。
TCPの状態遷移や実装に関する情報は以下を参考にさせていただきました。
TCP/IP通信の状態を調べる「netstat」コマンドを使いこなす (1/2)
net.ipv4.tcp_tw_recycle は廃止されました ― その危険性を理解する

2. TCPスタックの実装に関する設定

特にプロセス側の設定をしていなければ、カーネルの設定を利用する。
まずはカーネルの設定を確認する。

[root@vps ~]# sysctl -a | grep net.ipv4.tcp
# keepaliveパケットを送信するまで待機する秒数
net.ipv4.tcp_keepalive_time = 7200

# keepaliveパケットを送信し、応答がない場合の継続して送信する回数
net.ipv4.tcp_keepalive_probes = 9

# keepaliveパケットを送信し、応答がない場合の次のパケット送付まで待機する秒数
net.ipv4.tcp_keepalive_intvl = 75

# FIN-WAIT2 から TIME_WAIT に状態が変化するまでの時間
net.ipv4.tcp_fin_timeout = 60

# TIME_WAIT状態のソケットを新しい接続に対して安全に再利用
net.ipv4.tcp_tw_reuse = 0

3.対処

ここでしっかりと考えないといけないこととして、rsyslogdプロセスで受信している方において
FIN-WAIT_1の場合、net.ipv4.tcp_tw_reuse=1にしたとしても、そもそもFIN-WAIT_1であるから
対処となっていない。この場合は、FWにおけるセッションタイムアウトの時間を長くするか
rsyslogの設定において、keepaliveに関する設定をするかである。
現実的な解としては、後者のrsyslogの設定にkeepaliveに関する設定をすることである。

rsyslogにおけるkeepaliveに関する設定

rsyslogの公式ドキュメントを参考に設定。

$InputTCPServerKeepAlive on
$InputTCPServerKeepAlive_probes 5
$InputTCPServerKeepAlive_time 60