S3の操作ログをLambdaを経由してElasticsearchに送る方法
モバイルアプリサービス部の五十嵐です。
突然ですが、S3の操作ログを取れるのはご存じでしょうか?
S3のバケットレベルの操作はCloudTrailでロギングできるようになりました(【新機能】Amazon S3がCloudTrailに対応しました | Developers.IO)が、オブジェクトレベルの操作はログファイルが出力されるだけで他のサービスと連携する機能がありません。そこで、オブジェクトの操作ログをLambdaを経由してElasticsearchに送信してみました。
Elasticsearch Serviceの設定
新規ドメインの作成
Elasticsearchは、AWSのマネージドサービスであるElasticsearch Serviceを使います。ドメイン設定やインスタンスサイズの設定などについては、[新機能]Amazon Elasticsearch Serviceがリリースされました! | Developers.IOを参照してください。
ドメインが作成できたらElasticsearchのEndpointを確認します(後で使います。)
S3の設定
アクセスログの記録
S3にはオブジェクトの操作をログに出力する機能があります。ここではその機能を有効にし、ログ出力先のバケットトブレフィックスを指定します。
これでログファイルが指定のバケットに出力されるようになりました。
Lambdaの設定
Lambda Functionを作成
S3からElasticsearchにデータを送信する方法とLambda Functionのサンプル1が以下に公開されています。
- Streaming Data to Amazon ES - Amazon Elasticsearch Service
- awslabs/amazon-elasticsearch-lambda-samples
こちらから「src/s3_lambda_es.js」をダウンロードし、ファイル名を「index.js」に変更します。
このサンプルは、apacheのログファイルをJSONに変換してElasticsearchに投入するようになっていますので、S3のログファイルをJSONに変換するように修正します。
-var parse = require('clf-parser'); // Apache Common Log Format +var s3Logs = require('s3-logs');
- var logRecord = parse(line.toString()); + var logRecord = s3Logs.parse(line.toString())[0];
S3のログをJSONに変換するには、npmのs3-logsを使いました。
また、Endpointやindexなどのドメイン設定を修正します。
var esDomain = { endpoint: 'ここにElasticsearchのEndpointを設定', region: 'ap-northeast-1', index: 's3-logs', doctype: 's3' };
必要なnpmをインストールします。
$ npm install byline s3-logs path stream
Lambda Functionをデプロイ
index.jsに実行権限を付与し、index.jsとnode_modulesフォルダをzipファイルにします。
$ chmod 777 index.js $ zip -r eslambda.zip *
LambdaのAWSコンソールより、zipファイルをアップロードします。
Event sourceを設定
S3で設定したログファイルが出力されるバケットに、ログファイルが作成されたらそのイベントをトリガーとしてLambdaが起動するように設定します。
LambdaのAWSコンソールより、Event sourceを選択し、イベントを追加します。
動作確認
ログ出力するようにしたS3のバケットにファイルを1つアップロードします。
しばらくすると、ログ出力先のバケットにログファイルが作成されます。
ログファイルをトリガーとしてLambdaが起動したかどうかは、CloudWatchLogsから確認できます。
Elasticsearchにうまく送信されていればElasticsearchのコンソールのIndexに「s3-logs」が登録され、以下のようにmappingされているはずです。
あとはAPIで検索操作するなり、Kibanaで可視化するなり、好きなように使うことができます。
注意
今回紹介したS3のログ出力機能は、AWSのドキュメント2によると「ベストエフォート型のサーバーログ配信」と書かれていますので、絶対にログが出力される保証はありません。サービスレベルに合わせてお使いください。
- このスクリプトには不具合(Issue #4)が報告されており、まだマージされていませんが次のPR(Pull Request #2)で修正されているようです。 ↩
- サーバーアクセスのロギング - Amazon Simple Storage Service ↩