サイトアイコンmaita tomoya dev io

AWS CloudFront

devops

AWS CloudFront

CDN(Content Delivery Network)とは

CDNは、世界中に分散配置されたサーバー群(エッジロケーション)を使い、ユーザーに最も近い場所からコンテンツを配信する仕組み。これにより、レイテンシの削減、オリジンサーバーの負荷軽減、大量トラフィックへの耐性向上を実現する。

CDNがない場合とある場合の比較

項目CDNなしCDNあり
コンテンツ配信元オリジンサーバー(1箇所)エッジロケーション(世界中)
ユーザーからの距離遠い場合がある常に最寄り
レイテンシ高い(物理的距離に依存)低い
オリジン負荷全リクエストがオリジンに到達キャッシュヒット分は到達しない
耐障害性SPOFになりやすい分散されている
DDoS耐性低い高い(AWS Shield統合)

CloudFrontとは

Amazon CloudFrontは、AWSが提供するCDNサービス。S3、ALB、EC2、カスタムオリジンなど任意のHTTPサーバーをオリジンとして、グローバルに分散されたエッジロケーションからコンテンツを高速配信する。

CloudFrontの全体像

graph LR U1[ユーザー<br/>東京] --> E1["エッジロケーション<br/>東京"] U2[ユーザー<br/>大阪] --> E2["エッジロケーション<br/>大阪"] U3[ユーザー<br/>ニューヨーク] --> E3["エッジロケーション<br/>ニューヨーク"] E1 --> RC["リージョナルエッジキャッシュ<br/>(中間キャッシュ層)"] E2 --> RC E3 --> RC2["リージョナルエッジキャッシュ<br/>(中間キャッシュ層)"] RC --> O["オリジン<br/>(S3 / ALB / カスタム)"] RC2 --> O

エッジロケーションとPOP

エッジロケーション

CloudFrontのコンテンツをキャッシュし、ユーザーに配信する拠点。世界中に450箇所以上(2025年時点)存在する。

用語説明
エッジロケーションユーザーに最も近いキャッシュサーバー
POP(Point of Presence)エッジロケーションが設置されたデータセンター群
リージョナルエッジキャッシュエッジロケーションとオリジンの間にある中間キャッシュ層

リクエストの流れ

sequenceDiagram participant User as ユーザー participant Edge as エッジロケーション participant REC as リージョナルエッジキャッシュ participant Origin as オリジン User->>Edge: コンテンツリクエスト alt キャッシュヒット(エッジ) Edge->>User: キャッシュからレスポンス else キャッシュミス(エッジ) Edge->>REC: オリジンフェッチ alt キャッシュヒット(リージョナル) REC->>Edge: キャッシュからレスポンス Edge->>User: レスポンス返却 else キャッシュミス(リージョナル) REC->>Origin: オリジンフェッチ Origin->>REC: レスポンス REC->>Edge: レスポンス(キャッシュ保存) Edge->>User: レスポンス返却(キャッシュ保存) end end

日本のエッジロケーション

日本には東京と大阪にエッジロケーションが複数存在する。日本国内のユーザーへの配信は非常に低レイテンシで実現可能。


キャッシュ戦略

TTL(Time to Live)

キャッシュの有効期間を制御するパラメータ。

設定説明デフォルト
Minimum TTLキャッシュの最小有効期間0秒
Maximum TTLキャッシュの最大有効期間31536000秒(1年)
Default TTLオリジンがCache-Controlヘッダーを返さない場合のTTL86400秒(24時間)

Cache-Controlヘッダーとの関係

オリジンが返すCache-Controlヘッダーの値と、CloudFrontのTTL設定の関係:

オリジンのレスポンス: Cache-Control: max-age=3600

CloudFront側の設定:
  Minimum TTL = 60
  Maximum TTL = 86400
  Default TTL = 86400

結果: キャッシュTTL = 3600秒(max-ageがMin〜Maxの範囲内なので採用)
シナリオ結果
max-age < Minimum TTLMinimum TTLが採用
Minimum TTL <= max-age <= Maximum TTLmax-ageが採用
max-age > Maximum TTLMaximum TTLが採用
Cache-ControlヘッダーなしDefault TTLが採用

コンテンツ種別ごとの推奨TTL

コンテンツ種別推奨TTL理由
静的アセット(CSS/JS/画像)1年(31536000秒)ファイル名にハッシュを含めてバージョニング
HTMLページ短め(60〜300秒)頻繁に更新される可能性
APIレスポンス0〜60秒リアルタイム性が求められる
動画・大容量ファイル1日〜1週間更新頻度が低い

キャッシュ無効化(Invalidation)

キャッシュの有効期限前に強制的にキャッシュを削除する操作。

# 特定のファイルを無効化
aws cloudfront create-invalidation \
  --distribution-id E1234567890 \
  --paths "/index.html" "/css/style.css"

# ディレクトリ配下を一括無効化
aws cloudfront create-invalidation \
  --distribution-id E1234567890 \
  --paths "/images/*"

# 全キャッシュの無効化(非推奨:コスト大)
aws cloudfront create-invalidation \
  --distribution-id E1234567890 \
  --paths "/*"

Invalidationの注意点:

  • 月間1,000パスまでは無料。超過分は1パスあたり$0.005
  • /*は1パスとしてカウントされる
  • 全エッジロケーションへの反映には数分〜十数分かかる
  • 頻繁なInvalidationよりもファイル名バージョニング(例: style.abc123.css)を推奨

キャッシュキー

CloudFrontがキャッシュを一意に識別するためのキー。デフォルトではURLパスだが、以下をキャッシュキーに含めるよう設定可能。

キャッシュキー要素説明
URLパスデフォルトで含まれる/images/logo.png
クエリ文字列指定したパラメータのみ含める推奨?size=large&format=webp
ヘッダーAccept-Encoding等を含められるgzip/brotli分岐
Cookie指定したCookieのみ含める推奨セッションID等

ベストプラクティス: キャッシュキーに含める要素は最小限にする。含める要素が多いほどキャッシュヒット率が下がる。


オリジン

オリジンの種類

オリジンの種類説明ユースケース
S3バケット静的ファイルの配信静的Webサイト、画像、CSS/JS
ALB / ELB動的コンテンツの配信Webアプリケーション、API
EC2直接EC2インスタンスから配信カスタムWebサーバー
MediaStore / MediaPackageメディアコンテンツ動画ストリーミング
カスタムオリジン任意のHTTPサーバーオンプレミスサーバー、他社CDN

S3オリジンの設定

S3をオリジンとして使用する場合、2つの方式がある。

方式説明推奨
OAC(Origin Access Control)新しい方式。S3へのアクセスをCloudFrontのみに制限推奨
OAI(Origin Access Identity)旧方式。レガシー非推奨

オリジングループ(フェイルオーバー)

プライマリオリジンが障害の際にセカンダリオリジンへ自動フェイルオーバーする機能。

CloudFront → オリジングループ
              ├── プライマリ: S3バケット(東京リージョン)
              └── セカンダリ: S3バケット(大阪リージョン)

プライマリが5xx/4xxを返した場合 → 自動でセカンダリにフェイルオーバー

OAC(Origin Access Control)

OACとは

CloudFrontディストリビューションからのみS3バケットへのアクセスを許可する仕組み。S3バケットのURLを直接叩いてもアクセスできないようにする。

OACの設定手順

  1. CloudFrontディストリビューションのオリジン設定でOACを作成
  2. S3バケットポリシーにCloudFrontからのアクセスを許可する記述を追加

S3バケットポリシーの例:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontServicePrincipal",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1234567890"
        }
      }
    }
  ]
}

OAC vs OAI

項目OAC(推奨)OAI(レガシー)
SSE-KMS対応対応非対応
S3バケットポリシー標準的なIAMポリシー特殊なCanonicalUser記法
リージョン制限なし一部リージョンで非対応
署名バージョンSigV4SigV2/SigV4

Lambda@Edge と CloudFront Functions

概要

CloudFrontのエッジでコードを実行する機能。リクエスト/レスポンスの加工、認証、リダイレクト、A/Bテストなどを実現する。

Lambda@Edge vs CloudFront Functions

項目CloudFront FunctionsLambda@Edge
実行場所エッジロケーション(218+箇所)リージョナルエッジキャッシュ(13箇所)
対応イベントViewer Request / Viewer Response4つ全て
ランタイムJavaScript (ECMAScript 5.1)Node.js, Python
最大実行時間1ミリ秒5秒(Viewer)/ 30秒(Origin)
最大メモリ2MB128〜10,240MB
ネットワークアクセス不可可能
リクエストボディアクセス不可可能
料金非常に安価Lambda@Edgeの料金
用途軽量な変換、ヘッダー操作複雑な処理、外部API呼び出し

イベントトリガーのタイミング

graph LR U[ユーザー] -->|1. Viewer Request| CF["CloudFront<br/>エッジ"] CF -->|2. Origin Request| O[オリジン] O -->|3. Origin Response| CF CF -->|4. Viewer Response| U style CF fill:#f9f,stroke:#333
イベント説明ユースケース
Viewer Requestユーザーからのリクエスト受信時URL書き換え、認証、リダイレクト
Origin Requestオリジンへのリクエスト送信前オリジン選択、ヘッダー追加
Origin Responseオリジンからのレスポンス受信後レスポンスヘッダー追加、エラーページカスタマイズ
Viewer Responseユーザーへのレスポンス送信前セキュリティヘッダー追加

CloudFront Functionsの例

URLリライト(SPAのルーティング対応):

function handler(event) {
  var request = event.request;
  var uri = request.uri;

  // 拡張子のないパスは index.html にリライト
  if (!uri.includes('.')) {
    request.uri = '/index.html';
  }

  return request;
}

セキュリティヘッダーの追加:

function handler(event) {
  var response = event.response;
  var headers = response.headers;

  headers['strict-transport-security'] = {
    value: 'max-age=63072000; includeSubdomains; preload'
  };
  headers['x-content-type-options'] = { value: 'nosniff' };
  headers['x-frame-options'] = { value: 'DENY' };
  headers['x-xss-protection'] = { value: '1; mode=block' };
  headers['content-security-policy'] = {
    value: "default-src 'self'; script-src 'self'"
  };

  return response;
}

Lambda@Edgeの例

Basic認証:

export const handler = async (event) => {
  const request = event.Records[0].cf.request;
  const headers = request.headers;

  const authUser = 'admin';
  const authPass = 'password123';
  const authString = 'Basic ' + Buffer.from(authUser + ':' + authPass).toString('base64');

  if (
    !headers.authorization ||
    headers.authorization[0].value !== authString
  ) {
    return {
      status: '401',
      statusDescription: 'Unauthorized',
      headers: {
        'www-authenticate': [{ value: 'Basic realm="Restricted"' }],
      },
      body: 'Unauthorized',
    };
  }

  return request;
};

SSL/TLS

カスタムドメインでのHTTPS

CloudFrontでカスタムドメインを使用する場合、SSL/TLS証明書が必要。

方式説明費用
ACM証明書AWS Certificate Managerで発行(us-east-1リージョン必須無料
カスタム証明書IAMにアップロードした証明書証明書の購入費用
デフォルト証明書*.cloudfront.netのワイルドカード証明書無料

重要: CloudFrontで使用するACM証明書は、必ず**us-east-1(バージニア北部)**リージョンで発行する必要がある。

TLSバージョン

設定説明
TLSv1.2_2021(推奨)TLS 1.2以上を要求。最もセキュア
TLSv1.2_2019TLS 1.2以上。古いクライアントも一部対応
TLSv1.1_2016TLS 1.1以上。レガシー互換
SSLv3(非推奨)セキュリティ上の問題あり

SNI(Server Name Indication)

方式説明費用
SNI大半のブラウザが対応無料
専用IPSNI非対応の古いクライアント向け$600/月

WAF連携

AWS WAFとの統合

CloudFrontにAWS WAF(Web Application Firewall)のWeb ACLを関連付けることで、不正なリクエストをエッジで遮断できる。

WAFルールの種類説明
マネージドルールAWSやサードパーティが提供する定義済みルールSQLインジェクション、XSS防御
レートベースルール一定期間内のリクエスト数で制限IPあたり5分間に1000リクエスト
IPセットルール特定IPのブロック/許可社内IPのみ許可
Geo matchルール国や地域でブロック/許可日本からのアクセスのみ許可

AWS Shield

CloudFrontには自動的にAWS Shield Standardが適用され、一般的なDDoS攻撃(L3/L4)から保護される。Shield Advancedを有効にすると、より高度なDDoS防御とDDoSレスポンスチームのサポートが利用可能。


実務での構成パターン

パターン1: 静的Webサイトホスティング

Route 53 → CloudFront → S3(OAC)
              ↓
          ACM証明書(us-east-1)
          CloudFront Functions(URLリライト)
  • S3のウェブサイトホスティングではなくCloudFront経由で配信
  • OACでS3への直接アクセスを防止
  • CloudFront FunctionsでSPAのルーティング対応

パターン2: 動的Webアプリケーション

Route 53 → CloudFront → /api/*   → ALB → ECS
                       → /static/* → S3(OAC)
                       → /*        → S3(OAC)
              ↓
          WAF Web ACL
          ACM証明書
  • Behavior(キャッシュ動作)でパスパターン別にオリジンを振り分け
  • API通信はキャッシュなし(TTL=0)でALBに転送
  • 静的アセットはS3から長期キャッシュで配信

パターン3: マルチオリジン + フェイルオーバー

CloudFront → オリジングループ
              ├── プライマリ: ALB(東京リージョン)
              └── セカンダリ: ALB(大阪リージョン)
  • プライマリオリジンが5xxを返した場合に自動フェイルオーバー
  • リージョン障害時のDR対策

料金

課金の構成要素

項目説明
データ転送(エッジ→インターネット)配信したデータ量に応じて課金。リージョンごとに単価が異なる
HTTPリクエスト数HTTP: $0.0090/10,000リクエスト、HTTPS: $0.0120/10,000リクエスト(日本)
Invalidationリクエスト月間1,000パスまで無料。超過分$0.005/パス
Lambda@Edgeリクエスト数 + 実行時間
CloudFront Functions$0.10/100万呼び出し
オリジンへのデータ転送CloudFront → オリジンは無料

コスト最適化のポイント

方法効果
キャッシュヒット率を上げるオリジンフェッチ回数とデータ転送量を削減
圧縮(gzip/Brotli)を有効化転送データ量を50〜80%削減
CloudFront Security Savings Bundle1年コミットで最大30%割引
不要なInvalidationを減らすファイル名バージョニングで対応
Price Classの設定使用するエッジロケーションを限定(例: 日本・米国のみ)

Price Class

Price Class対象リージョンコスト
Price Class All全エッジロケーション最高
Price Class 200主要リージョン(南米・オーストラリア除く)
Price Class 100北米・ヨーロッパのみ最低

日本をターゲットにする場合は Price Class 200 以上が必要。


CloudFrontの設定項目まとめ

ディストリビューション設定

項目説明
Price Class使用するエッジロケーションの範囲
WAF Web ACL関連付けるWAFルール
代替ドメイン名(CNAME)カスタムドメイン
SSL証明書ACMまたはカスタム証明書
デフォルトルートオブジェクト/アクセス時に返すファイル(例: index.html
ログ記録S3にアクセスログを保存
IPv6IPv6の有効/無効

Behavior(キャッシュ動作)設定

項目説明
パスパターン対象のURLパス(例: /api/*, *.jpg
オリジンリクエストを転送するオリジン
ビューワープロトコルポリシーHTTP/HTTPS/Redirect HTTP to HTTPS
キャッシュポリシーTTL、キャッシュキー(ヘッダー、クエリ文字列、Cookie)
オリジンリクエストポリシーオリジンに転送するヘッダー等
レスポンスヘッダーポリシーセキュリティヘッダー等の追加
関数の関連付けCloudFront Functions / Lambda@Edge

参考文献