ApacheのアクセスログをAmazon Athenaを使って分析する
先日行われたre:Invent 2016で発表されたAmazon Athenaを利用して、Apache HTTP Serverのアクセスログを解析するまでの手順を紹介します。
Athenaで検索するためには、ログファイルをAmazon S3に配置しておく必要があります。LinuxからS3への転送にはfluentd(td-agent)を利用しました。
やりたいこと
Amazon Athenaを利用して、Apacheアクセスログ(combined log)に対しての検索クエリを実行できるようになりたい
前提環境
- LinuxはAmazon EC2のRedHat Enterprise Linux 7.3 AMIから起動
- EC2には、S3にPutObjectできる権限を持ったIAM Roleを紐付けておく
- Amazon Athenaはus-west-2(Oregon)リージョンで実行
手順概要
- OS側セットアップ
- Athena側セットアップ
- クエリ実行
OS側セットアップ
まずは、Linuxにtd-agentとApacheをインストールします。
$ sudo yum install httpd $ curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sh
インストールしたままの状態だと、 td-agent
ユーザがApacheのアクセスログを読めないので、ディレクトリのパーミッション変更と td-agent
ユーザのグループ追加を行います。
$ sudo usermod -a -G apache td-agent $ sudo chown apache:apache /var/log/httpd/ $ sudo chmod g+rx /var/log/httpd
td-agent.confは以下のとおりです。バケット名(s3_bucket
)やPrefix(path
)のパラメータはご自由に調整下さい。
<source> type tail path "/var/log/httpd/access_log" pos_file "/var/log/td-agent/access_log.pos" tag log.access format apache2 </source> <match log.access> type s3 s3_bucket <bucket_name> path "athena_apache/" s3_object_key_format %{path}%{time_slice}/access_%{index}.%{file_extension} buffer_path /var/log/td-agent/s3/access time_slice_format year=%Y/month=%m/day=%d/hour=%H/minute=%M time_slice_wait 10s utc buffer_chunk_limit 64m format json include_time_key true time_key log_time </match>
ポイントは time_slice_format
パラメータに、Amazon Athenaでパーティション定義をするためのラベリングをしている点です。Athenaにおけるパーティションの詳しい説明は以下ブログを参照下さい。
- S3のデータをAmazon Athenaを使って分析する | Amazon Web Services ブログ
- Amazon Athenaのパーティションを理解する #reinvent | Developers.IO
あとはtd-agentとApacheを起動すれば、OS側の設定は完了です。
$ sudo systemctl enable td-agent $ sudo systemctl start td-agent $ sudo systemctl enable httpd $ sudo systemctl start httpd
設定に成功していると、アクセスログがS3に以下のような形で出力されてきます。
{"host":"192.0.2.233","user":null,"method":"GET","path":"/index.html","code":200,"size":10,"referer":null,"agent":"Go-http-client/1.1","log_time":"2016-12-21T06:08:21Z"}
Athena側設定
AWS管理コンソールのAthena画面を開きます。前述のとおり、今回はオレゴンリージョンで試行しています。
Athenaでのテーブルはウィザードで作ることもできますが、今回はサンプルをベースにDDLを作成してそれを実行しました。以下のSQLをウィンドウに貼り付け、実行します。
まずはデータベースの作成です。
CREATE DATABASE IF NOT EXISTS access_table;
続いてテーブルを作成します。
CREATE EXTERNAL TABLE IF NOT EXISTS access_table.apache_access ( `host` string, `user` string, `log_time` string, `method` string, `path` string, `code` int, `size` int, `referer` string, `agent` string ) PARTITIONED BY ( year int, month int, day int, hour int, minute int ) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH serdeproperties ( 'paths'='host, user, log_time, method, path, code, size, referer, agent' ) LOCATION 's3://<bucket_name>/athena_apache/';
パーティションの定義に、先ほど td-agent.conf
の紹介の際に触れた time_slice_format
の値を入力しておきます。 LOCATION
の値も td-agent.conf
で設定した出力先と合うように設定しましょう。
テーブル作成が完了したら、データをロードします。以下のステートメントを実行して下さい。
MSCK REPAIR TABLE access_table.apache_access;
ここまで成功したら、完了です。
動作確認
実際にクエリを流して、データが入っているか確認してみましょう。
SELECT * from access_table.apache_access LIMIT 10;
実行すると、アクセスログが入っていることが確認できます。
もう少し複雑な集計クエリも流してみましょう。
SELECT host, count(*) FROM apache_access where log_time < '2016-12-21T06:14:05Z' and log_time > '2016-12-21T06:14:00Z' group by host;
ある一定期間内のリクエスト数をIPアドレス毎に表示するクエリです。
こちらも問題なく結果が出せました!今回はテスト用のサーバで実験したので結果が寂しいですが、本番稼働しているサーバのアクセスログを読ませれば、もっと興味深い値が出ると思います。
つまづいた場所
Athenaを触るのが初めてで、Hiveにも触れたことがなかったのでテーブル定義を作成するのに一番苦労しました。特にPARTITIONのところはつまづきました。今回は分単位でPARTITIONを作成しましたが、この粒度についてはもう少し検討が必要だと思います。それは個人的な今後の宿題です。
まとめ
多少のつまづきはありましたが、かなり簡単にApacheのアクセスログをAthenaで出力することができました!
S3に保存はしているが使われていないログ、結構あると思います。そういったログを活用するためのツールとしてAthenaを活用してみてはいかがでしょうか?