ログ分析基盤の責務分離 ─ 配送と格納を分け、Crawlerを使わない

 公開 2026-07-13

CloudFront・ALB・VPC Flow Logsを調査に使える状態にするログ分析基盤の設計を解説する。ログを送る側(配送)と受ける側(格納・参照)を分離し、スキーマはGlue Crawlerの自動推定に頼らずTerraformで明示定義する。その設計判断の理由を中心に整理する。

設計判断ログ・分析

AWSの各サービスはログをS3に出力できるが、「S3にログがある」と「ログを調査に使える」の間には距離がある。 本稿では、CloudFront・ALB・VPC Flow LogsをAthenaでSQL検索できる状態に整える基盤の設計を、 配送と格納の責務分離、そしてGlue Crawlerを使わないという2つの設計判断を軸に解説する。

1. 全体像: 配送側と格納側を分ける

配送側のCloudFront標準ログ、ALBアクセスログ、VPCフローログがS3バケットへログを送り、格納側ではS3バケット(バケットポリシーとライフサイクル付き)、明示的なスキーマを持つGlueカタログ、Athenaワークグループを通じて調査者がSQLで検索する全体像の図

配送(delivery)と格納(stores)を別モジュールに分ける理由は、両者のライフサイクルが違うからである。

配送側
格納側
変更のきっかけ
監視したいリソースの増減(Distributionを増やした等)
保持期間・スキーマ・分析要件の変更
依存の向き
格納先バケットを参照する
配送元を「宣言」として受け取るだけ
ログ種別 × リソースの数だけ増える
基本1つ(用途別に少数)

格納側は「どの種類のログが、どのprefixに書き込まれるか」の宣言を受け取り、 それに応じたBucket Policyのstatementを動的生成する。配送元が増えても、格納側は宣言を1行足すだけで済む。

2. 格納側の設計: 1バケット = 1モジュール = 1ポリシー

S3のBucket Policyはバケットに1つしか置けない。複数のモジュールが同じバケットにポリシーを書こうとすると、 最後にapplyしたものが勝つ事故が起きる。これを構造的に防ぐため、 1つのモジュールインスタンスが1つのバケットとそのポリシー全体を所有する設計にしている。

同じバケットに複数種類のログを入れたい場合は、そのバケットを所有するモジュールに対して ログ種別を複数宣言する。ポリシーは1箇所で合成されるため、衝突が原理的に起きない。

3. 設計判断: なぜGlue Crawlerを使わないのか

Glue Crawlerはデータを走査してスキーマを自動推定してくれるが、この基盤では採用せず、 テーブル定義(カラム名・型・パーティション構造)をTerraformコードとして明示的に書いている。

観点
Crawler自動推定
明示スキーマ定義
スキーマの正確さ
データ次第で揺れる(型の誤推定が起きうる)
常に確定
対象ログとの相性
未知データには有効
AWSがフォーマットを公開しているログには推定が不要
実行コスト
Crawler実行の継続課金
ゼロ(定義のみ)
変更管理
コンソール/Crawler側に状態が生まれる
Terraformで完結。レビュー可能

判断の核心は2行目にある。VPC Flow LogsもCloudFrontログも、フォーマットはAWSの公式ドキュメントで公開されており、事前に確定している。 確定しているものを毎回推定させるのは、揺れとコストを持ち込むだけで利点がない。 Crawlerは「スキーマが本当に未知のデータ」のための道具であり、AWSサービスログはそれに該当しない。

4. partition projectionでパーティション管理をなくす

パーティション(日付等での物理分割)は、データレイクでスキャン範囲を絞る唯一の手段だが、 通常はパーティションが増えるたびにカタログへの登録が必要になる。ここでもCrawlerや定期ジョブが使われがちである。

この基盤ではAthenaのpartition projectionを使い、「パーティションはこの規則で存在する」という ルール自体をテーブル定義に書く。日付パーティションなら「この範囲の日付が、このprefix形式で存在する」と宣言するだけで、 Athenaがクエリ時にパーティションを計算する。

  • パーティション登録処理そのものが不要になる(ジョブもCrawlerもゼロ)
  • 「新しい日付のログがテーブルに映らない」という登録漏れ事故が原理的に消える

5. コスト設計: prefix別ライフサイクル

ログは種類によって価値の減衰速度が違う。全ログに一律の保持期間を設定するのではなく、 S3ライフサイクルをprefix別に定義する。

ログの性質
保持設計の例
生ログ(サンプリング用途)
短期で削除(数日〜1週間)
集計・加工済みデータ
低頻度アクセス層へ移行した上で数十日保持
監査要件のあるログ
長期保持 + アーカイブ層

加えてAthena Workgroupにはクエリごとのスキャン量上限を設定し、 「調査のつもりが全期間フルスキャン」というコスト事故を仕組みで防ぐ。

6. まとめ

設計判断
内容
配送と格納の分離
ライフサイクルの違うものを別モジュールに。配送元の増減が格納側に波及しない
1バケット1ポリシー所有
Bucket Policy上書き事故を構造的に排除
Crawler不使用
フォーマット公開済みのAWSログに推定は不要。スキーマはコードで確定させる
partition projection
パーティション登録という運用作業そのものを消す
prefix別ライフサイクル + スキャン上限
保持コストとクエリコストの両方に上限を設ける

ログ分析基盤の価値は「作った日」ではなく「障害調査で開いた日」に決まる。 その日に確実に動くために、推定・登録・定期ジョブといった動く部品を極力減らし、宣言だけで成立する構造にしておくことが、この設計の一貫した方針である。