最近 Amazon Elasticsearch Service にログを転送している Aggregator の /var/log/td-agent/td-agent.log
に以下のログが出力されていて,調査してわかった fluent-plugin-aws-elasticsearch-service を使う場合に必要な設定に関してまとめておく.
2016-10-24 16:54:50 +0900 [warn]: temporarily failed to flush the buffer. next_retry=2016-10-24 16:54:52 +0900 error_class="Elasticsearch::Transport::Transport::Error" error="Cannot get new connection from pool." plugin_id="xxx" 2016-10-24 16:54:50 +0900 [warn]: suppressed same stacktrace 2016-10-24 16:54:52 +0900 [warn]: temporarily failed to flush the buffer. next_retry=2016-10-24 16:54:56 +0900 error_class="Elasticsearch::Transport::Transport::Error" error="Cannot get new connection from pool." plugin_id="xxx" 2016-10-24 16:54:52 +0900 [warn]: suppressed same stacktrace 2016-10-24 16:54:56 +0900 [warn]: temporarily failed to flush the buffer. next_retry=2016-10-24 16:55:04 +0900 error_class="Elasticsearch::Transport::Transport::Error" error="Cannot get new connection from pool." plugin_id="xxx" 2016-10-24 16:54:56 +0900 [warn]: suppressed same stacktrace 2016-10-24 16:55:04 +0900 [warn]: temporarily failed to flush the buffer. next_retry=2016-10-24 16:55:22 +0900 error_class="Elasticsearch::Transport::Transport::Error" error="Cannot get new connection from pool." plugin_id="xxx" 2016-10-24 16:55:04 +0900 [warn]: suppressed same stacktrace 2016-10-24 16:55:22 +0900 [warn]: temporarily failed to flush the buffer. next_retry=2016-10-24 16:55:51 +0900 error_class="Elasticsearch::Transport::Transport::Error" error="Cannot get new connection from pool." plugin_id="xxx" 2016-10-24 16:55:22 +0900 [warn]: suppressed same stacktrace
関連するプラグインなど
Fluentd で Amazon Elasticsearch Service にログを転送する場合,fluent-plugin-aws-elasticsearch-service を使うと思う.基本的には fluent-plugin-elasticsearch に依存していて,AWS で必要になる署名部分を拡張してサポートしてくれている.また fluent-plugin-elasticsearch で Elasticsearch に接続する部分は elasticsearch-ruby に依存していて,今回説明する Fluentd の設定は全て elasticsearch-ruby (Elasticsearch::Transport) の設定となる.関係性をザッと覚えておくと良いかと.
設定 3種類
1. reload_connections
(Default : true)
Elasticsearch クラスタのノードリストを更新するかどうかを設定する.デフォルトだと true になっていて,10000回リクエストを送ると自動的に更新されるようになっている.
しかし fluent-plugin-elasticsearch の README にも記載されている通り,Elasticsearch クラスタにリバースプロキシ経由で接続している場合(言い換えると Elasticsearch ノードに直接アクセスできない場合)に問題になることがある.Amazon Elasticsearch Service を使うと発生する問題はまさにここに該当する.README に Amazon Elasticsearch Service の場合は注意!と明記してくれたら事前に気付けたと思うけど,リバースプロキシ経由と書かれてしまうと気付かなかった.README に書いて欲しさ...!
This can be an issue if your ElasticSearch cluster is behind a Reverse Proxy, as Fluentd process may not have direct network access to the ElasticSearch nodes.
よって Amazon Elasticsearch Service を使う場合は false にする必要がある.
reload_connections false
2. reload_on_failure
(Default : false)
リクエストの送信が失敗した場合に Elasticsearch クラスタのノードリストを更新するかどうかを設定する.故障した Elasticsearch ノードをノードリストからすぐに消すことができて有効な場合がある.デフォルトだと false になっている.
reload_connections
に書いた通り,Amazon Elasticsearch Service だとエンドポイントは固定されているため,デフォルトのまま false にしておく.
reload_on_failure false
3. resurrect_after
(Default : 60s)
"resurrect" って単語を知らなくて最初読めなかった.調べたら "復活させる" という意味だった.ようするに故障した Elasticsearch ノードに対するコネクションをコネクションプールに戻す秒数の設定で,デフォルトだと 60秒 になっている.
今回は reload_connections
と reload_on_failure
で更新を抑制しているため,デフォルトのままで良いのではないかと考えた.もし僕の認識が間違っていて Amazon Elasticsearch Service を使う場合も短く設定するべき!などあったら指摘頂ければと!
resurrect_after 60
最終的な設定
以上の調査結果を反映した最終的な設定は以下となる.
- デフォルト値を割愛して書く場合
reload_connections false
- デフォルト値も意図的に書く場合
reload_connections false reload_on_failure false resurrect_after 60
調べてわかったこと
公式の Elasticsearch と Amazon Elasticsearch Service では /_nodes
API のレスポンス形式が異なっている.Amazon Elasticsearch Service だと IP アドレスに関係する情報を返却していなく,再接続のロジックで必要になる IP アドレスを取得できず,エラーになるという感じ.
fluent-plugin-aws-elasticsearch-service 側の Issue にも同じ話が挙がっていて,大きく2種類のワークアラウンドが紹介されていた.1個は今回説明した reload_connections false
の件で,もう1個は cron で定期的に Fluentd を再起動すると書いてあった.
AWS 側の Discussion Forums にも今年1月に投稿されていたけど,レス0件で厳しい感じだった.うむ.
まとめ
導入検証中に発生して検知できれば良かったんだけど,何かしらの原因で Amazon Elasticsearch Service と接続が切れた場合にしか発生せず,難しいかなと思う.今のところ reload_connections false
で問題は出てなく正常に稼働しているけど,中長期的にまた何か発生する場合は追記しようと思う.
Fluentd に困ってるツイートをするとすぐにアドバイスを下さる @repeatedly さんに感謝です.いつもありがとうございます!
Fluentd で "Cannot get new connection from pool." ってエラー出てて何だ?と思ったら Amazon Elasticsearch Service 特有の問題っぽい...?調べねば / https://t.co/M3qZL8OHl2
— カカカカック (吉田慶章) (@kakakakakku) 2016年10月24日
関連記事
同じ事象に該当した記事があって参考にした.調べたらすぐこの記事が出てきて「また Amazon Elasticsearch Service の問題か...?」と気付けたから助かった.
関連して Amazon Elasticsearch Service に同梱されてる Kibana のバグを踏んだ話を前に書いた.
クラスタと Kibana のアクセス制限を別々にして管理できなくて困った話も前に書いた.