「先月よりALBの請求額が2倍に増えている...」
AWS請求書を確認したとき、この数字を見て私は目を疑いました。特にDataTransfer料金が突出して増加していたのです。
問題発見:請求額が前月比2倍に急増した理由
2025年4月、AWSの請求書を確認して違和感を感じました。概要は例ですが、実際に発生した状況と同様のケースです。
【請求書概要】(例)
- 3月合計: $5,450
- 4月合計: $9,720 (前月比: +78%)
- CRDSのDataTransfer: $4,320 (前月比: +320%)
調査の結果、以下の事実が判明しました:
-
Application Load Balancingが全データ転送量の約80%(11,000 GB)を占め、約$1,200の費用が発生
-
ALBからインターネットへのアウトバウンドトラフィックが主要因
調査プロセス:効率的な原因特定のために行ったこと
STEP 1:AWS Cost Explorerによる全体像の把握
まずはAWS Cost Explorerで高額請求の全体像を把握します。
# AWS CLIを使用する場合
aws ce get-cost-and-usage \
--time-period Start=2025-03-01,End=2025-04-30 \
--granularity DAILY \
--metrics "BlendedCost" "UsageQuantity" \
--group-by Type=DIMENSION,Key=SERVICE \
--filter '{"Dimensions": {"Key": "SERVICE", "Values": ["Amazon Elastic Load Balancing"]}}' \
> alb_costs.json
STEP 2:CloudWatchでのメトリクス詳細分析
問題のALBに対して、以下のメトリクスを詳細に分析します:
# 特定ALBの詳細メトリクスを取得
aws cloudwatch get-metric-data \
--metric-data-queries '{"Id":"m1","MetricStat":{"Metric":{"Namespace":"AWS/ApplicationALB","MetricName":"ProcessedBytes","Dimensions":[{"Name":"LoadBalancer","Value":"app/problem-alb-1/abc123"}]},"Period":3600,"Stat":"Sum"}}' \
--start-time 2025-03-01T00:00:00Z \
--end-time 2025-04-30T23:59:59Z > alb1_bytes.json
調査のコツ: 以下のメトリクスを重点的に確認しましょう
-
ProcessedBytes
(処理バイト数) -
NewConnectionCount
(新規接続数) -
ActiveConnectionCount
(アクティブ接続数)
根本原因の特定:なぜトラフィックが爆発的に増えたのか?
詳細な分析の結果、以下が主要な原因と判明しました:
原因:静的画像リクエストがALBとアプリケーションに大負荷
3月中旬のプロモーション開始に伴い、以下の問題が複合的に作用していました:
- キャッシュ設定不備:静的画像にキャッシュヘッダーが設定されておらず、ブラウザが毎回再取得
- アプリケーション経由の配信:全ての静的アセットがALBとアプリケーションサーバーを経由
- 大量アクセスの集中:プロモーションページへのトラフィックが想定の5倍に増加
特に、高解像度の商品画像とバナー画像が毎回ALBを通して取得されていたことが最大の要因でした。
解決策の実装:S3+CloudFrontによる静的アセット最適化
問題の核心が「静的画像がALBを経由している」ことだと特定したため、以下のアーキテクチャ変更を実施しました。
コスト削減方針(ADR) の作成
目的
- 静的画像のALB経由アクセスを削減しコスト削減
- 適切なキャッシュ戦略によるパフォーマンス向上
アーキテクチャ決定
- S3バケットを東京リージョンに作成し、CloudFront経由のみアクセス可能に設定
- CloudFrontでディストリビューションを作成し、Origin Access Control (OAC)でS3へのアクセスを制限
- キャッシュ設定を最適化し、静的アセットの長期キャッシュを実現
具体的な実装:S3+CloudFrontの構築
1. S3バケットの作成
# バケット作成
aws s3 mb s3://company-static-assets-prod --region ap-northeast-1
# バージョニング有効化
aws s3api put-bucket-versioning \
--bucket company-static-assets-prod \
--versioning-configuration Status=Enabled
2. CloudFrontディストリビューションの設定
CloudFrontコンソールからディストリビューションを作成し、S3をオリジンとして設定しました。主な設定:
- Origin Access Control (OAC)を使用してS3バケットを非公開に保持
- TTLの最適化: デフォルトTTLを86400秒(1日)に設定
- リダイレクト: HTTPからHTTPSへのリダイレクトを有効化
- キャッシュポリシー: CachingOptimizedを選択し、オブジェクト側でTTLを上書き
3. 画像ファイルの移行とアップロード
既存の画像ファイルをS3にアップロードする際に、適切なキャッシュ設定も同時に行いました:
# 一括アップロード(初回)
aws s3 sync ./assets/images/ s3://company-static-assets-prod/assets/images/ \
--cache-control "public,max-age=31536000,immutable"
# 個別ファイル更新(必要に応じて)
aws s3 cp ./assets/images/banner.jpg \
s3://company-static-assets-prod/assets/images/banner.jpg \
--cache-control "public,max-age=31536000,immutable"
4. キャッシュ無効化の自動化
画像更新時のキャッシュ無効化を自動化するスクリプトを作成:
#!/bin/bash
# invalidate-cache.sh
# 引数チェック
if [ $# -ne 1 ]; then
echo "Usage: $0 <filename>"
exit 1
fi
FILENAME=$1
DISTRIBUTION_ID="Exxxxxxxx"
# キャッシュ無効化
aws cloudfront create-invalidation \
--distribution-id $DISTRIBUTION_ID \
--paths "/assets/images/$FILENAME"
echo "Cache invalidated for /assets/images/$FILENAME"
Cost Explorerによる継続的監視
引き続き Cost Explorerによるダッシュボードでの継続監視を続けていきます。
・GoogleスプレッドシートとAppScriptを使用して、
daily、Weekly,monthlyで費用を詳細に表示しても可能です
教訓:AWS料金管理における3つの重要な原則
今回の事例から得られた重要な教訓:
1. 早期発見・早期対応の仕組み作り
- 日次レベルでのコスト監視: AWS Cost Explorerを毎日チェック
2. ALB最適化のためのベストプラクティス
- キャッシュ戦略の重要性: TTL設定とCache-Controlの適切な活用
- レスポンスサイズの最適化: 不要なデータ転送を削減
- リージョン配置の考慮: クロスリージョン通信の最小化
まとめ:AWSコスト継続的な管理ために
AWSの料金、特にALB関連のコストは、トラフィックパターンの変化によって予期せぬ高騰が発生する可能性があります。今回の事例から学んだ最も重要な点は以下の3つです:
- 静的アセットは適切な場所で提供する: アプリケーションサーバーとALBを経由させず、S3+CloudFrontで提供
- キャッシュ戦略を明確に設計する: 更新頻度に合わせた適切なTTL設定とCache-Controlヘッダーの活用
- 継続的なモニタリングを行う: コスト変動を早期に検知し、迅速に対応できる体制を整える
こうした基本に忠実なアプローチが、大きなコスト削減と同時にパフォーマンス向上をもたらすのではないかと今回の事象を通して感じました。