最近遅ればせながら光の戦士になった増田です。サボり癖がなかなか直りません。
さて、この度 Elasticsearch と Kibana の社内事例を作ることが出来ましたので、興奮のあまりお伝えします。
ずっと導入したかった
2014 年 3 月に中途で入社して以降、導入したかったものの 1 つが Elasticsearch でした。個人ではすでに導入しており、効果を実感できていたためです。
その前段である fluentd の社内初事例が 2015 年 4 月のこちらの記事。気がつけば社内の他のプロジェクトにも導入が進んでいました。
ElastiCacheをCloudWatch+fluentd+Zabbixで監視する | feedforce Engineers' blog
ところで私は先月から DF PLUS というサービスにフルコミットし、主にエラー管理やログ基盤などを整備しています。
エラー管理については、弊社ではもうお馴染みとなった Bugsnag で整備しました。
実はログ基盤は特に求められていませんでした。でも個人的には、絶対ログ基盤があるべきでサービスの可視化も絶対に必要という、根拠のない信念を持っていました。今回導入して効果を実感できているので、本当にうれしく思っています。
CloudWatch Logs に送っていた
これまで DF PLUS では、Rails の Production ログを fluentd 経由で CloudWatch Logs に送っていました。
CloudWatch Logs はお手軽なのですが、このような問題もあります。
- ログ自体は設定で保持する期限を指定できるが、グラフ表示期間は 2 週間
- 柔軟にグラフを作ることが出来ない
- AWS の UI がアレで見ようという気にならない
特にグラフ表示期間の 2 週間が致命的で、中長期的なメトリクスを取得することが出来ません。
AWS Elasticsearch を導入した
そういう状況もあり、虎視眈々と導入を狙っていました。去年の 10 月に AWS Elasticsearch がリリースされたときはうれしかったですね。
導入は公式ガイドに加え、クラスメソッドさんのこちらの記事を参考にしました。
AWS再入門 Amazon Elasticsearch Service編 | Developers.IO
機能は相当制限されています。例えば本来は elasticsearch.yml にいくつも設定を書けるのに、AWS では管理画面上から下記 2 つの設定を変更出来るだけです。elasticsearch.yml を直接編集することが出来ません。
他にもバージョンは 1.5.2 固定だったり(2016 年 6 月現在の最新は 2.3.3)、VPC 内に作ることが出来ない等の制限があります。
今回はこれらが導入の障壁にならなかったため、AWS の Elasticsearch service を採用しました。
本家の Elastic さんもホスティングサービスを出してますので、検討してみるのも良いかもしれません。
導入してよかったこと
- サービスの現在を可視化出来る
- サービスの現在のログを、サーバにログインすることなく見られる
- 複数サーバのログを横串で検索できる
- データを可視化出来る
そこまで大量のログではないとは言え、個人サーバよりもいろいろなデータを扱えるのは面白いですね。まだまだこれからですが、エンジニア以外の方々も巻き込んでいけたらなと思っています(チームのエンジニアには相当受けが良かったw)。
まとめ
- ログ基盤は絶対に必要
- データを可視化すると楽しい
- CloudWatch Logs は甘え
付録
アクセスポリシーの Tips
今回は Production サーバから fluent-plugin-aws-elasticsearch-service 経由で AWS Elasticsearch にログを送っています。
この時、AWS の Credentials 情報が必要です。Production サーバの IP アドレスをアクセスポリシーに加えても、意味がありませんのでご注意下さい。EC2 インスタンスの場合は、Elasticsearch のパーミッションを持った IAM Role を付与すると良いでしょう。
今回は社内から Kibana でアクセスするための、IP アドレス制限ポリシーのみ設定しました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:ap-northeast-1:012345678901:domain/domainname/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"IPアドレス1",
"IPアドレス2"
]
}
}
}
]
}