LoginSignup
3
3

More than 3 years have passed since last update.

CloudWatch Logsを日次でS3にExportするStep Functions

Last updated at Posted at 2019-04-05

はじめに

皆さん、AWS上のログってどうしてますか?
EC2/RDS/Lambda/API Gateway 等いろんなサービスがログを吐きますよね。

しかし、CloudWatch Logsに保存し続けると結構なコストがかかるので、
S3に移して安く済ませたい方は多いはず!

サブスクリプションフィルタでKinesisとかに送っても良いのですが、
Kinesisにもお金がかかる・・・

S3へのエクスポートを使って、お安くアーカイブしたい!
と思って考え始めました。

仕様調査

CloudWatch Logsのエクスポートの仕様

一つのロググループがS3にエクスポート中だと、
それが完了するまで、次のエクスポートタスクは作成出来ません。

Lambda Functionの制約

CloudWatch Logsの仕様を見て、Lambda Function一つでloopしながら待つ事も考えたのですが、
Lambda FunctionのTimeoutの制限もあり、ロググループが増えたら、しんどくなる・・・

解決策

リアルタイムでデータが欲しいわけじゃないから、
Step FunctionでLambda Functionを数珠つなぎにして、のんびり動かせばいい!

実装

CloudFormationのテンプレート

CloudFormationの一枚のTemplateにまとめてます。(メンテナンス性悪いですが・・・)

Templateはせっかくなので、Githubに上げてみました
※初めてReadmeを英語で書いたので、拙い英語はお許しください・・・
https://github.com/Jump-Kishimoto/CloudWatchLogs-Export

Usageをもっとこう書いた方が良い!とか
どうやったらいいか分からねぇ!とかあれば、本記事へのコメント/Issue/PullRequestでいただければ喜びます!
一緒にブラッシュアップさせて下さい!

Step Functionのフロー

image.png

GetLogGroup

同一リージョンのCloudWatch Logsのロググループ名を取得します。
ロググループ名を取得する時、まだ次のロググループが有る場合は、NextTokenの値が返ってきますので、
それをState Machineに返却し覚えさせます。

2回目以降、NextTokenがLambdaに渡されれば、そのTokenを使い次のロググループ名を取得します。

CheckLogGroup

GetLogGroupの結果、ロググループを取得出来たかを判断し、ExportTaskの作成に移ります。

CreateExportTask

GetLogGroupで取得したロググループに対して、前日分のログをS3にExportするTaskを作成する。
Exportする対象の時間はLambda Function実行タイミングの前日の0:00(JST)~当日の0:00(JST)です。

例)
Lambda Functionが、2019/4/2 3:00(JST)に動いた場合
Export範囲:2019/4/1 0:00(JST) ~ 2019/4/2 0:00(JST) ←前日分をまるっと。
Lambda Functionが、2019/4/2 22:00(JST)に動いた場合
Export範囲:2019/4/1 0:00(JST) ~ 2019/4/2 0:00(JST) ←22:00に動こうが、範囲は変わらず。

WaitExportTask

ロググループのExportの完了を待つため、30秒待つ

GetExportTaskState

ロググループのExportのステータスを取得する。

CheckExportTaskState

Exportが完了している場合
→ GetLogGroupの処理へ。

Exportがまだ完了していない場合
→ WaitExportTaskの処理へ。

簡単な流れの説明

同一リージョンにあるロググループを昇順で一つずつ取得し、一つずつExport Taskを作成します。
しばらく待ってからチェックし、終わってなければまた待つ。終わっていれば次のロググループの取得へ。

というのをひたすら繰り返すだけです。
Step FunctionsのTimeOutが1年なので、State MachineがTimeoutする事はないでしょう。

S3にどう吐かれるの?

s3://{Bucket名}/CWLogs/{Region名}/{YYYY}/{MM}/{DD}/{ロググループ名}/{ExportTaksID}/{ログストリーム名}/00000.gz

というPathで吐かれます。

Lambda Functionのロググループなんかは"/"で区切られていますが、そのままExport先のPathとして使います。
S3マネジメントコンソール上では、サービス毎にフォルダが切られているように見えるので、見やすい気がしてます。

どう使う?

CloudWatch Eventで日次で動かしてもらうのがいいかと。
↓は3:00(JST)に日次でState Machineを動かしている時のExport状況です。
image.png

オプション

Usageにも少し書いてありますが、State Machine手動実行時に、以下の様にExportしたい日付を指定する事も出来ます。
※エラー時の手動リトライなんかで使って下さい。

{
  "TargetDate": "2018-08-20"
}

↑の例だと、2019/8/20 0:00(JST) ~ 2018/8/21 0:00(JST)の範囲で、全てのロググループをエクスポートします。

最後に

Github、初めて使ったので色々ご指摘下さい!
使いこなしたい!
IssueやPullRequestもお待ちしてます!

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3