Amazon Athena コストモニタリング設計書
概要
Amazon Athenaを使用したログ分析におけるコスト高騰リスクを防止するための包括的な監視・制御システムの設計書です。単一クエリの暴走防止から、複数クエリの累積コスト監視まで、多段階防御アプローチでコストガバナンスを実現します。
背景と課題
現状分析
FastDoctorでは、今後各種ログ分析にAthenaを活用する予定ですが、本格運用開始前にコスト管理体制を整備する必要があります。
ログ分析の計画
- 用途: アプリケーションログ、アクセスログ、監査ログの分析
- 想定スキャン量: 1TB/日(※あくまで仮の想定値。実際の使用量は運用開始後に判明)
- 想定月次コスト: $150/月(1TB/日 × $5/TB × 30日)
- 実行頻度: 過去データの調査が必要になった際にアドホッククエリを実行
想定されるリスク
本格運用開始前に、以下のリスクを想定し、予防的な対策を講じます:
単一クエリの暴走リスク
- リスク:
SELECT * FROM huge_tableなどの最適化されていないクエリ - 影響: 1クエリで数十GB〜数百GBスキャンの可能性
- 潜在的損失: 意図しない高額課金($50〜$500/クエリ)
- リスク:
累積コストの可視化不足
- リスク: 複数の小規模クエリが累積すると大きなコストに
- 影響: 日次・月次予算の超過
- 潜在的損失: 月末に予算オーバーが判明(手遅れ)
リアルタイム監視の欠如
- リスク: 監視がない状態でクエリを実行
- 影響: 異常なコスト発生を検知できない
- 潜在的損失: 数日〜数週間の検知遅延で$100〜$1,000の損失
アラート基盤の未整備
- リスク: コスト異常時の通知機能なし
- 影響: 問題の早期発見・対処が困難
- 潜在的損失: コスト高騰の長期化
本設計の目的
上記リスクを未然に防止するため、以下を実現します:
- 単一クエリ暴走防止: Athena Workgroup Controlsによる1クエリあたりのスキャン上限設定
- 複数クエリ累積監視: CloudWatch Alarmによる一定期間内の累積スキャン量監視
- 即時アラート通知: AWS Chatbot + Slack統合による迅速な問題共有
- 長期コスト分析: Cost Explorerベースの週次ワークフローによる自動分析・検知
検証で判明した課題
Datadog監視の技術的課題
当初はDatadog AWS統合による監視を計画していましたが、実装・検証の結果、以下の技術的課題により採用を見送りました。
課題1: スパースメトリクスの補間問題
- 問題: Athenaの
ProcessedBytesメトリクスは、クエリ実行時のみデータポイントが送信されるスパースメトリクス(Event-driven metrics) - 影響: Datadogはスパースメトリクスの欠損データポイントを「前回の値」で補間するため、ALERT状態が自動的にリカバリしない
- 検証結果: アラート発生後、クエリが実行されない期間でもALERT状態が継続し、自動リカバリが実現できなかった
課題2: 補間関数による改善の失敗 複数の補間関数を試行しましたが、いずれも自動リカバリを実現できませんでした:
| 試行した関数 | 期待した動作 | 実際の結果 | 判定 |
|---|---|---|---|
.as_count() | カウント型として扱い補間を抑制 | ALERT状態が継続 | ❌ 失敗 |
.fill(zero) | 欠損データを0で埋める | ALERT状態が継続 | ❌ 失敗 |
.fill(null) | 欠損データをnullとして扱う | ALERT状態が継続 | ❌ 失敗 |
default_zero() | デフォルト値を0に設定 | ALERT状態が継続 | ❌ 失敗 |
課題3: Datadogのアーキテクチャ制約
- Datadogは独自のメトリクスストレージを使用し、CloudWatchメトリクスをポーリングして取得
- スパースメトリクスの補間ロジックは、Datadog側で固定されており、ユーザー側で制御不可
- この設計により、イベント駆動型のメトリクスに対する自動リカバリが技術的に困難
CloudWatch Alarm採用の理由
上記課題を解決するため、CloudWatch Alarm + AWS Chatbot方式を採用しました。
CloudWatch Alarmの利点:
スパースメトリクス対応設定
treat_missing_data = "notBreaching": 欠損データを「閾値違反なし」として扱う- この設定により、クエリが実行されない期間は自動的にOK状態にリカバリ
ネイティブ統合
- AthenaメトリクスはCloudWatch内で完結
- 外部システムへのメトリクス転送・補間処理が不要
- データポイントの遅延や欠損リスクを最小化
AWS Chatbotによるリアルタイム通知
- SNS Topic経由でSlackへ即時通知
- アラーム発生とリカバリの両方を通知
- 既存のAWS Health Event通知基盤を活用
検証結果:
- ✅ アラート発生: 閾値超過時に即座にSlack通知
- ✅ 自動リカバリ: クエリ停止後、次の評価期間で自動的にOK状態に復帰
- ✅ 手動テスト:
aws cloudwatch set-alarm-stateによる動作確認完了 - ✅ 実データテスト: 実際のクエリ実行(292バイトスキャン)による通知確認完了
要件定義
機能要件
- FR-1: 単一クエリのスキャン量を物理的に制限(Workgroup Controls)
- FR-2: 短時間(10分)での累積スキャン量を監視(CloudWatch Alarm)
- FR-3: 段階的なアラート通知(Warning/Critical)
- FR-4: Slackへの即時通知(AWS Chatbot経由)
- FR-5: スパースメトリクスに対する自動リカバリ機能
非機能要件
- NFR-1: 実装負荷が低い(1日以内で構築可能)
- NFR-2: 管理が簡単(運用負荷最小)
- NFR-3: 監視システム自体のコストが低い(CloudWatch無料枠内)
- NFR-4: 検知遅延が短い(評価期間: 10分、カスタマイズ可能)
- NFR-5: 通知が確実(AWS Chatbot + Slack統合)
- NFR-6: スパースメトリクスに対応した自動リカバリ
アーキテクチャ設計
全体アーキテクチャ
通知先Slackチャンネル:
- infra-dev / staging環境:
#squad-sre-noti-saas-status-dev - production環境:
#squad-sre-noti-saas-status
監視の仕組み
Layer 1: 単一クエリ暴走防止(Athena Workgroup Controls)
目的: 1クエリあたりのスキャン上限を設定し、コスト高騰を物理的に防止
特徴:
- ✅ 検知速度: 瞬時(<1秒)
- ✅ コスト: $0
- ✅ 確実性: 100%(物理的にブロック)
- ✅ 設定項目:
bytes_scanned_cutoff_per_query = 10GB
Layer 2: スキャン量監視(CloudWatch Alarm + AWS Chatbot)
目的: 一定期間内の複数クエリによる累積スキャン量を監視し、コスト高騰を早期検知
特徴:
- ✅ Athena WorkgroupがCloudWatchにメトリクスを送信(
publish_cloudwatch_metrics_enabled = true) - ✅ CloudWatch Alarmが直接メトリクスを評価(外部システム不要)
- ✅ スパースメトリクス対応:
treat_missing_data = "notBreaching"により自動リカバリを実現 - ✅ 監視間隔: デフォルト10分(
evaluation_period_seconds変数でカスタマイズ可能) - ✅ 追加コストなし: CloudWatch Alarm無料枠内(10アラーム/月まで無料)
AWS Chatbot統合の制約と対応
AWS Chatbotの制限:
- 1つのSlackチャンネルには、1つのAWS Chatbot設定しか紐付けられない(AWSアカウント単位)
- 複数のSNS TopicをSlackに通知したい場合、Chatbot設定を共有する必要がある
実装上の対応: 本システムでは、既存のAWS Health Event用Chatbot設定を活用し、Athena監視用SNS TopicをChatbot設定に追加する方式を採用しました。
# globals/aws-health-event/main.tf
module "aws-health-event" {
source = "../../../../template_modules/common/platform/aws-health-event"
# 既存のAWS Health Event SNS Topic + Athena監視SNS Topicを統合
additional_sns_topic_arns = [
data.terraform_remote_state.common.outputs.athena_cost_monitoring_sns_topic_arn
]
}通知先Slackチャンネル: #squad-sre-noti-saas-status-dev
- AWS Health Event通知(本来の用途)
- Athena Cost Monitoring通知(追加)
Layer 3: 長期コスト分析(Cost Explorer週次ワークフロー)
目的: 週次コスト傾向分析と異常検知
- 実行頻度: 週次(毎週月曜日)
- 分析内容: Cost Explorerを使用したAthenaコスト傾向分析
- 検知方法: 前週比での異常増加の自動検知
- 通知先: Slack(#sre-alerts)
- 用途: 中長期的なコスト傾向把握と異常の早期発見
コスト試算
前提条件
- 想定スキャン量: 1TB/日(※あくまで仮の想定値)
- Athena料金: $5/TB
- 月次稼働日: 30日
注記: 以下のシナリオで使用するスキャン量および削減幅は、あくまでも削減効果のイメージを示すための仮の数値です。実際の運用では、クエリパターンやデータ量に応じて適宜調整が必要です。
シナリオ別コスト試算
シナリオ1: 監視なし(リスクケース)
| 項目 | 日次 | 月次 | 年次 |
|---|---|---|---|
| Athenaスキャン料金 | $5.00 | $150.00 | $1,800.00 |
| S3(クエリ結果) | $0.01 | $0.30 | $3.60 |
| 合計 | $5.01 | $150.30 | $1,803.60 |
リスク:
- ❌ 暴走クエリで突然10TB → $50/日の可能性
- ❌ 異常検知なし
- ❌ 年間潜在的損失リスク: $500〜$5,000
シナリオ2: Workgroup Controls のみ
設定: bytes_scanned_cutoff_per_query = 10GB
想定される効果:
- 暴走クエリが自動キャンセル(推定2-3件/日)
- 平均スキャン量: 1TB → 0.85TB(15%削減)
| 項目 | 日次 | 月次 | 年次 | 削減額 |
|---|---|---|---|---|
| Athenaスキャン料金 | $4.25 | $127.50 | $1,530.00 | -$270/年 |
| S3 クエリ結果 | $0.01 | $0.25 | $3.00 | -$0.60/年 |
| Workgroup Controls | $0.00 | $0.00 | $0.00 | 無料 |
| 合計 | $4.26 | $127.75 | $1,533.00 | -$270.60/年 |
効果:
- ✅ 年間約$270節約(15%削減)
- ✅ 追加コストゼロ
- ✅ 暴走クエリ自動防止
シナリオ3: 推奨構成(Workgroup + CloudWatch Alarm監視)
設定:
- Workgroup Controls: 10GB/クエリ
- CloudWatch Alarm(Warning): 50GB/評価期間
- CloudWatch Alarm(Critical): 100GB/評価期間
- 評価期間: 10分(カスタマイズ可能)
| 項目 | 日次 | 月次 | 年次 |
|---|---|---|---|
| Athenaスキャン料金 | $4.25 | $127.50 | $1,530.00 |
| S3 クエリ結果 | $0.01 | $0.25 | $3.00 |
| CloudWatch Alarm監視 | $0.00 | $0.00* | $0.00* |
| 合計 | $4.26 | $127.75 | $1,533.00 |
*CloudWatch Alarm無料枠内(10アラーム/月まで無料)
投資対効果(ROI):
年間コスト削減: $270.60
年間追加コスト: $0(CloudWatch無料枠内)
純利益: $270.60/年(15%削減)
ROI = ∞(追加コストゼロ)効果:
- ✅ 年間約$270節約
- ✅ 事前警告あり(評価期間ごと、デフォルト10分)
- ✅ 暴走クエリ自動防止
- ✅ Slack通知で即座に対応可能(AWS Chatbot経由)
- ✅ 自動リカバリ機能(運用負荷削減)
- ✅ 追加コスト: $0(CloudWatch無料枠内)
30分間でのスキャン量シミュレーション
Athenaの制限値
- 同時実行クエリ数: 20(デフォルト)
- 1クエリの上限: 10GB(Workgroup設定)
- クエリ実行時間: 30秒〜2分(平均1分)
最悪ケースシナリオ
| シナリオ | クエリペース | 30分のクエリ数 | スキャン量 | コスト |
|---|---|---|---|---|
| 通常 | 1クエリ/分 | 30 | 300GB | $1.50 |
| 高速 | 1クエリ/30秒 | 60 | 600GB | $3.00 |
| 最悪 | 同時20クエリ連続 | 1,200 | 12TB | $60 🚨 |
結論: 日次監視(24時間間隔)では、最悪ケースで$2,880の損失リスクあり。 対策: 10分間隔の監視が必須(運用しながら調整)
監視戦略
監視間隔の決定
監視間隔ごとの検知能力
| 監視間隔 | 最悪ケース累積 | 通常ケース累積 | 検知遅延 | 最大損失 | 推奨度 |
|---|---|---|---|---|---|
| 5分 | 2TB ($10) | 50GB ($0.25) | 最大5分 | $10 | ⭐⭐⭐⭐ |
| 10分 ⭐ | 4TB ($20) | 100GB ($0.50) | 最大10分 | $20 | ⭐⭐⭐⭐⭐ |
| 15分 | 6TB ($30) | 150GB ($0.75) | 最大15分 | $30 | ⭐⭐⭐⭐ |
| 30分 | 12TB ($60) | 300GB ($1.50) | 最大30分 | $60 | ⭐⭐⭐ |
| 1時間 | 24TB ($120) | 600GB ($3.00) | 最大1時間 | $120 | ⭐⭐ |
| 24時間 | 576TB ($2,880) | 14.4TB ($72) | 最大24時間 | $2,880 | ❌ |
推奨: 10分間隔(評価期間は変数でカスタマイズ可能)
選定理由:
- ✅ 検知遅延が短い(最大10分)
- ✅ 最大損失が許容範囲内($20)
- ✅ CloudWatch Alarm設定が簡単
- ✅ 誤検知が少ない(適度な集計期間)
- ✅ 運用負荷が低い
- ✅ 実運用で閾値・評価期間を調整可能(
evaluation_period_seconds変数)
評価期間のカスタマイズ:
# 5分評価の場合
evaluation_period_seconds = 300
# 10分評価の場合(デフォルト)
evaluation_period_seconds = 600
# 30分評価の場合
evaluation_period_seconds = 1800
# 1時間評価の場合
evaluation_period_seconds = 3600多段階アラート設定
予算ベースの閾値設定
月予算: $150
日予算: $5.00
時間予算: $0.208(≈ $0.20)
10分予算: $0.035(≈ $0.04)Layer 1: Workgroup Controls(物理的ブロック)
目的: 単一クエリの暴走防止
方式: 上限到達で自動キャンセル
閾値: 10GB/クエリ($0.05)
検知: 瞬時(<1秒)
通知: なし(物理的にブロックのみ)Layer 2: CloudWatch Alarm(10分累積監視)
| レベル | 閾値 | コスト | 日次換算 | 月次換算 | アクション | 自動リカバリ |
|---|---|---|---|---|---|---|
| Warning | 50GB/10分 | $0.25 | $36/日 | $1,080/月 | Slack通知 | ✅ 自動 |
| Critical | 100GB/10分 | $0.50 | $72/日 | $2,160/月 | Slack(緊急) | ✅ 自動 |
注:
- 閾値は運用開始後に実際のスキャン量に基づいて調整します
- 評価期間(デフォルト10分)は
evaluation_period_seconds変数で変更可能 - スパースメトリクス対応により、クエリが実行されない期間は自動的にOK状態に復帰
CloudWatch Alarmの設定:
# Warning Alarm設定
alarm_name = "[Athena][infra-dev][All Workgroups] 10分累積 Warning"
metric_name = "ProcessedBytes"
namespace = "AWS/Athena"
statistic = "Sum"
period = 600 # 10分
evaluation_periods = 1
threshold = 53687091200 # 50GB
comparison_operator = "GreaterThanThreshold"
treat_missing_data = "notBreaching" # 自動リカバリの要アラート通知メッセージ(AWS Chatbot経由): AWS Chatbotが自動的にSlackに以下の情報を通知します:
- アラーム名
- 現在の状態(ALARM/OK)
- メトリクス値
- 閾値
- トリガー時刻
- AWS Console リンク
技術仕様
AWS実装(Workgroup)
📄 Terraform実装例を表示(クリックして展開)
注意: 以下は実装例です。実際の環境に合わせて調整してください。
1. Athena Workgroup
# ============================================================================
# 実装例: Athena Workgroup
# ============================================================================
resource "aws_athena_workgroup" "log_analysis" {
name = "log-analysis-workgroup"
description = "Log analysis workgroup with cost controls"
state = "ENABLED"
configuration {
# ========================================
# CloudWatch メトリクス送信(Datadog監視に必須)
# ========================================
publish_cloudwatch_metrics_enabled = true
# ========================================
# コスト制御: 10GB/クエリ
# ========================================
bytes_scanned_cutoff_per_query = 10737418240 # 10GB
# ========================================
# クエリ結果の保存先
# ========================================
result_configuration {
output_location = "s3://${var.athena_results_bucket}/results/"
encryption_configuration {
encryption_option = "SSE_S3"
}
}
}
tags = {
Name = "log-analysis-workgroup"
ManagedBy = "Terraform"
Service = "log-analysis"
CostControl = "enabled"
}
}CloudWatch Alarm実装
ディレクトリ構成
terraform_for_aws/
├── fastdoctor-template/
│ ├── common/
│ │ └── infra-dev/
│ │ ├── main.tf # Athena監視モジュール呼び出し
│ │ ├── variable.tf # 環境固有変数の宣言
│ │ ├── outputs.tf # SNS Topic ARN出力
│ │ └── globals/
│ │ └── aws-health-event/
│ │ └── main.tf # Chatbot統合設定
│ └── template_modules/
│ └── options/
│ └── athena-cost-monitoring/ # 再利用可能モジュール
│ ├── main.tf # CloudWatch Alarm定義
│ ├── variables.tf # モジュール変数
│ ├── outputs.tf # SNS Topic ARN等
│ └── README.md # 使用方法ドキュメントモジュール実装
全Workgroup監視機能: workgroup_name = nullとすることで、特定のWorkgroupではなく全てのWorkgroupを集約して監視できます。これにより、予期しないWorkgroup作成によるコスト高騰を防止できます。
📄 CloudWatch Alarm Terraform実装例を表示(クリックして展開)
注意: 以下は実装例です。実際の環境に合わせて調整してください。
fastdoctor-template/template_modules/options/athena-cost-monitoring/main.tf
# ============================================================================
# 実装例: CloudWatch Alarm - 累積スキャン量監視
# ============================================================================
# ============================================================================
# Workgroup監視の柔軟性
# ============================================================================
# - workgroup_name = null → 全Workgroupを監視(推奨)
# - workgroup_name = "specific-name" → 特定Workgroupのみ監視
locals {
# 全Workgroup監視かどうかを判定
monitor_all_workgroups = var.workgroup_name == null || var.workgroup_name == ""
# CloudWatch Dimensions: 全Workgroup監視時は集約ディメンションを使用
dimensions = local.monitor_all_workgroups ? {
QueryState = "SUCCEEDED"
QueryType = "DML"
} : {
WorkGroup = var.workgroup_name
}
# アラーム名のサフィックス
alarm_name_suffix = local.monitor_all_workgroups ? "All Workgroups" : var.workgroup_name
}
# ============================================================================
# SNS Topic(アラート通知先)
# ============================================================================
resource "aws_sns_topic" "athena_alerts" {
name = "${var.project}-athena-alerts-${var.environment}"
tags = {
Name = "${var.project}-athena-alerts-${var.environment}"
Environment = var.environment
Service = "athena-monitoring"
ManagedBy = "Terraform"
}
}
# ============================================================================
# Warning Alarm: 50GB/評価期間
# ============================================================================
resource "aws_cloudwatch_metric_alarm" "athena_10min_warning" {
count = var.enable_warning_alarm ? 1 : 0
alarm_name = "[Athena][${var.environment}][${local.alarm_name_suffix}] 10分累積 Warning"
alarm_description = "Athena data scan warning: ${var.threshold_10min_warning_bytes} bytes in ${var.evaluation_period_seconds} seconds"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "ProcessedBytes"
namespace = "AWS/Athena"
period = var.evaluation_period_seconds
statistic = "Sum"
threshold = var.threshold_10min_warning_bytes
treat_missing_data = "notBreaching" # スパースメトリクス対応: 自動リカバリの要
dimensions = local.dimensions
alarm_actions = [aws_sns_topic.athena_alerts.arn]
ok_actions = [aws_sns_topic.athena_alerts.arn]
tags = {
Name = "athena-warning-alarm"
Environment = var.environment
Severity = "warning"
Service = "athena-monitoring"
ManagedBy = "Terraform"
}
}
# ============================================================================
# Critical Alarm: 100GB/評価期間
# ============================================================================
resource "aws_cloudwatch_metric_alarm" "athena_10min_critical" {
alarm_name = "[Athena][${var.environment}][${local.alarm_name_suffix}] 10分累積 Critical"
alarm_description = "Athena data scan critical: ${var.threshold_10min_critical_bytes} bytes in ${var.evaluation_period_seconds} seconds"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "ProcessedBytes"
namespace = "AWS/Athena"
period = var.evaluation_period_seconds
statistic = "Sum"
threshold = var.threshold_10min_critical_bytes
treat_missing_data = "notBreaching" # スパースメトリクス対応: 自動リカバリの要
dimensions = local.dimensions
alarm_actions = [aws_sns_topic.athena_alerts.arn]
ok_actions = [aws_sns_topic.athena_alerts.arn]
tags = {
Name = "athena-critical-alarm"
Environment = var.environment
Severity = "critical"
Service = "athena-monitoring"
ManagedBy = "Terraform"
}
}実装のポイント:
スパースメトリクス対応
treat_missing_data = "notBreaching": クエリが実行されない期間は自動的にOK状態に復帰- これにより、Datadogで実現できなかった自動リカバリを実現
全Workgroup監視
workgroup_name = null時:QueryState=SUCCEEDED+QueryType=DMLディメンションで全Workgroupを集約監視- 予期しないWorkgroup作成によるコスト高騰を防止
評価期間のカスタマイズ
evaluation_period_seconds変数でperiodを変更可能(デフォルト: 600秒=10分)- 環境やユースケースに応じて柔軟に調整
SNS Topicの統合
- モジュール内でSNS Topicを作成
- outputでARNを公開し、AWS Chatbot統合で使用
fastdoctor-template/template_modules/options/athena-cost-monitoring/variables.tf
# ============================================================================
# 実装例: 変数定義
# ============================================================================
# ============================================================================
# 基本設定
# ============================================================================
variable "project" {
type = string
description = "Project name"
}
variable "environment" {
type = string
description = "Environment name (infra-dev, develop, staging, production)"
}
variable "workgroup_name" {
type = string
description = "Athena Workgroup name to monitor. Set to null or empty string to monitor all workgroups."
default = null
}
# ============================================================================
# 監視期間設定
# ============================================================================
variable "evaluation_period_seconds" {
type = number
description = "CloudWatch Alarm evaluation period in seconds. Default: 600 (10 minutes)"
default = 600
}
# ============================================================================
# 閾値設定
# ============================================================================
variable "threshold_10min_warning_bytes" {
type = number
description = "Warning threshold for data scan (bytes). Default: 50GB"
default = 53687091200 # 50GB = 50 * 1024^3
}
variable "threshold_10min_critical_bytes" {
type = number
description = "Critical threshold for data scan (bytes). Default: 100GB"
default = 107374182400 # 100GB = 100 * 1024^3
}
# ============================================================================
# オプション設定
# ============================================================================
variable "enable_warning_alarm" {
type = bool
description = "Enable warning level alarm. Set to false to use only critical alarm."
default = true
}環境別定義例
📄 環境別定義例を表示(クリックして展開)
注意: 以下は実装例です。実際の環境に合わせて調整してください。
fastdoctor-template/common/infra-dev/main.tf
# ============================================================================
# 実装例: infra-dev環境のAthenaコスト監視(全Workgroup監視)
# ============================================================================
module "athena-cost-monitoring" {
source = "../../template_modules/options/athena-cost-monitoring"
project = var.project
environment = var.athena_monitoring_environment
workgroup_name = null # 全Workgroupを監視(推奨)
# 閾値設定
threshold_10min_warning_bytes = var.athena_monitoring_threshold_warning_bytes
threshold_10min_critical_bytes = var.athena_monitoring_threshold_critical_bytes
# 評価期間(デフォルト: 600秒 = 10分)
evaluation_period_seconds = 600
# Warning Alarmを有効化
enable_warning_alarm = true
providers = {
aws = aws.tokyo
}
}fastdoctor-template/common/infra-dev/variable.tf
# Athena監視の環境変数
variable "athena_monitoring_environment" {
type = string
description = "Environment name for Athena cost monitoring"
}
variable "athena_monitoring_threshold_warning_bytes" {
type = number
description = "Warning threshold for Athena data scan (bytes)"
}
variable "athena_monitoring_threshold_critical_bytes" {
type = number
description = "Critical threshold for Athena data scan (bytes)"
}fastdoctor-template/common/infra-dev/terraform.tfvars(S3で管理)
# Athena監視設定
athena_monitoring_environment = "infra-dev"
athena_monitoring_threshold_warning_bytes = 53687091200 # 50GB
athena_monitoring_threshold_critical_bytes = 107374182400 # 100GBfastdoctor-template/common/infra-dev/globals/aws-health-event/main.tf(Chatbot統合)
# ============================================================================
# AWS Health EventとAthena Cost MonitoringのChatbot統合
# ============================================================================
# 注意: AWS Chatbotの制限により、1つのSlackチャンネルには1つのChatbot設定しか
# 紐付けられないため、AWS Health EventとAthena Cost Monitoringの通知を
# このChatbot設定に統合しています。
data "terraform_remote_state" "common" {
backend = "s3"
config = {
bucket = "fd-tfstate-infra-dev"
key = "common.tfstate"
region = "ap-northeast-1"
}
}
module "aws-health-event" {
source = "../../../../template_modules/common/platform/aws-health-event"
chatbot_role_name = var.chatbot_role_name
chatbot_policy_name = var.chatbot_policy_name
channel_name = var.channel_name
slack_workspace_id = var.slack_workspace_id
slack_channel_id = var.slack_channel_id
sns_topic_name = var.sns_topic_name
event_rule_name = var.event_rule_name
# Athena Cost Monitoring SNS Topicを追加
additional_sns_topic_arns = [
data.terraform_remote_state.common.outputs.athena_cost_monitoring_sns_topic_arn
]
}運用ガイド
アラート対応フロー
Level 1: Query Cancelled(瞬間値)
トリガー: 単一クエリが10GBを超過してキャンセル
対応手順:
クエリの確認
bashaws athena get-query-execution --query-execution-id <query-id>クエリの最適化検討
- パーティション使用の確認
- WHERE句の最適化
- 不要なカラムの除外
必要に応じてWorkgroup変更
- 正当に10GB超が必要な場合、大規模クエリ用Workgroupを検討
Level 2: CloudWatch Alarm - Warning(50GB超過)
トリガー: 評価期間(デフォルト10分)で50GB以上スキャン
Slack通知内容(AWS Chatbot経由):
- アラーム名:
[Athena][infra-dev][All Workgroups] 10分累積 Warning - 状態: ALARM
- メトリクス値: 実際のスキャン量(バイト)
- 閾値: 53687091200 bytes (50GB)
- AWS Consoleリンク
対応手順:
CloudWatch Consoleで詳細確認
- AWS Consoleリンクから直接アクセス
- メトリクスの推移を確認
- スパイクか継続的な増加かを判断
AWS CLIで実行クエリ確認
bash# 最近実行されたクエリをリスト表示 aws athena list-query-executions \ --max-results 50 \ --region ap-northeast-1頻繁に実行されているクエリの特定
bash# クエリ詳細を確認 aws athena get-query-execution \ --query-execution-id <query-id> \ --region ap-northeast-1一時的な高負荷か継続的な問題かを判断
- 一時的: 監視継続(自動リカバリを待つ)
- 継続的: Level 3へエスカレーション
Level 3: CloudWatch Alarm - Critical(100GB超過)
トリガー: 評価期間(デフォルト10分)で100GB以上スキャン
Slack通知内容(AWS Chatbot経由):
- アラーム名:
[Athena][infra-dev][All Workgroups] 10分累積 Critical - 状態: ALARM
- メトリクス値: 実際のスキャン量(バイト)
- 閾値: 107374182400 bytes (100GB)
- AWS Consoleリンク
対応手順:
即座に実行中クエリの確認
bashaws athena list-query-executions \ --status-filter RUNNING \ --region ap-northeast-1必要に応じてクエリ強制停止
bashaws athena stop-query-execution \ --query-execution-id <query-id> \ --region ap-northeast-1根本原因の調査
- 自動化ジョブの暴走
- スクリプトのバグ
- 意図しない全件スキャン
- 予期しないWorkgroupの作成
一時的な対策
- 問題のクエリを停止
- 必要に応じてWorkgroup一時停止も検討
- IAM権限の一時的制限
アラート自動リカバリ
重要: CloudWatch Alarmはtreat_missing_data = "notBreaching"設定により、クエリが実行されない期間(データポイントなし)は自動的にOK状態に復帰します。
リカバリ通知(AWS Chatbot経由):
- アラーム名:
[Athena][infra-dev][All Workgroups] 10分累積 Warning/Critical - 状態: OK
- メッセージ: アラームが復旧したことを通知
確認事項:
- リカバリ通知を受信したら、Slack上で確認完了を報告
- 必要に応じてインシデント事後分析(Post-mortem)を実施
セキュリティ考慮事項
IAMポリシー
📄 IAMポリシー例を表示(クリックして展開)
注意: 以下は実装例です。実際の環境に合わせて調整してください。
Athena実行権限
data "aws_iam_policy_document" "athena_user" {
# Athena実行権限
statement {
effect = "Allow"
actions = [
"athena:StartQueryExecution",
"athena:GetQueryExecution",
"athena:GetQueryResults",
"athena:StopQueryExecution",
"athena:GetWorkGroup",
"athena:ListQueryExecutions",
]
resources = [
aws_athena_workgroup.log_analysis.arn,
]
}
# S3アクセス権限
statement {
effect = "Allow"
actions = [
"s3:GetObject",
"s3:ListBucket",
]
resources = [
"arn:aws:s3:::${var.log_bucket_name}/*",
"arn:aws:s3:::${var.log_bucket_name}",
]
}
# クエリ結果保存権限
statement {
effect = "Allow"
actions = [
"s3:PutObject",
"s3:GetObject",
]
resources = [
"arn:aws:s3:::${var.athena_results_bucket}/results/*",
]
}
# Glue Data Catalog権限
statement {
effect = "Allow"
actions = [
"glue:GetDatabase",
"glue:GetTable",
"glue:GetPartitions",
]
resources = ["*"]
}
}導入ロードマップ
Phase 1: AWS基盤構築
実装内容:
- ✅ Athena Workgroup作成
- ✅ Data Usage Controls設定(10GB/クエリ)
成果物:
- Workgroup設定完了
- 単一クエリ暴走防止機能有効化
Phase 2: CloudWatch Alarm監視構築(infra-dev検証完了)
実装内容:
- ✅ CloudWatch Alarmモジュール作成(
template_modules/options/athena-cost-monitoring) - ✅ 10分累積監視設定(Warning: 50GB / Critical: 100GB)
- ✅ スパースメトリクス対応(
treat_missing_data = "notBreaching") - ✅ 全Workgroup監視機能実装
- ✅ 評価期間のカスタマイズ機能(
evaluation_period_seconds変数) - ✅ AWS Chatbot統合(既存AWS Health Event設定を活用)
- ✅ Slack通知設定(#squad-sre-noti-saas-status-dev: infra-dev/staging用)
成果物:
- ✅ infra-dev環境でのCloudWatch Alarm構築完了
- ✅ Slack通知機能有効化・検証完了
- ✅ 自動リカバリ機能検証完了
- ✅ 実データテスト完了(292バイトスキャンクエリ)
- ✅ 手動アラームテスト完了(
set-alarm-state)
検証結果(infra-dev環境):
- アラート発生: ✅ 成功(Slack #squad-sre-noti-saas-status-dev 通知確認)
- 自動リカバリ: ✅ 成功(OK状態への自動復帰確認)
次のステップ:
- staging環境への展開
- production環境への展開(通知先: #squad-sre-noti-saas-status)
Phase 3: 運用最適化(継続)
実装内容:
- ✅ Cost Explorer週次ワークフロー統合
- ✅ チーム向けトレーニング
- ✅ 閾値チューニング
KPI:
- 平均スキャン量: 実測値をベースに最適化
- アラート対応時間: 10分以内
- 週次コスト傾向: 異常増加の早期検知
まとめ
期待効果
| 項目 | リスクケース | 導入後 | 改善 |
|---|---|---|---|
| 月次コスト | $150.30 | $127.75 | -15% |
| 検知遅延 | なし | 10分(カスタマイズ可) | 早期検知 |
| 最大損失リスク | 無制限 | $20(10分) | 制御可能 |
| 運用工数 | - | +1時間/月 | 微増 |
| 監視システムコスト | $0 | $0 | 無料 |
| 自動リカバリ | なし | ✅ 自動 | 運用負荷削減 |
*CloudWatch Alarm無料枠内(10アラーム/月まで無料)
主要な利点
リスク予防
- 運用開始前にコスト制御機能を整備
- 単一クエリ暴走防止: 物理的ブロック(Workgroup Controls)
- 累積コスト監視: 評価期間(デフォルト10分)で早期検知
- 全Workgroup監視: 予期しないWorkgroup作成によるコスト高騰を防止
コスト最適化
- データドリブンな意思決定
- CloudWatch Metricsでコスト傾向の可視化
- カスタマイズ可能な評価期間(5分〜1時間)
- 追加コストゼロ(CloudWatch無料枠内)
運用効率化
- 自動監視・通知(CloudWatch Alarm + AWS Chatbot)
- 問題の早期発見(評価期間内)
- 自動リカバリ: クエリ停止後、自動的にOK状態に復帰
- Slack統合で迅速な対応
- 運用負荷削減(手動リカバリ不要)
技術的優位性
- スパースメトリクス対応(Datadogで実現できなかった自動リカバリ)
- ネイティブAWS統合(外部システム依存なし)
- 柔軟な設定(評価期間・閾値・Workgroup範囲)
- Terraform化による再現性・移植性
参考資料
AWS公式ドキュメント
- Amazon Athena Pricing
- Configure per-query and per-workgroup data usage controls
- Amazon CloudWatch Alarms
- Using Amazon CloudWatch alarms
- AWS Chatbot User Guide
- AWS Cost Explorer
Terraform Provider
内部ドキュメント
- Athena Cost Monitoring Module README:
fastdoctor-template/template_modules/options/athena-cost-monitoring/README.md - Athena Cost Monitoring Datadog Verification:
docs/aws/service-guides/athena-datadog-verification.md(未作成) - Datadog Setup Documentation:
datadog/common/infra-dev/ATHENA_MONITOR_SETUP.md(未作成)
改訂履歴
| バージョン | 日付 | 作成者 | 変更内容 |
|---|---|---|---|
| 1.0 | 2026-02-17 | SREチーム | 初版作成 |