はじめに
皆さん、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のフロー
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状況です。
オプション
Usageにも少し書いてありますが、State Machine手動実行時に、以下の様にExportしたい日付を指定する事も出来ます。
※エラー時の手動リトライなんかで使って下さい。
{
"TargetDate": "2018-08-20"
}
↑の例だと、2019/8/20 0:00(JST) ~ 2018/8/21 0:00(JST)の範囲で、全てのロググループをエクスポートします。
最後に
Github、初めて使ったので色々ご指摘下さい!
使いこなしたい!
IssueやPullRequestもお待ちしてます!