AWSの各サービスはログをS3に出力できるが、「S3にログがある」と「ログを調査に使える」の間には距離がある。 本稿では、CloudFront・ALB・VPC Flow LogsをAthenaでSQL検索できる状態に整える基盤の設計を、 配送と格納の責務分離、そしてGlue Crawlerを使わないという2つの設計判断を軸に解説する。
ページ構成
- 全体像: 配送側と格納側を分ける
- 格納側の設計: 1バケット = 1モジュール = 1ポリシー
- 設計判断: なぜGlue Crawlerを使わないのか
- partition projectionでパーティション管理をなくす
- コスト設計: prefix別ライフサイクル
- まとめ
1. 全体像: 配送側と格納側を分ける
配送(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別ライフサイクル + スキャン上限 | 保持コストとクエリコストの両方に上限を設ける |
ログ分析基盤の価値は「作った日」ではなく「障害調査で開いた日」に決まる。 その日に確実に動くために、推定・登録・定期ジョブといった動く部品を極力減らし、宣言だけで成立する構造にしておくことが、この設計の一貫した方針である。