Edited at

CloudWatchLogsをLambdaで自動的にS3へアップロードする1つの仕掛け


あなたはCloudWatchで収集したログを放置していないだろうか?

image.png

データは活用しないと意味がない。


ログはS3に集約しよう。

そうしてこそ、分析に活かせたり、運用も一元化できたり、、

何より注目したいのは保管料金だ。

より安価なアーカイブサービスのGlacierの保管も視野に入る。

■CloudWatchの保管料金

0.033 USD/GB

■S3の保管料金

0.025 USD/GB

■Glacierの保管料金

0.005 USD/GB


賢いあなたは1GBにつき、約3円の無駄金を許せないはずだ。

【要件】

毎日0時にLambda関数が起動し、CloudWatchロググループ「cloudwatch-logs-messages」の

前日0:00〜23:59のログをS3のバケット「mys3bucketname/test_prifix」にアップロードする

では、設定していこう。

(というかAWSさん、そろそろこういう機能リリースしてくれないかなー)


S3の設定

保存先のS3バケットにバケットポリシーを付与する

以下を自分の環境に置き換える

- バケット名(以下の例ではmys3bucketnameとしている)

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "logs.ap-northeast-1.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::mys3bucketname"
},
{
"Effect": "Allow",
"Principal": {
"Service": "logs.ap-northeast-1.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::mys3bucketname/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}


Lambdaの作成

python3.6でLambda関数を一から作成する。

(ロールにはCloudWatchLogsの権限とS3の書き込み権限を付与して下さい)

image.png

Lambda関数を作成する。

以下を自分の環境に置き換える

  - Lambda関数名

  - 保存先S3バケット名

  - 取得するCloudWatchロググループ名

  - 保存先S3バケット名配下の任意のプリフィックス名(任意の名前で構わない)


lambda_function.py

import datetime

import time
import boto3

lambda_name = 'PutLogFromCWLtoS3Function' #Lambda関数名
log_group_name = '/aws/lambda/' + lambda_name
s3_bucket_name = 'mys3bucketname' #保存先S3バケット名
s3_prefix = lambda_name + '/%s' % (datetime.date.today() - datetime.timedelta(days = 1))

def get_from_timestamp():
today = datetime.date.today()
yesterday = datetime.datetime.combine(today - datetime.timedelta(days = 1), datetime.time(0, 0, 0))
timestamp = time.mktime(yesterday.timetuple())
return int(timestamp)

def get_to_timestamp(from_ts):
return from_ts + (60 * 60 * 24) - 1

def lambda_handler(event, context):
from_ts = get_from_timestamp()
to_ts = get_to_timestamp(from_ts)
print('Timestamp: from_ts %s, to_ts %s' % (from_ts, to_ts))

client = boto3.client('logs')
response = client.create_export_task(
logGroupName = 'cloudwatch-logs-messages', #取得するCloudWatchロググループ名
fromTime = from_ts * 1000,
to = to_ts * 1000,
destination = 'mys3bucketname', #保存先S3バケット名
destinationPrefix = 'test_prifix' #保存先S3バケット名配下の任意のサブフォルダ名(プリフィックス名)
)
return response


Lambda関数のテストは以下の形で「作成」を押下してOK

image.png

この関数をCloudWatchイベントに登録し、毎日0:00に起動するようにすればOK

(時刻はUTC基準なので気をつける。)

UTC + 9時間 = JST

0 15 * * ? *


CloudWatchイベントの登録方法は以下の記事を参照してみて欲しい。

朝7時にCloudWatchイベントからLambdaを介しAmazon Connectのコールスクリプトを発動し、

バーチャル彼女(女性の機会音声)に事前登録したスクリプトを読み上げさせるモーニングコールを

サーバーレスで設計したものだ。


AWSバーチャル彼女から毎朝モーニングコールで起こしてもらう1つのアーキテクト


おわりに

 ・バケット名、プリフィクス名をパラメーターで渡せば多数のロググループも対応可能と思われる。

 ・日次ではなく、1週間ごとにまとめてアップロードも可能。時間がかかりそうな際はLambdaの実行時間制約に気をつけて(デフォルト3秒となっているので、1分とかに延ばすこと)

ありがとうございました。

少しでもお役にたちましたら「いいね」をよろしくお願いします。