病みつきエンジニアブログ

機械学習、Python、Scala、JavaScript、などなど

Amazon S3 を使ったログ保存の仕方

多分、Linuxのコマンドに慣れてないと上手く出来ないと思うので、書いておきます。

Log rotation

これについては、あまり書くこともないです。logrotate で検索してみて下さい
まず、Log rotationは、ログファイルを、1週間なり、1ヶ月なりで、ローテーションさせるものです。
あるファイルaccess.logがあったとしたら、1週間でaccess.log を一旦削除、バックアップ(ないしは両方)し、access.log にはまた新たなログが書き込まれていきます。
なぜそうするかというと、access.log は無限に大きくなり、ファイル操作する上で障害になったりすることと、
AWSにおいては、EC2に巨大なログを保管するより、S3に巨大なログを保管するのが、運用上正しいからです(EC2は消える前提のデータで、値段的にもEC2は安い。EC2でなくとも、ただストレージに特化したS3のようなものに、大きなデータを横流しするのが良いと思う)。

と、いうことで適当なタイミングでlog をrotate させる設定をしてください。
1日1つぐらいがいいんじゃないかと思います。「EC2のインスタンスが一回落ちたとき、ログが消えても泣かないレベル」の頻度でないと泣いちゃうので。
ちなみに1000リクエストで1円とかのレベルなので、そのあたりも気にしないで良いと思います。

S3 を使う

細かいことははぶきますが、http://timkay.com/aws/にて公開されているスクリプトを使います(Amazonからもリンクされてます)。
そのサイトに書いてある設定(1〜5って書いてあるとこ)を完了させ、

s3mkdir BUCKET_NAME

を実行すると、s3上にbucketが一個生成されます。1サービスごとにBucketを作るのがいいのではないかと。

S3へのバックアップ

Log rotateするタイミングで、S3にバックアップを取りたいですね。そして、EC2上にはログデータを残さないようにしたいわけです。
捨てられるログを外部保管させるを参考にしてます。

logrotateされる前にあるスクリプトを実行するわけですが、以下のスクリプトを使います。save_to_s3.sh等、適当なファイル名で保存して下さい。
シェルスクリプト怖いです症候群なので、ループとか良い感じに書き換えてくれると嬉しいのですが…。

#!/bin/env bash

DIR_NAME=$1 # ex: rails, apache, nginx
LOG_PATH=$2 # ex: /path/to/log/file.log
LOG_NAME=`echo $2 | sed -e "s/\//\n/g" | tail -n 1` # ex: file.log

DATE=`date -d '9 hours' +%F` # ex: 2012-08-30
AMI_ID=`wget -q -O - http://169.254.169.254/latest/meta-data/ami-id` #ami-a1b2c3

s3put BUCKET_NAME/${DIR_NAME}/${LOG_NAME}/${DATE}-${AMI_ID}-${LOG_NAME} ${LOG_PATH}

BUCKET_NAMEは適当に書き換えて下さい。これで、上で作成したS3のBucket内に、
rails/production.log/2012-08-30-ami****-production.logというファイルが作成されます(例)。

さて、今度はlog rotationの設定ファイル(例:/etc/logrotate.d/httpd.conf)を開きます。たいていはroot権限で開いたほうが良いです。
その設定ファイルに、prerotateを以下のように書きます。

/var/log/httpd/*log { 
    (中略)
    postrotate 
        /path/to/save_to_s3.sh apache /var/log/httpd/access_log 
        /path/to/save_to_s3.sh apache /var/log/httpd/error_log 
    endscript 
} 

各ファイルパスなどは、適宜書き換えて下さい。