S3の操作ログをLambdaを経由してElasticsearchに送る方法

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

モバイルアプリサービス部の五十嵐です。

突然ですが、S3の操作ログを取れるのはご存じでしょうか?

S3のバケットレベルの操作はCloudTrailでロギングできるようになりました(【新機能】Amazon S3がCloudTrailに対応しました | Developers.IO)が、オブジェクトレベルの操作はログファイルが出力されるだけで他のサービスと連携する機能がありません。そこで、オブジェクトの操作ログをLambdaを経由してElasticsearchに送信してみました。

Elasticsearch Serviceの設定

新規ドメインの作成

Elasticsearchは、AWSのマネージドサービスであるElasticsearch Serviceを使います。ドメイン設定やインスタンスサイズの設定などについては、[新機能]Amazon Elasticsearch Serviceがリリースされました! | Developers.IOを参照してください。

ドメインが作成できたらElasticsearchのEndpointを確認します(後で使います。)

スクリーンショット_2015-12-10_14_46_16

S3の設定

アクセスログの記録

S3にはオブジェクトの操作をログに出力する機能があります。ここではその機能を有効にし、ログ出力先のバケットトブレフィックスを指定します。

スクリーンショット_2015-12-08_18_00_37

これでログファイルが指定のバケットに出力されるようになりました。

Lambdaの設定

Lambda Functionを作成

S3からElasticsearchにデータを送信する方法とLambda Functionのサンプル1が以下に公開されています。

こちらから「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ファイルをアップロードします。

スクリーンショット_2015-12-10_15_10_45

Event sourceを設定

S3で設定したログファイルが出力されるバケットに、ログファイルが作成されたらそのイベントをトリガーとしてLambdaが起動するように設定します。

LambdaのAWSコンソールより、Event sourceを選択し、イベントを追加します。

スクリーンショット_2015-12-10_15_13_02

スクリーンショット_2015-12-08_20_09_35

動作確認

ログ出力するようにしたS3のバケットにファイルを1つアップロードします。

スクリーンショット_2015-12-10_15_25_19

しばらくすると、ログ出力先のバケットにログファイルが作成されます。

スクリーンショット_2015-12-10_15_33_36

ログファイルをトリガーとしてLambdaが起動したかどうかは、CloudWatchLogsから確認できます。

Elasticsearchにうまく送信されていればElasticsearchのコンソールのIndexに「s3-logs」が登録され、以下のようにmappingされているはずです。

スクリーンショット_2015-12-10_15_21_15

あとはAPIで検索操作するなり、Kibanaで可視化するなり、好きなように使うことができます。

注意

今回紹介したS3のログ出力機能は、AWSのドキュメント2によると「ベストエフォート型のサーバーログ配信」と書かれていますので、絶対にログが出力される保証はありません。サービスレベルに合わせてお使いください。


  1. このスクリプトには不具合(Issue #4)が報告されており、まだマージされていませんが次のPR(Pull Request #2)で修正されているようです。 
  2. サーバーアクセスのロギング - Amazon Simple Storage Service