ALBトラフィック倍増より料金が請求金額が上がった話




「先月より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の費用が発生
- **グローバルフリーティア**の10TB制限超過による従量課金($0.114/GB)が大部分を占める
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671079/730e4f1d-29ca-4942-ba99-e5e56df2e66f.png)

- **ALBからインターネットへのアウトバウンドトラフィック**が主要因

## 調査プロセス：効率的な原因特定のために行ったこと

### STEP 1：AWS Cost Explorerによる全体像の把握  

まずはAWS Cost Explorerで高額請求の全体像を把握します。

```bash
# 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に対して、以下のメトリクスを詳細に分析します：

```bash
# 特定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月中旬のプロモーション開始に伴い、以下の問題が複合的に作用していました：

1. **キャッシュ設定不備**：静的画像にキャッシュヘッダーが設定されておらず、ブラウザが毎回再取得
2. **アプリケーション経由の配信**：全ての静的アセットがALBとアプリケーションサーバーを経由
3. **大量アクセスの集中**：プロモーションページへのトラフィックが想定の5倍に増加

特に、高解像度の商品画像とバナー画像が毎回ALBを通して取得されていたことが最大の要因でした。

## 解決策の実装：S3+CloudFrontによる静的アセット最適化

問題の核心が「静的画像がALBを経由している」ことだと特定したため、以下のアーキテクチャ変更を実施しました。

### コスト削減方針（ADR） の作成

#### 目的
- 静的画像のALB経由アクセスを削減しコスト削減
- 適切なキャッシュ戦略によるパフォーマンス向上

#### アーキテクチャ決定
1. **S3バケット**を東京リージョンに作成し、CloudFront経由のみアクセス可能に設定
2. **CloudFront**でディストリビューションを作成し、Origin Access Control (OAC)でS3へのアクセスを制限
3. **キャッシュ設定**を最適化し、静的アセットの長期キャッシュを実現

### 具体的な実装：S3+CloudFrontの構築

#### 1. S3バケットの作成

```bash
# バケット作成
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にアップロードする際に、適切なキャッシュ設定も同時に行いました：

```bash
# 一括アップロード（初回）
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. キャッシュ無効化の自動化

画像更新時のキャッシュ無効化を自動化するスクリプトを作成：

```bash
#!/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つです：

1. **静的アセットは適切な場所で提供する**: アプリケーションサーバーとALBを経由させず、S3+CloudFrontで提供
2. **キャッシュ戦略を明確に設計する**: 更新頻度に合わせた適切なTTL設定とCache-Controlヘッダーの活用
3. **継続的なモニタリングを行う**: コスト変動を早期に検知し、迅速に対応できる体制を整える

こうした基本に忠実なアプローチが、大きなコスト削減と同時にパフォーマンス向上をもたらすのではないかと今回の事象を通して感じました。

## 参考リソース：

- [AWS Elastic Load Balancing 料金](https://aws.amazon.com/jp/elasticloadbalancing/pricing/)
- [AWS Application Load Balancer ユーザーガイド](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/introduction.html)
- [AWSのコスト最適化ベストプラクティス](https://aws.amazon.com/jp/aws-cost-management/aws-cost-optimization/)
- [AWS Well-Architected フレームワーク - コスト最適化の柱](https://docs.aws.amazon.com/ja_jp/wellarchitected/latest/cost-optimization-pillar/welcome.html)
- [AWS公式: Origin Access Control でS3へのアクセスを制限する](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html)
- [AWS公式: Cache-Control / TTL ベストプラクティス](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html)