AmazonのマネージドサービスとしてElasticsearch+Kiban4が使えるAmazon Elasticsearch Serviceが発表されました。
【AWS発表】Amazon Elasticsearch Service
以前fluentdを使ってELBのログをElasticsearchに取り込むことをやってみたのですが、その場合、fluentdを動かすサーバーが必要です。
ELBのアクセスログをfluentd(fluent-plugin-elb-access-log)+Elasticsearch+kibanaで可視化する
今であればLambdaがTokyoリージョンにあって使えるのでS3へのELBアクセスログのアップロードをイベントにして、Lambdaで処理してElasticsearchに登録することでサーバーレスで可視化ができそうだと思い、やってみたのでメモ。
Lambda用のロール作成
IAMでLambda用のS3へのアクセス及びElasticsearchへの登録ができるロールを予め作成しておきます。
Elasticsearchの作成
マネージメントコンソールなどからElasticsearchの新規ドメインを作成しておきます。
また、先ほど作成したロールからElasticsearchを操作できるようにします。
作成後、作成したドメインのエンドポイントをメモしておきてください。
Lambdaのコード作成
LambdaからElasticsearchへ登録するコードを書く必要があります。
と、思ったのですが、以下にLambdaによってS3からapacheのログをElasticsearchに登録するAWS公式のサンプルがありました。
amazon-elasticsearch-lambda-samples/src/s3_lambda_es.js
ログファイルのパース部分がapache/nginx用のものを使っているようなので、ELB用のパースに変えれば良さげです。
apache/nginxで利用されているものを参考にELBのアクセスログをパースするnpmを作ってみました。
今回はこれと既存のものを利用して少しのコード変更で実現します。もし、パース部分をもっと細かくする場合も同様にparserを作って登録する部分は既存のものを使ってやると簡単にできるかと思います。
まず、適当な所でAmazon公式のリポジトリからs3からElasticsearchへ登録するコードを取得します。
$git clone https://github.com/awslabs/amazon-elasticsearch-lambda-samples.git
次に今回利用する用のLambdaのプロジェクトを作成します。
# プロジェクト作成
$mkdir es-elb-log
$cd es-elb-log
$cp ../amazon-elasticsearch-lambda-samples/src/s3_lambda_es.js index.js
# 依存ライブラリのインストール。bylineはStreamを1行ごとに取り出せる
$npm install aws-sdk byline elb-log-parser
次に少しファイルを変更します。{your-es-endpoint}
は先ほど作成したElasticsearchのエンドポイントにしてください。
- var parse = require('clf-parser');
+ var parse = require('elb-log-parser');
- endpoint: 'my-search-endpoint.amazonaws.com',
+ endpoint: {your-es-endpoint},
- region: 'my-region',
+ region: 'ap-northeast-1',
- doctype: 'apache',
+ doctype: 'elb',
ZIPで圧縮します。
$zip -r es-elb-log.zip index.js node_modules
これでコードができたのであとはLambdaFunctionをマネジーメントコンソールなどから作成し、作成したZIPファイルをアップロードします。
Handlerにはindex.handlerを指定し、Roleには最初に作成したロールを指定してください。また、ログの量によると思いますが、Timeoutの時間は少し長めにしておくと良いかもしれません。
やってみる
準備ができたので以下を行い、Lambda経由でアクセスログが登録できるか確認します。
- EC2を起動し、Webサーバーを起動
- ELBを作成し、EC2にトラフィックが流れるようにする
- ELBのアクセスログを任意のS3バケットに登録するように設定。アクセスログの間隔を5分にすると結果が早く分かります。
- LambdaのEventSourcesでELBのアクセスログを配置するバケット、EventTypeとしてObject Created(All)を指定します。
あとは適当にELBにアクセスし、ログが出力されるのを待ちます。
設定が無事できていればS3へアクセスログがアップロードされたタイミングでLambdaが実行され、Elasticsearchへログ情報が登録されます。Elasticsearhをマネージメントコンソールで確認すると以下のようにレコードが登録されているのが確認できるかと思います。
CloudwatchLogsでLambdaのログも確認できます。
また、Elasticsearchのアクセスポリシーを変更し、利用している環境のIPからの接続を許可することでKinabaにアクセスし、以下のようにログ情報を見ることができます。
サーバー管理なしでここまでできるのはかなりいい感じです!