月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%)

正直、ここまで削減できるとは思ってなかった。ただし、カラクリは以下の通りです:

  1. VPCエンドポイント導入だけなら月20万円程度の削減
  2. CloudFrontキャッシュ戦略と組み合わせて月68万円
  3. キャッシュヒット率が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万円程度の削減を狙ってます。

U

Untanbaby

ソフトウェアエンジニア|AWS / クラウドアーキテクチャ / DevOps

10年以上のIT実務経験をもとに、現場で使える技術情報を発信しています。 記事の誤りや改善点があればお問い合わせからお気軽にご連絡ください。

関連記事