AWS CloudFrontとS3でグローバルCDN配信を設計する方法|オリジンフェイルオーバーとキャッシュ制御入門

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)AWS(Amazon Linux) > AWS CloudFrontとS3でグローバルCDN配信を設計する方法|オリジンフェイルオーバーとキャッシュ制御入門
「CloudFrontの設定をどこから始めればいいか分からない」「S3で直接公開しているが、障害時の自動切り替えができていない」
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を適切に制御する


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

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" } } }

OACのIDが払い出されたら、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"

※インバリデーションは毎月1,000パスまで無料です。頻繁なコンテンツ更新がある場合は、S3のバージョニングとファイル名にバージョン文字列を付加するキャッシュバスティング(例: 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"} ] } }

フェイルオーバー条件に指定できる代表的なHTTPステータスコードは次のとおりです。
ステータスコード 意味 フェイルオーバー推奨
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
404 Not Found △(コンテンツ不在との区別が難しいため要注意)
※オリジングループを使ったフェイルオーバーは冗長設計の入口です。より高度なマルチリージョン・マルチAZ構成についてはAWSクラウド実践セミナーで体系的に学べます。

セキュリティ設計(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-SecurityX-Frame-OptionsX-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"

DNS検証ではACMが指定するCNAMEレコードをDNSに追加する必要があります。Route 53を使っている場合はACMコンソールから「Route 53でレコードを作成」ボタンで自動追加できます。LinuxサーバーのDNS設定についてはLinuxのDNS設定方法(resolv.confとnmcliの手順)も参考にしてください。

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レコード追加
CloudFrontは「とりあえずキャッシュを入れる」だけのツールではなく、OAC・オリジンフェイルオーバー・WAF・ACMと組み合わせることで、セキュアで高可用性なCDN配信基盤を構築できます。設計の全体像が見えたところで、次は実際の構成をハンズオンで体験することをおすすめします。

現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、Amazon LinuxとAWSを実務レベルで学べる無料マニュアルをご用意しています。AWSの設定を現場で自在に扱えるエンジニアになるために、まずは無料マニュアルをお受け取りください。

>> 無料マニュアルを受け取る

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。