CloudWatch Logs を "自動で" S3 にエクスポートする方法。その 2 、EventBridge Scheduler を使用する方法。

記事タイトルとURLをコピーする

こんにちは😺
技術課の山本です。

前回、Kinesis Data Firehose を使って、CloudWatch Logs を自動で S3 にエクスポートするブログを書きました。
Kinesis Data Firehose を経由して、S3 に保管する方法では、Kinesis Data Firehose の料金もかかってくるため、料金削減にはならなそうでした。

CloudWatch Logs を "自動で" S3 にエクスポートする方法。その 1 、Kinesis Data Firehose を使用する方法。 - サーバーワークスエンジニアブログ

2. EventBridge Scheduler を使用する方法

本記事では、CloudWatch Logs を EventBridge Scheduler を使用し、自動で S3 にエクスポートする方法を紹介します。
EventBridge Scheduler を使用し、定期的に S3 へのエクスポートを行います。
以下の記事で CloudWatch Logs のエクスポート機能を使って手動で実施していた内容を、EventBridge Scheduler を使用して実施します。
CloudWatch Logs を AWS マネジメントコンソールから手動で S3 バケットにエクスポートする - サーバーワークスエンジニアブログ
エクスポート機能 で使っているのは、CloudWatch の CreateExportTask という API で、EventBridge Scheduler から呼び出し可能です。

イメージ:

事前に S3 バケットのバケットポリシーを記述し、CloudWatch Logs のサービスから S3 バケットへの Put オブジェクトを許可する必要があります。 詳細は以下のドキュメントをご参照ください。
コンソールを使用してログデータを Amazon S3 にエクスポートする

東京リージョンでのバケットポリシー設定例:

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

EventBridge Scheduler の利用する IAM ポリシーと IAM ロールを作成する

IAM ポリシーの作成

CloudWatch の CreateExportTask API を利用するには、以下の権限が必要なため、IAM ポリシーを作成します。
必要な権限は以下です。

logs:CreateExportTask
logs:CancelExportTask
logs:DescribeExportTasks
logs:DescribeLogStreams
logs:DescribeLogGroups

参考: docs.aws.amazon.com

Lambda の test 関数が出力する CloudWatch Logs ロググループに出るログを、S3 にエクスポートする権限を付与した. IAM ポリシーを作成しました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "logs:CreateExportTask",
                "logs:DescribeLogStreams"
            ],
            "Resource": "arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws/lambda/test:*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "logs:DescribeExportTasks",
                "logs:DescribeLogGroups",
                "logs:CancelExportTask"
            ],
            "Resource": "*"
        }
    ]
}

IAM ロールの作成

EventBridge Scheduler に利用させる IAM ロール には、以下の信頼ポリシーを付与します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "scheduler.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

参考: docs.aws.amazon.com

IAM ポリシー を IAM ロールに紐付ける

上で作成した ExportTask を実行する権限のある IAM ポリシー を、上で作成した EventBridge Scheduler に利用させる IAM ロールに紐づけてました。

EventBridge Scheduler の設定

スケジュール

毎月 月末に実行するようにします。

日付に「L」 を入れると最終日に実行します。(豆知識)

The L wildcard in the Day-of-month or Day-of-week fields specifies the last day of the month or week.

参考: docs.aws.amazon.com

実行する API

CloudWatch Logs にある CreateExportTask を選択しました。

json は以下にしました。

Destination はバケット名
From は開始時間 (Unix時間をミリ秒で指定)
LogGroupName はロググループ名
To は終了時間(Unix時間をミリ秒で指定)

{
  "Destination": "test12345678901234567890123456789012",
  "From": 1703216663000,
  "LogGroupName": "/aws/lambda/test",
  "To": 4858890263000
}

開始時間、終了時間を指定できるものの、全部を取りたいので、ざっくり 2023 年 12 月 22 日〜2123 年 12 月 22 日としました。
ログ自体の保持期間は、CloudWatch Logs 側で制御しようと考えているため、こちらは広めの期間にしています。

参考:
docs.aws.amazon.com

IAM ロール

作成したものを付与しました。

実行結果

正常時

テストとして Cron を書き換えて、実行してみると、CloudTrail にログが出ていました。
イベント名:CreateExportTask

S3 バケットに対象のログが出ていました。

まず、exportedlogs/ というフォルダができていました。

下に、ランダム識別子のフォルダができていました。dcba339d-b21c-4639-9138-6d5f0cce1d3b/ 実行した際にできる親フォルダのようです。

中には、以下のブログと同じ形式で、ログが出ていました。

詳細は以下ブログを参照ください。
blog.serverworks.co.jp

正常時 (2 回目の実行)

試しに連続で 2 回実行すると、exportedlogs/ 配下に 2 回目の実行時のランダム識別子のフォルダ f6ba5abd-c67e-482b-9e6c-7e629d106582/ ができていました。 その中に同じログがまたエクスポートされていました。

従って、CloudWatch Logs のログ保持期間の設定と、EventBridge Scheduler での EventBridge Scheduler で のスケジュールを上手に設定しないと、ログが重複して S3 に保管されることになります。
例えば、 CloudWatch Logs の保持期間を 60 日に設定しておき、EventBridge Scheduler で 毎月の最終日に 実行すると、大体 1 ヶ月分くらいを重複して保持することになります。
S3 側で長期保管する想定なら、おそらく気にならない程度ではないかと思います。 CreateExporTask ではログも圧縮されますので、多少重複しても安心かなと思います。

エラー時

バケットポリシーを正しく設定していない場合は、CloudTrail に以下のエラーが出ていました。

"errorCode": "InvalidParameterException",
"errorMessage": "GetBucketAcl call on the given bucket failed. Please check if CloudWatch Logs has been granted permission to perform this operation.",

まとめ

EventBridge Scheduler を利用して自動で定期的に CloudWatch Logs にログをエクスポートする方法を紹介しました。
多少の重複は発生するものの、S3 にエクスポートされるログは自動で gz に圧縮となる点や、ノーコードで実装できる点から、CloudWatch Logs のログを S3 で長期保管する方法としては、良いのではと考えます。

余談

最近はランニングにハマっています。100 マイル走れるように頑張っています。
山中湖畔から夕暮れの富士山が見えました。

山本 哲也 (記事一覧)

カスタマーサクセス部のエンジニア(一応)

好きなサービス:ECS、ALB

趣味:トレラン、登山(たまに)