#初心者が送る!ElasticSearch格闘日記
ElasticSearch導入2回目の初心者ですが
日々、ElasticSearchと戦いながら楽しく運用をしています。
##導入してわかったメリット
・可視化することで異変に気づく(気づいてしまうことも。。)
・時系列にすることで思わぬ気づきがある
・ログ調査のスピード早くなる
##日々の格闘
新規システム構築時にあわせ、
可視化目的で運用(監視)ツールの一環としての構築。
導入の際、投入するログ量が多いと分かっていたのですが、
負荷と戦う毎日を繰り返しています!!
##稼働環境
・ElasticSearch 1.4.4
・kibana 4
・AWS t2.large×8台 EBS:250G
・ES_HEAP_SIZE:4096m
・3000~6000docs/秒
・データサイズ:600GB程度
・index数:500個位
##定期的なindexのお掃除
Cronで定期的にindexの削除を実施しており
以下のようなスクリプトを実行
TGTDATE=$1
URL="http://xxxx:9200"
curl -s ${URL}/_cat/indices 2>/dev/null | awk -v TGTDATE=$TGTDATE '$3 ~ TGTDATE { print $3 }' | \
while read INDEX
do
curl -s -XDELETE -w'\n' ${URL}/${INDEX} | jq .acknowledged
done
考慮点として、直近のデータ以外は必要ではないため、
indexの保持期間は2日保存と自分ルールを決めてます。
##インデックス命名規則
Fluentdでfluent-plugin-elasticsearchからデータ投入。
2つのパターンで分けており
- Webサーバなどのデータ量が大きいもの
- OSのログなど負荷が低いもの
でインデックス命名規則を分けています。
1時間単位のネーミング
<template>
include_tag_key true
tag_key @log_name
host xxxxxx
port 9200
logstash_format true
logstash_prefix ${tag_parts[0]}
logstash_dateformat %Y.%m.%d-%H
buffer_chunk_limit 16m
buffer_queue_limit 256
buffer_type file
buffer_path /var/log/td-agent/buffer1/elastic_${tag}
flush_at_shutdown true
flush_interval 1s
try_flush_interval 2s
queued_chunk_flush_interval 1s
num_threads 4
retry_limit 2
retry_wait 2
</template>
日単位のindex
<template>
include_tag_key true
tag_key @log_name
host xxxxx
port 9200
logstash_format true
logstash_prefix ${tag_parts[1]}
logstash_dateformat %Y.%m.%d
buffer_chunk_limit 8m
buffer_queue_limit 128
buffer_type file
buffer_path /var/log/td-agent/buffer2/elastic_${tag}
flush_at_shutdown true
flush_interval 1s
try_flush_interval 2s
queued_chunk_flush_interval 1s
num_threads 4
retry_limit 2
retry_wait 2
</template>
ただ、1時間単位でindexを作ること数が多くなり運用しずらいです。
#送り先であるFluentdのチューニング
Fluentdを使ってElasticSearchのですが、
NGINXなどのログは大量に送られてくるので
データ送信を設定値で細かくしています
大きい値8と小さい値0.01くらいまで
パフォーマンスを取って試しましたが、この環境では
flush_interval 1s
try_flush_interval 2s
queued_chunk_flush_interval 1s
が良かった結果でした
#負荷軽減のためのIndexTemplate
fieldのtypeで考慮している点
なるべく負荷を下げようとした結果、
・集計しないとき
"index": "no",
"doc_values": true,
"type": "string"
・本当にkibanaとかで集計するとき
"index": "not_analyzed",
"doc_values": true,
"type": "string"
を設定しています。
基本的には、"index": "no"を設定しておき
どうしてもKibanにグラフ化したいときには
"index": "noを設定しないような運用をしています。
あわせて、refresh_intervalに30秒を指定して付加を軽減しています。
"index.refresh_interval": "30s",
"index.number_of_replicas": "1
#データの長期保存のための再集計
2日でデータを削除するとしても、長期保存したいデータもあり
その場合は、保存したいデータを集計して抜き出し、再度ElasticSearchに入れ込んで
工夫しています。
再投入の際には、複数値で割り算など求めて加工したり
他にも、zabbixとかAeroSpikeのデータなどAPIで取って
ElasticSearchに含めて集約しています。
#設定値
node名にホスト名を入れたいので
node.name: ${HOSTNAME}
を指定して、
export HOSTNAME=ES-SERVER
とホスト名で認識されるようにしています。
リバランシンシングで均等にするため
cluster.routing.allocation.cluster_concurrent_rebalance
や
リカバリー時に負荷を少なくするため
cluster.routing.allocation.node_concurrent_recoveries: 3
indices.recovery.max_bytes_per_sec: 50mb
indices.recovery.concurrent_streams: 5
をいれています。
##EC2のインスタンス入れ替え
導入当初はc4.large×8台を使っていたが
コストの兼ね合いもあり、t2.largeへ移行しました。
移行方法はこちらを参考にしました
https://www.elastic.co/guide/en/elasticsearch/guide/current/_rolling_restarts.html
#Kibanaのデータバックアップ
Kibana再設定は手間がかかるのでデータバックは重要です!
elasticsearch-cloud-awsを使っているので、S3に時々保存しています。
https://github.com/elastic/elasticsearch-cloud-aws#s3-repository
https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html
#障害対応時
残念ながら、負荷に負けてしまうことが時々あります。
そんなときは、復旧ができなくなるため、断腸の思いでindex削除しています。
curl -XDELETE 0:9200/*2015*
でindex削除しています。
ですので、長期保存用のindexなど必要なデータはindex名を変えておきます。
あとは、
unassigned_shardsが無いかCronで定期チェックしていたり、
unassigned_shardsがあった場合は
curl -s -m 5 -XPOST '0:9200/_cluster/reroute' -d '{
"commands" : [ {
"allocate" : {
"index" : "'$index名'",
"shard" : '$shard',
"node" : "'$割当先'",
"allow_primary" : true
}
}
]
}' | jq -r .acknowledged
で配置しているようにしています。
##最後に
AZ間を跨いで稼動させているので通信量が気になって、ノード間の通信量を調べたてみたかったり
スプリットブレインがおきたときの対処を冷静にしたり
EC2のインスタンスストアを使えばよかったと思ったり
これからも日々楽しく運用してみます。