FargateでCloudWatch Logsからログをエクスポートするアイデア
fargateからAWS CLIでcreate-export-task APIを叩き、CloudWatch Logsからログをエクスポートする方法を考えてみました。
モチベーション
CloudWatch Logsに格納されたログを取り出して、別のシステムに移したいような要件があると思います。
例えば、複数システムを運用している環境で、監査用システムにログを集約したいような時などです。
CloudWatch Logsからログを取り出す方法はいくつかあります。
例えば、
- サブスクリプションフィルタ
- エクスポート機能
- fluentdなどの3rd party製品
ただ、どの方法も意外と面倒臭く、こういう要件に当たっている方は結構苦労している印象があります。
具体的には、
- ロググループあたり1個までしか使えない(2020/5現在) ため、既に埋まっていると使えない。しかもデータ部分がbase64&gzip圧縮されるので、デコードしないといけない。
- エクスポート後、続けて処理をするようなワークフローを作るのに、Step Functionsなどでテクいことをしないといけない。わざわざEC2を立てて、lambdaで起動/停止するのもなんか違う気がする。
- AWS公式の読み出しpluginがない。
バッチ処理でいいので、なんとか簡単にできないかと思っていたところ、Fargateが思い当たり、検証してみることにしました。
構成
こんな感じのことを考えています。
Docker Imageを作る
エクスポートタスクを作る用のDocker Imageを作ります。
以下の公式ドキュメントを参考に、fargateからcreate-export-task APIをCLIから叩く作戦です。
docs.aws.amazon.com
AWS CLIを使う分には、公式でイメージ(AWS CLI v2 Docker image | AWS Developer Blog)を公開してくれていますが、個人的にpythonのイメージで自作した方がやりやすかったので、そちらで行きます。
そうすると、以下のようなDockerfileになります。
FROM python:3.7-alpine RUN pip3 install awscli CMD aws logs create-export-task --task-name "my-log-group-09-10-2015" --log-group-name "my-log-group" --from 1441490400000 --to 1441495000000 --destination "my-exported-logs" --destination-prefix "export-task-output"
なお、create-export-task APIの仕様は、下記のドキュメントにあります。注意点としては、エクスポートするログのタイムスタンプを、ミリ秒単位のUNIXタイムで書くのが厄介です。
docs.aws.amazon.com
今回は時間をdocker fileに決め打ちで書いていますが、dateコマンドで動的に取得して取れると良いです。なお、ミリ秒単位のUNIXタイムは下記で取得できます。
date +%s%3
fargateにはIAMロールで権限を設定する
create-export-task APIを実行するには、実行側に、CloudWatch LogsとS3のフルアクセスが必要なので、タスクロールとして使用するIAMロールにつけておきます。
後はpushしたDocker imageをfargateにpullしてタスクとして実行するだけです。
fargateを使うのが初めての方は、初心者向けのサイト等を参考に設定してみてください。
dev.classmethod.jp
docker imageをビルドして、ECRにpushしておくのも忘れずに。
スケジューリング
タスクはECSの機能で一貫して、cron方式でスケジューリングできるようです。この機能でスケジュールしておけば、簡単にバッチ処理化できそうです。
docs.aws.amazon.com
qiita.com
感想
この方法であれば、指定の時間になればFargateが勝手に起きてくれてエクスポートして落ちてくれるので、めっちゃ楽ですし、安く済みます。
Lambdaを駆使して頑張ったり、事故ったりする必要もなさげです。
EC2を立てる程ではないけど、Lambdaのカバー範囲より少し長めの時間がかかる処理って、とても大変だなぁと痛感しました。Fargateがあってくれて本当によかったです。