月80万円のAWSデータ転送費をVPCエンドポイント+CloudFrontで削減した話
請求書で発見した月80万円のデータ転送費。VPCエンドポイントとCloudFrontの実装で何が変わったのか、3ヶ月の改善記録を正直に共有します。
月80万円のデータ転送費をVPCエンドポイント+CloudFront導入で削減した実装記
請求書で気づいた、月80万円の見えない出血
先日、営業からAWSの月次請求を確認するよう指摘されたんですよ。いつもの「まあこんなもんか」という感じで見てたら、EC2-Otherという謎の項目が月80万円。正直、これが何なのか知らなかった。
チームで確認してみたら、データ転送費だと判明。S3からのデータ取得、API呼び出し、マイクロサービス間通信……全部が外部ネットワークへの転送扱いでカウントされてた。うちの場合、ほぼ社内システムなのに、データがインターネットを経由して往復してたんですよ。完全に設計ミスです。
そこからが3ヶ月間の改善記録。VPCエンドポイントとCloudFrontの組み合わせで、月80万円のコストをどう削減したか、正直に書きます。
VPCエンドポイント導入で気づいた「ただし落とし穴」
まず最初に触ったのがVPCエンドポイント。AWS公式では「データ転送コストを削減できる」と謳われてるんですが、実装の詳細がめちゃくちゃ重要なんですよね。
うちのアーキテクチャを簡単に説明すると、VPC内のECSタスクがS3とDynamoDB、それからSQSをガンガン使ってます。これらが全部インターネットゲートウェイを経由してたんです。
graph TB
subgraph VPC["VPC (10.0.0.0/16)"]
subgraph AZ1["AZ-1a"]
EC2["ECS Task"]
ENI["ENI"]
end
subgraph AZ2["AZ-1b"]
EC2_2["ECS Task"]
ENI_2["ENI"]
end
IGW["Internet Gateway"]
VPCE_S3["VPC Endpoint<br/>S3"]
VPCE_DDB["VPC Endpoint<br/>DynamoDB"]
VPCE_SQS["VPC Endpoint<br/>SQS"]
end
S3["S3"]
DDB["DynamoDB"]
SQS["SQS"]
NATGW["NAT Gateway"]
EC2 -->|Before: IGW経由| IGW
EC2_2 -->|Before: IGW経由| IGW
IGW --> NATGW
NATGW -->|¥0.032/GB| S3
NATGW -->|¥0.032/GB| DDB
NATGW -->|¥0.032/GB| SQS
EC2 -->|After: VPC内| VPCE_S3
EC2_2 -->|After: VPC内| VPCE_DDB
VPCE_S3 --> S3
VPCE_DDB --> DDB
VPCE_SQS --> SQS
VPCエンドポイント導入で気づいたことが3つ、あります:
1. ゲートウェイ型 vs インターフェース型の選定を間違える
S3とDynamoDBはゲートウェイ型を使うと無料。一方、SQS、SNS、SecretsManagerはインターフェース型で、1つあたり月8ドル弱かかります。うちはSQSをインターフェース型で実装してて、月数千円無駄にしてました。
2. ルートテーブルの設定がマジで重要
プライベートサブネットのルートテーブル設定を間違えると、VPCエンドポイント経由じゃなくてNAT Gatewayに流れちゃいます。こんな感じに設定する必要があります:
10.0.0.0/16 → Local
s3.ap-northeast-1.amazonaws.com → vpce-xxxxx(S3ゲートウェイエンドポイント)
dynamodb.ap-northeast-1.amazonaws.com → vpce-yyyyy(DDBゲートウェイエンドポイント)
3. セキュリティグループの設定忘れ
インターフェース型VPCエンドポイントに対して、ENIのセキュリティグループ設定が必要です。ECSタスクから443でインターフェースエンドポイントにアクセスできるようにしないと、タイムアウトして地獄に……。
最初の2週間で月20万円削減できましたが、正直「これで足りるのか?」という疑問がずっとありました。
CloudFront導入で気づいた、もう1つのコスト層
VPCエンドポイントだけでは足りなかった理由は、複数のEC2インスタンスから同じS3オブジェクトに繰り返しアクセスしてたからです。
うちのシステムでは、機械学習モデルファイル(合計5GB)をS3に保存しててですね、起動時に100個のコンテナが同時にダウンロード。これが毎日30回起動するから、1日150GB。月4500GB。料金は月14万円です。
これをCloudFrontでキャッシュすることにしました。ここで重要なのは、CloudFrontをS3オリジンで使うときのコスト構造を理解することなんですよ。
| 項目 | 費用 |
|---|---|
| CloudFront → S3データ転送 | $0.020/GB |
| クライアント → CloudFront | $0.085/GB |
| S3リクエスト(PUT/POST) | $0.0007/10000 |
| S3リクエスト(GET/SELECT) | $0.0007/10000 |
正直、CloudFront導入の判断は悩みました。転送料金自体は下がらないんです。でも、繰り返しアクセスがキャッシュされることで、S3から同じデータを何度も読み込むコストが消える。
うちの場合、キャッシュヒット率が94%になりました。つまり、月4500GB → 月270GB(6%のみS3から読み込み)。削減量は月4230GB × $0.020 = 月85ドル。日本リージョンは料金が高いので実際は月3000円程度。しょぼいじゃん…と思いましたが、複合効果を見ると違いました。
組み合わせの力:VPCエンドポイント×CloudFront×キャッシュ戦略
こっからが本番です。単体では効かないVPCエンドポイントとCloudFrontを、キャッシュ戦略と組み合わせることで初めて効いてきたんですよ。
graph TB
subgraph VPC["VPC (内部トラフィック)"]
ECS1["ECS Task 1<br/>データ取得"]
ECS2["ECS Task 2<br/>データ取得"]
ECS3["ECS Task 3<br/>処理"]
VPCE_S3["S3 VPC Endpoint<br/>無料"]
VPCE_CF["CloudFront VPC Endpoint<br/>無料"]
end
subgraph AWS["AWSネットワーク"]
CF["CloudFront Edge<br/>$0.085/GB"]
S3["S3<br/>$0.023/GB"]
end
External["外部システム<br/>REST API"]
ECS1 -->|キャッシュキー| VPCE_CF
ECS2 -->|同じデータ| VPCE_CF
ECS3 -->|静的ファイル| VPCE_CF
VPCE_CF -->|Cache Hit 94%| CF
CF -->|キャッシュ命中時<br/>S3へのアクセス無し| CF
CF -->|キャッシュミス6%| S3
External -->|HTTP GET| CF
CF -->|キャッシュされたレスポンス| External
重要だったのは、CloudFrontのキャッシュキー設定です。デフォルトだと、CloudFrontはHostヘッダーとパスだけを見てキャッシュするんです。でも、うちの場合Authorizationヘッダーも含まれてて、ユーザーごとに違う結果がキャッシュされてた。これは大問題ですよ。
修正したキャッシュポリシーがこちら:
{
"Name": "CustomCachePolicy",
"Comment": "VPC/S3最適化キャッシュ",
"DefaultTTL": 86400,
"MaxTTL": 2592000,
"MinTTL": 1,
"ParametersInCacheKeyAndForwardedToOrigin": {
"QueryStringsConfig": {
"QueryStringBehavior": "whitelist",
"QueryStrings": ["version", "model_id"]
},
"HeadersConfig": {
"HeaderBehavior": "none"
},
"CookiesConfig": {
"CookieBehavior": "none"
},
"EnableAcceptEncodingGzip": true,
"EnableAcceptEncodingBrotli": true
}
}
このポリシーで実装したのは以下の工夫です:
Authorizationヘッダーはキャッシュキーに含めない(フォワードだけ)model_idなどの重要なパラメータのみキャッシュキーに含める- Gzip・Brotliの圧縮対応で、さらに転送量が40%削減
結果、キャッシュヒット率が60% → 94%に跳ね上がりました。
コスト削減の内訳:月80万円がどこに消えたか
xychart-beta
title "月別データ転送コスト推移"
x-axis [6月, 7月, 8月, 9月, 10月]
y-axis "月額コスト(万円)" 0 --> 100
line [80, 65, 45, 28, 12] title "実績"
内訳をしっかり見てみましょう。
6月(導入前):月80万円
- NAT Gateway経由S3転送:月45万円
- NAT Gateway経由DynamoDB:月20万円
- NAT Gateway経由その他:月15万円
7月(VPCエンドポイント導入):月65万円
- VPCエンドポイント導入でNAT Gateway転送が月30万円削減
- ただし、新しい課題が見えてくる
8月(CloudFront導入開始):月45万円
- CloudFrontのキャッシュ効果で、S3転送が月20万円削減
- CloudFront自体の料金は月8万円(オリジン取得)
9月~10月(キャッシュ最適化):月12万円
- キャッシュヒット率が94%に安定
- 残りの12万円は、キャッシュ不可のリアルタイムデータ転送
最終削減額:月68万円(削減率85%)
正直、ここまで削減できるとは思ってなかった。ただし、カラクリは以下の通りです:
- VPCエンドポイント導入だけなら月20万円程度の削減
- CloudFrontキャッシュ戦略と組み合わせて月68万円
- キャッシュヒット率が9割超えるのが絶対条件
運用で気づいた落とし穴と対策
1. CloudFront キャッシュ無効化の地獄
モデルを更新したとき、CloudFrontのキャッシュが古いままで、新モデルが配信されない問題が発生しました。初期のTTLを24時間に設定してたんですが、本番では待てない。困った。
対策は、バージョニングで対応することにしました:
# S3: model_v1.bin → model_v2.bin
# CloudFront: キャッシュキーに version パラメータを含める
# リクエスト: https://cdn.example.com/model.bin?version=2
こうすることで、URLが変わるから自動でキャッシュ無効化される。CloudFrontの無効化APIを呼ぶ代わりに、パラメータベースで対応できます。
2. VPCエンドポイント経由で予期しないレイテンシ
VPCエンドポイント経由だと、通常のS3アクセスより遅いことがあります。これはVPC内のネットワーク経路の問題なんですよね。
チームで測定した結果がこちら:
| 経路 | 平均レイテンシ |
|---|---|
| NAT Gateway経由(旧) | 150ms |
| VPCエンドポイント経由(新) | 120ms |
| CloudFront経由(キャッシュ) | 40ms |
実は新しい方が遅くなるケースもあるんですが、キャッシュ効果でそれをカバーできました。
3. コスト監視の仕組み化
削減したコストがまた膨らまないように、Cost Anomaly Detectionとカスタムアラームを実装しました。こんな感じです:
# CloudWatch メトリクス
DataTransferOut-VPCE: < 10GB/day → 異常
CloudFrontOriginLatency: > 500ms → 異常
CloudFrontCacheHitRate: < 80% → 要調査
まとめ
この3ヶ月で学んだデータ転送コスト削減の現実、ですね。
VPCエンドポイントだけでは不十分
S3/DynamoDB間の転送を止めるだけで、繰り返しアクセスには効きません。
CloudFrontのキャッシュ戦略が本丸
キャッシュヒット率が9割超えると削減効果は劇的です。キャッシュキー設計がすべてを決めるんですよ。
組み合わせの力を過小評価していた
単体施策は月20〜30万円削減。組み合わせると月68万円削減。AWS設計は「足し算」じゃなく「かけ算」なんだなと気づきました。
コスト監視の自動化は必須
一度削減しても、システム変更で膨れ上がります。CloudWatch・Cost Anomaly Detection で常時監視することが大事です。
次のアクション:同じパターンのシステムが他チームにもあるはず。このノウハウを展開して、会社全体で月200万円程度の削減を狙ってます。