AWS CloudFrontを使ったCDN設計は、単に「コンテンツをキャッシュする」だけではありません。オリジンフェイルオーバー・キャッシュポリシー・セキュリティ設定の設計次第で、可用性とパフォーマンスが大きく変わります。
この記事では、CloudFrontとS3を組み合わせたCDN配信設計の実践手順を、ディストリビューション作成からオリジンフェイルオーバー・キャッシュ制御・OACセキュリティ設定・ACM証明書まで一通り解説します。
動作確認環境: Amazon Linux 2023 + AWS CLI v2(2.17.x)・東京リージョン(ap-northeast-1)
この記事のポイント
・CloudFrontはエッジロケーションでキャッシュしてレイテンシを削減するCDNサービスです
・S3オリジンにはOAC(Origin Access Control)を使い、S3直接アクセスを必ず遮断する
・オリジングループで5xxエラー時にセカンダリS3へ自動フェイルオーバーさせる
・キャッシュポリシーとCache-Controlヘッダーを組み合わせてTTLを適切に制御する
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
CloudFrontとはなにか(CDNとエッジロケーションの仕組み)
CloudFrontはAWSが提供するCDN(Content Delivery Network)サービスです。世界100カ国以上・450超のエッジロケーション(PoP: Point of Presence)にコンテンツをキャッシュし、ユーザーの最寄りのエッジから配信することでレイテンシを大幅に削減します。コンテンツが返されるまでの流れは次のとおりです。
・ユーザーがコンテンツをリクエストする
・Route 53などのDNSがユーザーの位置情報をもとに最寄りエッジロケーションのIPを返す
・エッジにキャッシュが存在する場合はそのまま返す(キャッシュヒット)
・キャッシュがない場合はオリジン(S3・ALBなど)から取得してキャッシュに保存した上で返す(キャッシュミス)
CloudFrontを採用する主な理由は以下の4点です。
・グローバルなレイテンシ削減: ユーザーが日本にいる場合、米国のS3バケットから直接取得するより、東京エッジのキャッシュから取得するほうが応答時間が圧倒的に短い
・オリジン負荷軽減: キャッシュヒット率が高いほどオリジンへのリクエスト数が減り、EC2やRDSへの負荷が下がる
・DDoS保護: CloudFrontはデフォルトでAWS Shield Standardが有効になっており、L3・L4の一般的な攻撃を緩和する
・HTTPS終端の一元管理: ACM証明書をCloudFrontに関連付けるだけで、オリジン側の証明書管理を単純化できる
CloudFrontのディストリビューション作成と基本設定
CloudFrontの設定単位を「ディストリビューション」と呼びます。作成するとCloudFrontドメイン(例: d1234abcdef.cloudfront.net)が払い出され、このドメインでコンテンツにアクセスできるようになります。1. S3バケットの準備
オリジンとなるS3バケットを作成します。このバケットは公開設定をオフにし、CloudFront経由のみでアクセスできるようにします(OAC設定の前提条件です)。# create S3 bucket in ap-northeast-1 region $ aws s3 mb s3://my-web-content-20261001 --region ap-northeast-1 # パブリックアクセスブロックを有効化(S3直接アクセスを禁止する) $ aws s3api put-public-access-block --bucket my-web-content-20261001 --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
2. OAC(Origin Access Control)の作成
S3オリジンには必ずOAC(Origin Access Control)を使います。以前はOAI(Origin Access Identity)が標準でしたが、2022年以降はOACが推奨に変わっています。OACを使うとS3バケットポリシーで「CloudFrontのディストリビューションからのGetObjectのみ許可」という設定が可能になり、S3の直接URL(https://bucket.s3.amazonaws.com/...)へのアクセスを完全に遮断できます。鉄則: OACなしのS3オリジン設定は、バケットポリシーを緩めざるを得ず、直接アクセスが漏れるリスクがある。新規設定では必ずOACを使うこと。
# OACを作成する $ aws cloudfront create-origin-access-control --origin-access-control-config "Name=my-oac,Description=OAC for S3,SigningProtocol=sigv4,SigningBehavior=always,OriginAccessControlOriginType=s3" # 実機出力(IDをメモしておく) { "Location": "https://cloudfront.amazonaws.com/2020-05-31/origin-access-control/E3OACXMPL123", "ETag": "E2QWRUH2EXAMPLE", "OriginAccessControl": { "Id": "E3OACXMPL123", "OriginAccessControlConfig": { "Name": "my-oac", "Description": "OAC for S3", "SigningProtocol": "sigv4", "SigningBehavior": "always", "OriginAccessControlOriginType": "s3" } } }
012345678901はAWSアカウントID、E2QW9XMPL123は後で払い出されるディストリビューションIDに置き換えてください。# S3バケットポリシー(policy.json) { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::my-web-content-20261001/*", "Condition": { "StringEquals": { "aws:SourceArn": "arn:aws:cloudfront::012345678901:distribution/E2QW9XMPL123" } } } ] } $ aws s3api put-bucket-policy --bucket my-web-content-20261001 --policy file://policy.json
3. ディストリビューションの作成と確認
# 簡易作成(デフォルト設定で即時作成したい場合) $ aws cloudfront create-distribution --origin-domain-name my-web-content-20261001.s3.ap-northeast-1.amazonaws.com --default-root-object index.html # 実機出力(抜粋) { "Location": "https://cloudfront.amazonaws.com/2020-05-31/distribution/E2QW9XMPL123", "Distribution": { "Id": "E2QW9XMPL123", "ARN": "arn:aws:cloudfront::012345678901:distribution/E2QW9XMPL123", "Status": "InProgress", "DomainName": "d1a2b3c4d5ef6.cloudfront.net" } } # Deployed になるまで数分かかる(進行状況を確認) $ aws cloudfront get-distribution --id E2QW9XMPL123 --query "Distribution.Status" --output text Deployed
Status: Deployed になったら、払い出されたドメイン(d1a2b3c4d5ef6.cloudfront.net)でコンテンツにアクセスできます。キャッシュ制御の設計(TTL・Cache-Control・キャッシュポリシー)
キャッシュの設計を誤ると「コンテンツを更新したのにキャッシュが残って古い情報が返される」「動的コンテンツまでキャッシュされてログイン状態がおかしくなる」といったトラブルが起きます。1. マネージドキャッシュポリシーの選択
CloudFrontはAWS管理のキャッシュポリシーをデフォルトで用意しています。コンテンツの種類に応じて使い分けます。| ポリシー名 | デフォルトTTL | 用途 |
|---|---|---|
| CachingOptimized | 86400秒(1日) | 画像・CSS・JSなどの静的コンテンツ |
| CachingDisabled | 0秒(無効) | APIエンドポイント・動的コンテンツ |
| CachingOptimizedForUncompressedObjects | 86400秒(1日) | gzip圧縮不要な静的コンテンツ |
2. Cache-Controlヘッダーとの関係
オリジン(S3)がCache-Control ヘッダーを返す場合、そのヘッダーが優先されます(キャッシュポリシーのTTL範囲内で)。・オリジンが
Cache-Control: max-age=3600 を返す → キャッシュポリシーの最大TTL以内であれば1時間キャッシュされる・オリジンが
Cache-Control: no-cache を返す → キャッシュしない(CachingDisabledポリシーと組み合わせること)・S3にアップロードするオブジェクトにヘッダーを設定する場合:
aws s3 cp file.html s3://bucket/ --cache-control "max-age=86400"3. キャッシュインバリデーションで即時更新
コンテンツを更新した直後にキャッシュを即座に反映させたい場合はインバリデーション(無効化)を実行します。# 全コンテンツのキャッシュを削除(/* はすべてのパスを対象にする) $ aws cloudfront create-invalidation --distribution-id E2QW9XMPL123 --paths "/*" # 実機出力 { "Invalidation": { "Id": "I3INVALIDXMPL1", "Status": "InProgress", "CreateTime": "2026-10-01T10:23:45.000Z", "InvalidationBatch": { "Paths": { "Quantity": 1, "Items": ["/*"] } } } } # 特定パスだけ削除する場合 $ aws cloudfront create-invalidation --distribution-id E2QW9XMPL123 --paths "/images/*" "/index.html"
main.v20261001.js)で対応するほうが効率的です。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、Amazon LinuxとAWSを実務レベルで学べる無料マニュアルをご用意しています。
>> 無料マニュアルを受け取るオリジンフェイルオーバーで障害を自動回避する
オリジンのS3バケットが何らかの理由で5xxエラーや接続タイムアウトを返した場合、CloudFrontのオリジングループ(Origin Group)機能を使うとセカンダリオリジンに自動でフェイルオーバーさせることができます。1. セカンダリS3バケットの準備(クロスリージョンレプリケーション)
フェイルオーバーが正しく機能するには、セカンダリオリジンのS3バケットに同じコンテンツが存在する必要があります。S3のクロスリージョンレプリケーションを使ってプライマリバケットの内容をセカンダリに自動同期します。・プライマリ:
my-web-content-20261001(ap-northeast-1: 東京)・セカンダリ:
my-web-content-20261001-dr(ap-northeast-3: 大阪)# セカンダリバケットを大阪リージョンに作成 $ aws s3 mb s3://my-web-content-20261001-dr --region ap-northeast-3 # プライマリバケットでバージョニングを有効化(レプリケーションに必須) $ aws s3api put-bucket-versioning --bucket my-web-content-20261001 --versioning-configuration Status=Enabled # セカンダリバケットでもバージョニングを有効化 $ aws s3api put-bucket-versioning --bucket my-web-content-20261001-dr --versioning-configuration Status=Enabled # レプリケーション設定を適用(replication.jsonを用意してから実行) $ aws s3api put-bucket-replication --bucket my-web-content-20261001 --replication-configuration file://replication.json
2. オリジングループの設定
プライマリとセカンダリの2つのオリジンを定義したオリジングループを作成します。フェイルオーバーをトリガーするHTTPステータスコードを指定できます。# オリジングループの設定例(JSON) # フェイルオーバー条件: 500・502・503 の場合にセカンダリへ切り替え { "Id": "my-origin-group", "FailoverCriteria": { "StatusCodes": { "Quantity": 3, "Items": [500, 502, 503] } }, "Members": { "Quantity": 2, "Items": [ {"OriginId": "primary-s3-ap-northeast-1"}, {"OriginId": "secondary-s3-ap-northeast-3"} ] } }
| ステータスコード | 意味 | フェイルオーバー推奨 |
|---|---|---|
| 500 | Internal Server Error | ○ |
| 502 | Bad Gateway | ○ |
| 503 | Service Unavailable | ○ |
| 504 | Gateway Timeout | ○ |
| 404 | Not Found | △(コンテンツ不在との区別が難しいため要注意) |
セキュリティ設計(HTTPS強制・WAF連携・レスポンスヘッダー)
1. HTTPS強制(Viewer Protocol Policy)
ユーザーからCloudFrontへの通信(ビューワーリクエスト)に対し、HTTPSのみを許可する設定です。| 設定値 | 動作 |
|---|---|
| allow-all | HTTP・HTTPSどちらも許可(本番環境では禁止) |
| redirect-to-https | HTTPアクセスをHTTPSに301リダイレクト(推奨) |
| https-only | HTTPアクセスを403で拒否 |
# 現在の設定を確認する $ aws cloudfront get-distribution --id E2QW9XMPL123 --query "Distribution.DistributionConfig.DefaultCacheBehavior.ViewerProtocolPolicy" --output text redirect-to-https
2. AWS WAF連携
AWS WAF(Web Application Firewall)をCloudFrontに関連付けると、SQLインジェクション・XSS・IP制限などの防御をエッジロケーションで処理できます。注意: CloudFrontに関連付けるWAFのWebACLは必ずus-east-1(バージニア北部)リージョンで作成してください。 東京リージョン(ap-northeast-1)で作成したWebACLはCloudFrontに関連付けられません。WAFとCloudFrontの連携で最も多いミスがこのリージョン間違いです。
# WebACL を us-east-1 で作成(scope=CLOUDFRONT が必須) $ aws wafv2 create-web-acl --name my-cloudfront-waf --scope CLOUDFRONT --default-action Allow={} --visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=my-cloudfront-waf --rules file://waf-rules.json --region us-east-1
3. セキュリティレスポンスヘッダーポリシー
CloudFrontのレスポンスヘッダーポリシーを使うと、Strict-Transport-Security・X-Frame-Options・X-Content-Type-Optionsなどのセキュリティヘッダーをエッジで自動付与できます。オリジン(S3・EC2など)を変更せずにヘッダーを追加できるため、セキュリティ要件の変更に柔軟に対応できます。AWSのマネージドポリシーに SecurityHeadersPolicy(HSTS・XFO・XCTOを一括設定)が用意されているため、まずこれを使うことをおすすめします。
CloudFront設定でよくあるトラブルと対処法
実際の運用でよく遭遇するエラーと対処方法をまとめます。1. 503 Service Unavailable が返る(OAC設定ミス)
S3へのアクセスが拒否されると503が返ります。最も多い原因はバケットポリシーのSourceArn指定ミスです。・バケットポリシーの
aws:SourceArn に正しいディストリビューションARNが設定されているか確認・ディストリビューションのオリジン設定にOAC IDが紐付いているか確認
・S3バケットのパブリックアクセスブロックが有効になっているか確認(OACと矛盾なし)
# バケットポリシーの現在の設定を確認する $ aws s3api get-bucket-policy --bucket my-web-content-20261001 --query Policy --output text | python3 -m json.tool
2. キャッシュが更新されない
コンテンツをS3に更新したのにCloudFrontが古いキャッシュを返し続ける場合の確認点です。・インバリデーションを実行したか(
aws cloudfront create-invalidation --paths "/*")・オリジンのCache-Controlヘッダーに
max-age が長く設定されていないか・キャッシュポリシーのTTLが長く設定されていないか
3. カスタムドメインで証明書エラーが出る
「証明書が見つからない」「SSL_ERROR_RX_RECORD_TOO_LONG」などが出る場合の確認点です。・ACMの証明書が us-east-1 で発行されているか(他リージョンの証明書はCloudFrontに使用不可)
・ACMの証明書Statusが
ISSUED になっているか(Pending validationのままでは使えない)・ディストリビューションのAlternate Domain Nameにカスタムドメインが正しく設定されているか
カスタムドメインとSSL証明書の設定(ACM・DNS連携)
CloudFrontのデフォルトドメイン(d1a2b3c4d5ef6.cloudfront.net)の代わりに独自ドメインで配信する方法を解説します。1. ACMでSSL証明書を取得する(us-east-1必須)
CloudFrontに使用するSSL証明書は必ず us-east-1(バージニア北部)のACMで発行します。# ACMで証明書を申請(DNS検証推奨・us-east-1を指定する) $ aws acm request-certificate --domain-name www.example.com --validation-method DNS --subject-alternative-names example.com --region us-east-1 # 実機出力 { "CertificateArn": "arn:aws:acm:us-east-1:012345678901:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" } # DNS検証に必要なCNAMEレコードを確認する $ aws acm describe-certificate --certificate-arn arn:aws:acm:us-east-1:012345678901:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --region us-east-1 --query "Certificate.DomainValidationOptions"
2. ディストリビューションにカスタムドメインを設定する
証明書のStatusがISSUED になったら、ディストリビューションのAlternate Domain Name(CNAME)と証明書ARNを設定し、Route 53でAliasレコードを追加します。# Route 53 に Alias A レコードを追加する例(change-batch.json) { "Changes": [{ "Action": "UPSERT", "ResourceRecordSet": { "Name": "www.example.com", "Type": "A", "AliasTarget": { "HostedZoneId": "Z2FDTNDATAQYW2", "DNSName": "d1a2b3c4d5ef6.cloudfront.net", "EvaluateTargetHealth": false } } }] } # HostedZoneId: Z2FDTNDATAQYW2 は CloudFront 固定値 $ aws route53 change-resource-record-sets --hosted-zone-id Z1234EXAMPLE5678 --change-batch file://change-batch.json
本記事のまとめ
AWS CloudFrontとS3を組み合わせたCDN設計の主なポイントを整理します。| やりたいこと | 設定・コマンド |
|---|---|
| S3を非公開にしてCF経由のみ許可 | aws cloudfront create-origin-access-control でOACを作成しS3バケットポリシーに適用 |
| ディストリビューションを作成 | aws cloudfront create-distribution --origin-domain-name |
| キャッシュを即時削除 | aws cloudfront create-invalidation --paths "/*" |
| オリジン障害時に自動フェイルオーバー | オリジングループで5xxをトリガーにセカンダリS3へ切り替え |
| HTTPをHTTPSに強制リダイレクト | ViewerProtocolPolicy: redirect-to-https |
| WAFでSQLi・XSSを防御 | us-east-1でWebACLを作成しディストリビューションに関連付け |
| 独自ドメインでHTTPS配信 | us-east-1のACMで証明書取得 + AlternateDomainName設定 + Route 53 Aliasレコード追加 |
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、Amazon LinuxとAWSを実務レベルで学べる無料マニュアルをご用意しています。AWSの設定を現場で自在に扱えるエンジニアになるために、まずは無料マニュアルをお受け取りください。
>> 無料マニュアルを受け取る3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。
登録無料・いつでも解除できます