oranie's blog

旧:iをgに変えると・・・なんだっけ・・・

#fluentd VMware+fluentdで「no nodes are available」が出てしまう問題と対処方法

何が問題?

VMware ESXi5系(4系もかも)のVM(今回はCentOS5.4 64bit td-agent-1.1.10.3-0)同士でfluentdを使うと、td-agent.logに以下の様なエラーが吐かれる場合があります。

2012-11-07 23:08:10 +0900: temporarily failed to flush the buffer, next retry will be at 2012-11-07 23:09:13 +0900. error="no nodes are available" instance=23456251017660
  2012-11-07 23:08:10 +0900: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.27/lib/fluent/plugin/out_forward.rb:146:in `write_objects'
  2012-11-07 23:08:10 +0900: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.27/lib/fluent/output.rb:439:in `write'
  2012-11-07 23:08:10 +0900: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.27/lib/fluent/buffer.rb:279:in `write_chunk'
  2012-11-07 23:08:10 +0900: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.27/lib/fluent/buffer.rb:263:in `pop'
  2012-11-07 23:08:10 +0900: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.27/lib/fluent/output.rb:303:in `try_flush'
  2012-11-07 23:08:10 +0900: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.27/lib/fluent/output.rb:120:in `run'
2012-11-07 23:09:14 +0900: temporarily failed to flush the buffer, next retry will be at 2012-11-07 23:11:21 +0900. error="no nodes are available" instance=23456251017660

なんでこんなエラーになるの??

何が起きているかと言うと、正しく設定を行なっているfluentd同士でもforwardプラグインを使って通信をしようとした時に、OSのNICドライバでvmxnet3ドライバを選択していると、実はHeartBeat用のUDPパケットがdropされているのです。互いにtcpdumpを取得すると分かりやすいです。

/usr/sbin/tcpdump -i eth0 port 24224
とかで

で、vmxnet3ドライバのBugなので今のところLinux使っている限り直りません。
ただ、素晴らしいことに対処方法がちゃんとナレッジベースに書かれています。どれどれ。(^ω^)
http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2019944

・・・・・・・・

要約すると【NICを作りなおしてドライバを「e1000」に変えろ】という素晴らしいナレッジです。完璧ですね。(#^ω^)

ただ、そうは言っても何十台とか何百台とか作っちゃっている場合あるじゃないですか。それのドライバを変更するとか気が遠くなるので何か他に方法は無いかというと、このBugは「小さなサイズのUDPはdropする」というBugなのです。

じゃあ、fluentd自体をどう直すか

で、fluentdのforwardで使用しているudpパケットのデータは「\0」だけです。(今のVerを見る限り)
なので、送信側のfluentdの
/usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.27/lib/fluent/plugin/out_forward.rbの259行目を

@usock.send "\000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 0, Socket.pack_sockaddr_in(n.port, n.resolved_host)

と書き換え、今度は受け取る側のfluentdの
/usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.27/lib/fluent/plugin/in_forward.rbの204行目を

@usock.send "\000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 0, host, port

と書き換えると、互いにforwardで送信するパケットがちょっとおっきくなるので、無事UDPパケットがdropされずにheartbeatがちゃんと成功します。

多分、こんなアホな特殊な事例の為にpullreqしてもマージしてくれないと思うのでブログに書きました。みんなが困ればfluentd側の修正が入るか、VMware側が修正されるかどちらかがいつかは直るかも。もしくはfluentd側にtcpでのheartbeatモードを誰かpullreqして下さい><