Upgrade to Pro — share decks privately, control downloads, hide ads and more …

非機能要件対応でCloudWatch LogsのS3エクスポートを担当したら、最も簡単だと思っ...

Avatar for 三与木 輝 三与木 輝
September 15, 2026
110

非機能要件対応でCloudWatch LogsのS3エクスポートを担当したら、最も簡単だと思っていた方法が意外と大変だった話

少し前、非機能要件の対応でCloudWatch Logsの定期S3エクスポートを設計・構築、リリースまで行ったところ、様々な知見を得たので、それをご共有します。

Avatar for 三与木 輝

三与木 輝

September 15, 2026

Transcript

  1. 自己紹介 非機能要件対応でCloudWatch LogsのS3エクスポートを担当 したときに多くの知見を得たので、共有します。 都内IT企業勤務の社会人2年目エンジニア 業務領域 AWSを使用したインフラの設計・構築 たまにバックエンド開発 (Lambda等) 三与木

    輝 25卒(歴史学科卒) 新卒2年目インフラエンジニア 2 / 40 好きなAWSサービス DynamoDB 保有資格 2026 Japan AWS Jr. Champion 2026 Japan All AWS Certifications Engineer IPA ネットワークスペシャリスト IPA 情報処理安全確保支援士試験合格 LPIC-3、など
  2. 目次 4 / 40 01 対応した具体的な非機能要件について 02 CloudWatch LogsからS3にエクスポートするいくつかの選択肢 03

    どのような構成をとったか 04 結構色々と落とし穴があったこと 05 運用についても考える
  3. CloudWatch LogsからS3へエクスポートする方式は大きく分けて、 「リアルタイム」と「バッチ」の2種類あります。 Kinesis Data Streams Kinesis Data Streamsの後段処理は省略 ほぼリアルタイム

    取り込み後すぐに継続配送 CloudWatch Logs サブスクリプションフィルター Amazon Data Firehose バッチ Amazon S3 指定した期間をまとめてS3へ退避 期間を指定して定期退避 今回 8 / 40 保持期間365日に達するより前にアーカイブすることになるので、リアルタイム方式は過剰として バッチ方式を採用しました。 出典 CloudWatch Logs Subscriptions / S3 Export
  4. バッチ方式も代表的には、大きく分けて2つほどの構成が考えられます。 Step Functionsを使用して待機、状態確認、再試行をワークフローで表す方法 A EventBridge Scheduler Step Functions LambdaとSQSでゴリゴリ開発する方法 B

    EventBridge Scheduler Lambda SQS FIFO Lambda 最初にEventBridge Schedulerがあり、そこからStep FunctionsもしくはLambdaを使用して、 CloudWatch LogsをS3へエクスポートするAPIであるCreateExportTask APIを叩く構成となります。 ここでStepFunctionsやSQSを入れた通り、後述しますが基本的に状態を管理する構成が必要となります。 9 / 40 出典 AWS Step Functions / CloudWatch Logs
  5. 今回は、個人的な利用経験が豊富だと言う理由で、Lambda+ SQS FIFOの方式を採用しました。 A EventBridge Scheduler Step Functions EventBridge Scheduler

    Lambda B SQS FIFO Lambda 今回は個人的な経験回数からもこちらを採用しました →ただ、今思うとStepFunctionsを利用した方が丸かったかも、、 (隣の芝生は青い) 10 / 40
  6. 実装してみると、下記の通り落とし穴が5つありました 14 / 40 01 最初にいらないログを取得してしまう問題 02 Lambdaの実行時間15分制限問題と、Active ExportTaskが1件だけの問題 03

    CreateExportTask APIでは直接Glacier Instant Retrievalへ移動できない問題 04 S3ライフサイクルは128KB未満だと移動されない問題 05 保持期間をいつ設定するか問題
  7. 1つ目の落とし穴は「最初にいらないログを取得してしまう問題」です 1 2 3 4 5 そのまま渡すと describe_log_groups() 要件に含まれないログ(保持期間設定無のログなど) もキューへ入ります。

    ↓そこで、、 対象を絞ります retentionInDays(保持期間) == 365 対象だけをSQS FIFOへ渡します。 →今回の要件上、365日保持期間を設定したロググループのみを取得する構成にすることで、S3へのアーカイブの 対象を固定しました。これによって、保持期間を設定していない無関係なロググループが勝手にエクスポートされて コストが跳ね上がる現象を防止します。 16 / 40 出典 DescribeLogGroups
  8. 2つ目の落とし穴は「Lambdaの実行時間15分制限問題」と、 「アクティブなExportTaskはアカウント・リージョンごとに1件問題」です 1 15 1 2 3 4 5 Lambda

    分 皆さんご存知の通り、Lambdaの 1回の呼び出しは最大900秒です。 Active ExportTask 件 アカウント・リージョンごとの上限です。 (クォータ制限) ロググループを並列に処理できず、直列のみ実施可能となり、かつ一気に対象のロググ ループを投入するとLambdaの15分上限を超える可能性があります。 18 / 40 出典 Lambda Timeout / CloudWatch Logs Quotas
  9. 容量別で実際にエクスポート時間を測定した結果は、下記のようになりました。 ブレがあるのが個人的に怖いですね。 1 2 3 4 Lambdaの上限 15分 1GB 58.318秒

    3GB 2分24.975秒 5GB 3分25.245秒 10GB 9分26.079秒 20GB、初回 13分07.302秒 20GB、2回目 14分26.862秒 30GB、初回 12分50.980秒 30GB、2回目 10分10.051秒 0分 19 / 40 5分 10分 15分 5
  10. そこで、まずSQSを挟んで1ロググループにつき1回Lambdaを起動することで、 少しでも一回でエクスポートされる容量を減らしました。 1 2 3 4 5 SQSを挟んでLambdaを2つ利用 Lambda①はCloudWatch Logsから

    ロググループを取得しつつSQSに渡します。 Lambda②はSQSから1ロググループあたり1 回起動されるようにすることで、 エクスポートされる容量を減らす設計 にしました。 20 / 40 出典 Amazon SQS FIFO / Lambda
  11. 追加情報として、CreateExportTask APIでのCloudWatch Logsから S3へのエクスポートはLambda自身が行うわけでは無いというものがあります 1 2 3 4 5 Lambda

    Taskを起動する 次の呼び出しで状態を確認する CloudWatch Logs 非同期ExportTaskを続ける ログ本体をS3へ出力する →つまりTaskを1度起動すれば、AWSバックボーンネットワークでエクスポートが行われるので、 Lambdaが終了しても、CloudWatch Logs側のExportTaskは続きます。 21 / 40 出典 CreateExportTask API Reference
  12. なので、SQSで再試行を10回にして、実質150分の待機時間を持たせる構成を 採用することができました。これは個人的に助かりました。 1 2 3 今回の設定 約15分 × 10回 ≈

    150分 →MaxReceiveCountを10にすることで、エクスポート待機時間を最大150分まで 持たせました。この値は現場のログ量によって変わってくるものです。 22 / 40 出典 SQS DLQ 4 5
  13. 監視設定も大事で、10回で完了しなければDLQへ送り、SNSで 通知するようにもしています。 1 2 3 4 通知する条件 DLQにエクスポート依頼の メッセージが入ったとき 通知を受ける人

    開発者・運用担当者 通知後の対応 Taskの状態、対象期間、S3への 出力を確認し、再処理の要否を 判断する 23 / 40 出典 Amazon SQS DLQ / CloudWatch Alarm 5
  14. 3つ目の落とし穴は「CreateExportTask APIでは、 直接Glacier Instant Retrievalへ移動できない問題」です 1 2 3 4 5

    CreateExportTask request 指定可能 destination (出力先S3バケット) 指定可能 destinationPrefix (保存先のプレフィックス) 指定項目なし ストレージクラス (例としてGlacier Instant Retrieval) こちらの通り、 ストレージクラスを直接指定する項目がありません。 →まずS3へ出力し、そのあとでS3ライフサイクルを使って移行することでコスト削減します。 25 / 40 出典 CreateExportTask / Amazon S3 Lifecycle
  15. 4つ目の落とし穴は「S3ライフサイクルでは128KB未満が移動されない問題」です 1 2 3 4 5 128KB未満は、既定では ライフサイクル移行の対象外 →サイズフィルターを指定すると、 移行対象に含めること自体は可能ですが、、

    ↓ S3 Glacier Instant Retrievalの ストレージ料金は、1ファイル最低128KB 実サイズ 料金計算上のサイズ 10KB 128KB 実サイズは変わらないのに、料金上は128KBで計算され てしまい、加えて移行リクエスト料金も発生します。 26 / 40 →この通り、S3ライフサイクルで移行されない小さいファイルは、無理やり移行すると割高に なる場合があります。そもそもS3 GIRへの移行はコスト削減目的なので、本末転倒になり得ま す。 出典 Amazon S3 Lifecycle / Glacier Storage Classes
  16. 5つ目の落とし穴は「保持期間365日をいつ設定するか問題」です 1 2 3 4 5 【変更前】無期限保持 700日前 365日前 今日

    700日分のログを保持 保持期間を365日に変更 【変更後】365日の保持期間設定 700日前 古い335日分が削除対象 365日前 今日 直近365日分を保持 保持期間は、ログの発生日時を基準に判定されます。 →システムの運用が365日より前からあり、ログが存在する場合、365日以前のログは 問答無用で消えてしまいます。これは場合によっては大問題になり得る危ない落とし穴です。 28 / 40 出典 CloudWatch Logs Retention
  17. そこで先に初回退避を終え、そのあとで保持期間を365日に 設定することでこの落とし穴を回避しました。 時間帯 1日目・リリース日 2日目・完了確認日 1 2 3 4 3日目以降

    360日前を日時退避開始(自動) 毎日0時 日中 保持期間は 無期限のまま 業後・夜間 デプロイ+ 初回退避(手動)を実施 (稼働開始〜360日前) TaskとS3出力を確認 完了後、保持期間を365日に変 更 →これで日次退避が自動で行 われるようになる 日次処理の 結果を確認 →初回退避で稼働開始から360日前までを退避させるために、Lambda② の中に特定のイベントを手動で渡すとエクスポートされるプログラムを 組み込みました 29 / 40 出典 CloudWatch Logs Retention 5
  18. ログの保存形式に合わせて、 Athenaのテーブルを定義しました S3上の ログファイル 既存のテーブル作成画面(DDL部分) 外部テーブル log_line 検索用ビュー 日時・メッセージなどの列 外部テーブル

    S3上のログを、 テーブルとして参照する log_group・dt ロググループと日付で 調査範囲を限定する 検索用の列 ログ形式に合わせて 日時やメッセージを取り出す 34 / 40 出典 Amazon Athena CREATE TABLE
  19. Logs Insight側に置いてあるいつもの調査クエリも、 Athenaでも使えるように書き換える必要があります。 例)エラーを新しい順に100件確認する。 CloudWatch Logs Insights QL fields @timestamp,

    @message | filter @message like /ERROR/ | sort @timestamp desc | limit 100 Athena SQL SELECT event_time, message FROM archived_cloudwatch_logs_view WHERE message LIKE '%ERROR%' ORDER BY event_time DESC LIMIT 100; →結構たくさんの調査クエリがある場合は、それぞれを書き換える作 業が発生します。 36 / 40 出典 CloudWatch Logs Insights QL / Athena SQL
  20. 比較用に、ExportTaskの完了待ちを、Step Functionsでも作ってみまし た。正直こっちの方が見やすく、かつシンプルに感じます。 比較用の試作 Wait 完了確認までの 待機を表します。 Choice 実行中・完了・失敗で 処理を分けます。

    実行すれば、実行履歴で 経由した状態を確認できます。 SQSで行っていた再確認の流れを、Step Functionsの状態遷移として表した試作です。 割と不慣れだったものの、数時間で作れてしまいました。 39 / 40 出典 AWS Step Functions