ビデオもあるよ → こちら
おぉ、200ブクマとか付いてる^^
追記:ブクマで教えてもらったのですが、serf join の時に特定のノードを指定しなければいけない問題については、v0.4.5 で -discover オプションが追加されて join する「クラスタ」を指定できるようになったそうです。
$ self join -discover=web
のような。 mDNS (multicast DNS) を利用するらしいですね。うーん、multicast かー。。。
まとめとく。out_forward プラグインのパラメータ一覧はオフィシャルドキュメントへ
2014-03-11 00:53:34 +0900 [warn]: detached forwarding server 'host:22442' host="host" port=22442 phi=12.123
heartbeat の結果、サーバが応答せず phi_threashold を超えてしまった場合に出るメッセージ。
なお、ここで言う heartbeat とは、out_forward プラグインが in_forward プラグインに対して 1s (デフォルト)毎に udp (デフォルト)パケットを送信し、さらに in_forward がそれに対して udp パケットを返却することで行っている死活監視。
受信側の Fluentd において、内部処理でブロックしている。
送信元の Fluentd において、内部処理でブロックしている。
そもそも heartbeat パケットを送れていない
heartbeat_interval を変更したたために、適切な phi_threshold の値が変わってしまっている。
CPU使用率が高い場合(送信・受信いずれか、または両方)
プラグインがブロックしている場合(送信・受信いずれか、または両方)
そもそも heartbeat パケットが届いていない
heartbeat_interval を変更したら適切な phi_threshold の値が変わってしまった
問答無用で detach したくない場合
そもそも phi ってなんぞ
2014-03-11 00:53:34 +0900 [warn]: detached forwarding server 'host:22442' host="host" port=22442 hard_timeout=true
hard_timeout (デフォルト 60s) の間、heartbeat への反応がなかった場合に出るメッセージ。 phi_threshold で detach されるよりも状況が逼迫していると思って良い。
基本的には phi_threshold の場合と同様。
基本的には phi_threshold の場合と同様。hard_timeout を大きくして誤摩化したところで 60s 以上の遅延が発生しているのだから対策を打った方がよい。
ネットワーク設定も疑ったほうがよい。次の章にまとめて記述する。
2014-03-11 12:37:37 +0900 [warn]: temporarily failed to flush the buffer. next_retry=2014-03-11 12:37:37 +0900 error_class="Errno::ECONNREFUSED" error="Connection refused - connect(2) for \"192.168.0.2\" port 22442" instance=70182894105380
こちらは heartbeat ではなくメッセージ送信が失敗した場合に出るメッセージ。実際のエラーはログの error_class などを見てググると良い。
さらに retry 上限を超えると retry count exceeds limit
の warn メッセージが出る
受信側の Fluentd において、内部処理で時間がかかるなどしてブロックしている。
開いているソケットの数が多くなりすぎて1プロセスが開けるファイルディスクリプタの数を超えてしまっている。
受け付けられるTCP接続要求の上限値を超えている。
CPU使用率が高い場合(受信)
プラグインがブロックしている場合(受信)
開いているソケットの数が多くなりすぎて1プロセスが開けるファイルディスクリプタの数を超えてしまっている(送信・受信いずれか、または両方)
lsof -p [PID] | wc -l
や cat /proc/sys/fs/file-nr
で開いているファイルの数を確認。参考になるサイトのリンクを貼っておくが、ググって欲しい
受け付けられる接続要求の上限値を超えている(送信・受信いずれか、または両方)
cat /proc/sys/fs/file-nr
で開いているファイルの数を確認。参考になるサイトのリンクを貼っておくが、ググってほしい。
今まで fluent-agent-lite の生存監視には fluent-plugin-ping-messge を利用していたのだが、agent を動かしているサーバをつぶしただけでアラートが飛んできたり、in_ping_message を動かしているノードがCPUあまってるのにデータを受け付けてくれなくて誤検知したり、元から agent が死んでいるとそもそも検知できない、などの問題があったので引退して普通に生存監視することにした。fluent-agent-lite の監視方法をまとめておく。
ふつうに ps auxww | grep fluent-agent-lite してみるのがよい。fluent-agent-lite は init スクリプト内でログごとにプロセスを立ち上げるので、/etc/fluent-agent-lite.conf のログ一覧をとってきて、さらにログパスで grep し、ヒットする行がなければ死んでいるという判断をする必要あり。
fluent-agent-lite.conf はシェルスクリプトなのでログ一覧は $LOGS を変数展開すれば取得できる。
INFO レベルで出るが、デフォルトでは INFO ログは出ない。conf で LOG_VERBOSE=yes を設定すると出る。
2014-03-12T15:51:24 [INFO] (25118) SIGHUP (or SIGTERM) received at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 195
2014-03-12T15:51:24 [INFO] (25118) disconnecting to current server at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 199
2014-03-12T15:51:24 [INFO] (25118) disconnected. at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 204
2014-03-12T15:51:24 [WARN] (25118) SIGTERM received at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 206
2014-03-12T15:51:24 [INFO] (25118) process exit at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 209
2014-03-12T15:51:24 [INFO] (25118) Sending TERM to pid 25127 at /usr/local/fluent-agent-lite/bin/fluent-agent-lite line 262
2014-03-12T15:51:24 [INFO] (25118) process exit. at /usr/local/fluent-agent-lite/bin/fluent-agent-lite line 273
WARN レベルなのは、SIGTERM received だけなので、シグナル以外のなんらかの理由で不意に死んだことがわからない。 LOG_VERBOSE=yes にして、INFO ログも出力しておくことが推奨される(なお、INFOログの量はたいしたことない. DEBUGログは1つもない)
tail プロセスが死んだ場合は bin/fluent-agent-lite も死ぬのでそちらの死活監視だけでまかなえそう
=> 訂正: やっぱり defunct な tail プロセスがいないか監視したほうがよさそう(理由は後述)
2014-03-12T15:42:19 [WARN] (8711) failed to read from child process, maybe killed. at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 227
give up to read tailing fd, see logs at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 228.
Fluent::AgentLite::drain('Fluent::AgentLite=HASH(0x88e7d10)', 'IO::Handle=GLOB(0x88ca9c8)', undef) called at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 168
Fluent::AgentLite::execute('Fluent::AgentLite=HASH(0x88e7d10)', 'HASH(0x88ca098)') called at /usr/local/fluent-agent-lite/bin/fluent-agent-lite line 252
main::main() called at /usr/local/fluent-agent-lite/bin/fluent-agent-lite line 271
可能性としては、
I/O error with tail fd
がでることもありそう。
訂正: 対向 fluentd サーバにつながらないなどして reconnect ループしている場合は、tail のエラー処理に入れず fluent-agent-lite が死なない模様。そして tail が defunct (ゾンビ) の状態で残ってしまう。該当コード。
このレアケースもカバーしたい完璧主義な方は ps auxww | grep tail | grep defunct がヒットしないか監視すると良い。 うちはやらないことにしたけど。
コラム: tail 子プロセスのプロセス表示名はいじれるか?
tail プロセスの ps での表示名をいじって、通常の tail プロセスと区別がつきやすいようにしたかったのだが(誰かに間違って kill されたことがあると事例をきいたので、間違い防止のため)、どうも無理そうだった。tail コマンド自体をいじって中で prctl(2) を呼ぶとかできるようにしないと無理っぽい。
送信に失敗した場合や、KEEPALIVE_TIME を過ぎた場合は、ランダムでノードを選択して reconnect する。
その接続失敗時にログに出る "waiting xx seconds to reconnect" の頻度(2回以上など)で監視する。
xx の値が 30 秒(任意)より大きいログが何度も出ているようならアラートを飛ばす、のようにすると良い。
実際に出るログは以下のようなかんじ
2014-03-12T16:49:55 [WARN] (5444) failed to connect to server ['localhost','20000'] : 接続を拒否されました at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 330
2014-03-12T16:49:55 [WARN] (5444) failed to connect to server ['localhost','21000'] : 接続を拒否されました at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 330
2014-03-12T16:49:55 [WARN] (5444) failed to connect servers, primary: ['localhost','20000'], secondary: ['localhost','21000'] at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 135
2014-03-12T16:49:55 [WARN] (5444) waiting 4 seconds to reconnect at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 136
2014-03-12T16:49:59 [WARN] (5444) waiting 8 seconds to reconnect at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 136
接続失敗時に、ログに "Cannot send data" と出るのでその頻度で監視できる。
実際に出るログは以下のようなかんじ
2013-11-21T21:11:21 [WARN] (21263) Cannot send data: パイプが切断されました at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 305.\n at /usr/local/fluent-agent-lite/bin/../lib/Fluent/AgentLite.pm line 321
以下のようなエラーが出ていることがあった
/usr/bin/tail: inotify cannot be used, reverting to polling: Too many open files
現象のおきたサーバで状況を確認
$ cat /proc/sys/fs/file-nr
16320 0 2423842
$ sudo sysctl -a | grep fs.inotify
fs.inotify.max_user_instances = 128
fs.inotify.max_user_watches = 8192
fs.inotify.max_queued_events = 16384
fs.inotify の値を引き上げると良いが、監視しておいてもよいだろう。特に max_user_instances はデフォルト値が 128 と少ないので増やしておきたい。
追記: なお、1つファイルを tail するのに、inotify_init システムコールが1回、inotify_add_watch システムコールが2回呼ばれるようだ。tail プロセスの数をカウントして max_user_instances をプロセス数よりも大きい値に、max_user_watches をプロセス数 x 2 よりも大きい値に変更する必要がある。
$ ( sudo strace -s 1024 tail -F /var/log/boot.log 2>&1 ) | grep inotify
inotify_init() = 3
inotify_add_watch(3, "/var/log", IN_ATTRIB|IN_MOVED_TO|IN_CREATE) = 1
inotify_add_watch(3, "/var/log/boot.log", IN_MODIFY|IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF) = -1 EACCES (Permission denied)
追記: プロセスが inotify_init しているか、さらに何個の inotify_add_watch をしているかは、linux kernel 3.x (debian 系、centos 7以上)ならばみることができる。
$ ls -l /proc/${pid}/fd/
lr-x------ 1 sonots sonots 64 Nov 19 12:56 5 -> anon_inode:inotify
$ cat /proc/${pid}/fdinfo/5
pos: 0
flags: 00
inotify wd:2 ino:520054 sdev:800001 mask:800ac06 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:540052009caa5375
inotify wd:1 ino:520053 sdev:800001 mask:800ac06 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:5300520095aa5375
まとめ
1. bin/fluent-agent-lite の生存監視
2. tail 子プロセスの生存監視
3. fluent-agent-lite の接続監視
4. fluent-agent-lite の送信失敗監視
5. inotify 監視
を監視するとよい。うちでは、1, 3, が MUST で、2, 4, 5 は WANT とした。