昨年10月にAmazon Elasticsearch Service(Amazon ES)がリリースされました。
今まではEC2インスタンスにElasticsearch をインストールして運用していましたが、AWS側でマネージドしてくれるということでとても便利そうだなと思い使ってみました。
動作環境は以下の通りです。
- Fluentd 0.10.58
- fluent-plugin-elasticsearch 0.9.0
- Amazon Elasticsearch Service r3.xlarge
構成としては、各WebサーバからApacheのアクセスログをFleuntdサーバに集約してAmazon ESへ転送するようにしていました。
しかし、FluentdからAmazon ESへ転送する際に途中でエラーが出てしまい、転送できなくなることがありました。
2015-12-14 07:00:55 +0900 [warn]: failed to flush the buffer. error_class="Elasticsearch::Transport::Transport::Error" error="Cannot get new connection from pool." plugin_id="object:3f883d4b52e4"
2015-12-14 07:00:55 +0900 [warn]: retry count exceededs limit.
2015-12-14 07:00:55 +0900 [warn]: /usr/local/rvm/gems/ruby-2.1.2/gems/elasticsearch-transport-1.0.12/lib/elasticsearch/transport/transport/base.rb:182:in `perform_request'
2015-12-14 07:00:55 +0900 [warn]: /usr/local/rvm/gems/ruby-2.1.2/gems/elasticsearch-transport-1.0.12/lib/elasticsearch/transport/transport/http/faraday.rb:20:in `perform_request'
2015-12-14 07:00:55 +0900 [warn]: /usr/local/rvm/gems/ruby-2.1.2/gems/elasticsearch-transport-1.0.12/lib/elasticsearch/transport/client.rb:119:in `perform_request'
2015-12-14 07:00:55 +0900 [warn]: /usr/local/rvm/gems/ruby-2.1.2/gems/elasticsearch-api-1.0.12/lib/elasticsearch/api/actions/bulk.rb:80:in `bulk'
2015-12-14 07:00:55 +0900 [warn]: /usr/local/rvm/gems/ruby-2.1.2/gems/fluent-plugin-elasticsearch-0.9.0/lib/fluent/plugin/out_elasticsearch.rb:170:in `send'
2015-12-14 07:00:55 +0900 [warn]: /usr/local/rvm/gems/ruby-2.1.2/gems/fluent-plugin-elasticsearch-0.9.0/lib/fluent/plugin/out_elasticsearch.rb:163:in `write'
2015-12-14 07:00:55 +0900 [warn]: /usr/local/rvm/gems/ruby-2.1.2/gems/fluentd-0.10.58/lib/fluent/buffer.rb:300:in `write_chunk'
2015-12-14 07:00:55 +0900 [warn]: /usr/local/rvm/gems/ruby-2.1.2/gems/fluentd-0.10.58/lib/fluent/buffer.rb:280:in `pop'
2015-12-14 07:00:55 +0900 [warn]: /usr/local/rvm/gems/ruby-2.1.2/gems/fluentd-0.10.58/lib/fluent/output.rb:315:in `try_flush'
2015-12-14 07:00:55 +0900 [warn]: /usr/local/rvm/gems/ruby-2.1.2/gems/fluentd-0.10.58/lib/fluent/output.rb:136:in `run'
Fluentd側の設定(一部抜粋)
index_name accesslog
type_name apache
type elasticsearch
include_tag_key true
tag_key @log_name
host xxxxxx.ap-northeast-1.es.amazonaws.com
port 443
scheme https
logstash_prefix apache_access
logstash_dateformat %Y.%m.%d-%H
logstash_format true
flush_interval 10s
最初からエラーが出るわけではなく途中でエラーが出てしまい、最終的にはqueue size exceeds limit
となってログを破棄されてしまいました。
Amazon ES側のログが見れないので何故発生したかはこの時点ではわかりません(CloudWatch Logsで見れるようにしてほしいです)。
エラー内容でググると以下のスレッドがヒットしました。
Elasitcsearch-ruby raises “Cannot get new connection from pool” error
何かしらの原因でElasticsearchへの接続がタイムアウトした後、再びコネクションプールに接続するにはある程度の時間(@resurrect_after
)まで待たなければならないようです。
@resurrect_after
のデフォルトが60秒なので接続するまでに60秒待たなければならず、頻繁にESへトラフィックを送る環境だと接続できるようになるまでにキューがどんどん詰まってしまい、queue size exceeds limit
となってしまったのが原因だということです(合っているかな・・・?)。
fluent-plugin-elasticsearch v1.2.0で @resurrect_after
を設定できるようになったのでアップデートして@resurrect_after
パラメータを短くすれば解決するはずです。
もう一点の問題があって、reload_connections
が デフォルト値(true
)になっていると、Amazon ESの場合のみ問題が起こるみたいです。
The problem with reoccurring exception:temporarily failed to flush the buffer. next_retry=2015-12-12 23:56:36 +0000 error_class="Elasticsearch::Transport::Transport::Error" error="Cannot get new connection from pool." plugin_id="output_to_elasticsearch"can be triggered also by plugin setting "reload_connections" (default set to true) and occurs only for Amazon Elasticsearch Service
reload_connections false
を設定すれば問題を回避できるみたいです。
対応
fluent-plugin-elasticsearch を 1.2.0以上にアップデートします。
最新版が 1.2.1 なのでそのバージョンでアップデートすることにします。
root> gem install fluent-plugin-elasticsearch -v 1.2.1 --no-ri --no-rdoc
gem install fluent-plugin-elasticsearch -v 1.2.1 --no-ri --no-rdoc
Fetching: fluent-plugin-elasticsearch-1.2.1.gem (100%)
Successfully installed fluent-plugin-elasticsearch-1.2.1
1 gem installed
Fluentdの設定を以下のように変更します。
index_name accesslog
type_name apache
type elasticsearch
include_tag_key true
tag_key @log_name
host xxxxxx.ap-northeast-1.es.amazonaws.com
port 443
scheme https
logstash_prefix apache_access
logstash_dateformat %Y.%m.%d-%H
logstash_format true
buffer_chunk_limit 100MB
flush_interval 10s
resurrect_after 5s
reload_connections false
- 追加された
resurrect_after
をデフォルト(60s)から5sに変更した - Amazon ESのみ起こる問題への対応として
reload_connections false
を入れた buffer_chunk_limit
をAmazon ES(r3.xlarge)の上限(100MB)まで上げた。flush_interval
が10sだが、バッファチャンクが作られてからフラッシュするまでに100MB以上のログが溜まると、Amazon ESへ送る際にエラーになるので念のため設定した- 先の設定では触れなかったが、Amazon ESはVPC外にあるので、HTTPSで通信した方が安全なので、
scheme
とport
を変更することでHTTPS対応した
Fluentdを再起動して完了です。
root> service fluentd restart
最後に
Amazon ESを本格的に使っている人が少ないのか、同じようにハマっている人があまりいなかったです。