AWSの各サービスはログをS3に出力できるが、「S3にログがある」と「ログを調査に使える」の間には距離がある。 本稿では、CloudFront・ALB・VPC Flow LogsをAthenaでSQL検索できる状態に整える基盤の設計を、 配送と格納の責務分離、そしてGlue Crawlerを使わないという2つの設計判断を軸に解説する。
1. 全体像: 配送側と格納側を分ける
配送(delivery)と格納(stores)を別モジュールに分ける理由は、両者のライフサイクルが違うからである。
格納側は「どの種類のログが、どのprefixに書き込まれるか」の宣言を受け取り、 それに応じたBucket Policyのstatementを動的生成する。配送元が増えても、格納側は宣言を1行足すだけで済む。
2. 格納側の設計: 1バケット = 1モジュール = 1ポリシー
S3のBucket Policyはバケットに1つしか置けない。複数のモジュールが同じバケットにポリシーを書こうとすると、 最後にapplyしたものが勝つ事故が起きる。これを構造的に防ぐため、 1つのモジュールインスタンスが1つのバケットとそのポリシー全体を所有する設計にしている。
同じバケットに複数種類のログを入れたい場合は、そのバケットを所有するモジュールに対して ログ種別を複数宣言する。ポリシーは1箇所で合成されるため、衝突が原理的に起きない。
3. 設計判断: なぜGlue Crawlerを使わないのか
Glue Crawlerはデータを走査してスキーマを自動推定してくれるが、この基盤では採用せず、 テーブル定義(カラム名・型・パーティション構造)をTerraformコードとして明示的に書いている。
判断の核心は2行目にある。VPC Flow LogsもCloudFrontログも、フォーマットはAWSの公式ドキュメントで公開されており、事前に確定している。 確定しているものを毎回推定させるのは、揺れとコストを持ち込むだけで利点がない。 Crawlerは「スキーマが本当に未知のデータ」のための道具であり、AWSサービスログはそれに該当しない。
4. partition projectionでパーティション管理をなくす
パーティション(日付等での物理分割)は、データレイクでスキャン範囲を絞る唯一の手段だが、 通常はパーティションが増えるたびにカタログへの登録が必要になる。ここでもCrawlerや定期ジョブが使われがちである。
この基盤ではAthenaのpartition projectionを使い、「パーティションはこの規則で存在する」という ルール自体をテーブル定義に書く。日付パーティションなら「この範囲の日付が、このprefix形式で存在する」と宣言するだけで、 Athenaがクエリ時にパーティションを計算する。
- パーティション登録処理そのものが不要になる(ジョブもCrawlerもゼロ)
- 「新しい日付のログがテーブルに映らない」という登録漏れ事故が原理的に消える
5. コスト設計: prefix別ライフサイクル
ログは種類によって価値の減衰速度が違う。全ログに一律の保持期間を設定するのではなく、 S3ライフサイクルをprefix別に定義する。
加えてAthena Workgroupにはクエリごとのスキャン量上限を設定し、 「調査のつもりが全期間フルスキャン」というコスト事故を仕組みで防ぐ。
6. まとめ
ログ分析基盤の価値は「作った日」ではなく「障害調査で開いた日」に決まる。 その日に確実に動くために、推定・登録・定期ジョブといった動く部品を極力減らし、宣言だけで成立する構造にしておくことが、この設計の一貫した方針である。
