[CloudFront]複数のS3バケットをオリジンとする場合のTips

に公開

やりたいこと

静的WEBサイトをS3でホスティング、https://ドメイン名/aaaのパスごとに、別のS3バケットに振り分けたい。

URL S3バケット
https://mydomain/* S3バケット①
https://mydomain/aaa/* S3バケット②
https://mydomain/aaa/bbb/* S3バケット③

実装・ハマったこと

基本的なS3 + CloudFront構成の実装方法は省略。
CloudFrontのビヘイビアの設定で、下記の通り実装します。

URL S3バケット ビヘイビアのパスパターンの設定 優先度
https://mydomain/* S3バケット① デフォルト(*) 2
https://mydomain/aaa/* S3バケット② /aaa/* 1
https://mydomain/aaa/bbb/* S3バケット③ /aaa/bbb/* 0

ちなみに今回のように、パスパターンが重複する可能性がある場合(例えば/aaa/bbbというパスはどのパターンにも当てはまりますね?)は注意が必要です。
この場合、より具体的なパスパターンの優先度を上げる(0に近くする)必要があります。

例えば/aaa/*を/aaa/bbb/*より優先度を上げて設定してしまうと、
/aaa/bbb/*のURLは全て/aaa/*の方へ吸収されてしまいます。

一方/*のバケットに/aaa/*の階層と/aaa/*にはないファイルを用意しておき、意図せず/*のバケットの/aaa/*階層のファイルが表示されてしまわないか確認しましたが、/aaa/*ルールにないからといって、/*のバケットに合致するファイルがないか探しにいくようなことはいようでした。

Route53のエイリアスでCloudFrontディストリビューションが表示されない。

ALBやCloudFront等AWSのサービスをRoute53でAレコードに設定する場合、
通常グローバルIPを指定するところ、
AWSでは下記の通りエイリアスを選択して、レコードを選択できるようになっています。

CloudFrontのディストリビューション作成直後、
作成したはずのディストリビューションが表示されず、
時差的なものかと思いしばらく待ってしまいましたが、
ディストリビューション作成時に、下記のAlternative domain nameにAレコード指定予定のドメインを指定する必要があったようです。設定から修正したところ、無事Route53から設定できるようになりました。

WEBから接続時にAccessDeniedが表示されてしまう。

あらためて設定を記載します。

URL S3バケット ビヘイビアのパスパターンの設定 優先度
https://mydomain/* S3バケット① デフォルト(*) 2
https://mydomain/aaa/* S3バケット② /aaa/* 1
https://mydomain/aaa/bbb/* S3バケット③ /aaa/bbb/* 0

https://mydomain/*のパターンは直ぐに接続可能になったものの、
それ以外のパターンでAccessDeniedとなってしまう事象がありました。

こちらChatGPTで確認したところ、OAC(Origin access control)の設定の記述古いままになっている等、誤った指示を真に受けていろいろ試行錯誤しましたが、結局のところS3のフォルダの階層の問題でした。

ビヘイビアのパスパターンの設定で/aaa/*を指定し、それとS3バケットを紐づけているので、
https://mydomain/aaa/を引き継いだ状態でオリジンの階層を辿ってくれると思っていました。

しかし、実際はパスパターンの設定はあくまでURL側のルーティングの設定で、
S3バケット側にもパスパターンと同様のフォルダ階層を作成しておかないと、正しくルーティングされないということが分かりました。

S3のバケットに/aaa/階層を追加したところ、意図通り動きました。

その他CloudFrontのこれ何?な設定

正直CloudFrontはAWSが提供するCloudFrontテンプレートを基に展開して使用したことがあるくらいで、自分で細かな設定をしたことがなかった。
特にビヘイビアの設定で何が何だか分からないものが多かったため、整理してみました。

設定 内容
ビューワーの設定 クライアント(ビューワー)⇔CloudFrontの設定
キャッシュポリシー CloudFrontが処理するキャッシュに関する設定
オリジンリクエストポリシー CloudFront⇔オリジン(S3)の設定
レスポンスヘッダーポリシー クライアント(ビューワー)に返すレスポンスに関する設定

※私はビューワーという表現が慣れず、ぱっと見何の設定かずっと読み飛ばしていましたが、クライアントと読み替えて問題なさそうでした。

ビューワー

デフォルトだと下記のような設定になっています。
ALBと違い自動でhttpsリダイレクトしてくれるようです。

キャッシュポリシー

まずはキャッシュに関する理解からです。
terminalでcacheにヒットしたか確認するには、下記のコマンドを実行します。

curl -I URL

初回実行結果

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 283
Connection: keep-alive
Date: Fri, 04 Jul 2025 08:23:52 GMT
Last-Modified: Fri, 04 Jul 2025 05:42:13 GMT
ETag: "1c180b85f4579e9142578d8483c44a83"
x-amz-server-side-encryption: AES256
Accept-Ranges: bytes
Server: AmazonS3
X-Cache: Miss from cloudfront
Via: 1.1 692ffa98ef111ee24bd6eed0db7ec1de.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: NRT57-P2
X-Amz-Cf-Id: MmyzN77cARDOiSNmqtlz0kLDqFSHq-tjxmCRguQiOwGS5vidpgNGcA==

二回目実行結果

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 283
Connection: keep-alive
Date: Fri, 04 Jul 2025 08:23:58 GMT
Last-Modified: Fri, 04 Jul 2025 05:42:13 GMT
ETag: "1c180b85f4579e9142578d8483c44a83"
x-amz-server-side-encryption: AES256
Accept-Ranges: bytes
Server: AmazonS3
X-Cache: Hit from cloudfront
Via: 1.1 4bee516d0163cd392c310c300265b098.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: NRT57-P2
X-Amz-Cf-Id: F6LxRCzXWa2rVQxuTjQVcq9gb4DcYgcnNIav1twvrQp68OiNZpa02w==
Age: 6

結果の通り一回目の結果はX-Cache: Miss from cloudfrontになっているのに対し、
二回目はX-Cache: Hit from cloudfrontとなっています。
二回目の接続は、S3まで到達せず、CloudFrontのキャッシュが利用されたことが分かります。

デフォルトのポリシー:CachingOptimizedの場合、すべてのコンテンツがキャッシュされますが、
コンテンツによってキャッシュさせたくないパターンがある場合に、キャッシュポリシーを変更、またはLegacy cache settingsから要件に合わせカスタマイズすることで、キャッシュを管理することができます。

ちなみに上記のデフォルトのCachingOptimizedを設定した場合、下記の仕様になるようです。
各ポリシーの中身は、下記ドキュメントに記載されています。
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/using-managed-cache-policies.html#managed-cache-caching-optimized

・最小 TTL: 1 秒。
・最大 TTL: 31,536,000 秒 (365 日)。
・デフォルト TTL: 86,400 秒 (24 時間)。
・キャッシュキーに含まれるヘッダー: 明示的に含まれているものがありません。圧縮オブジェクトのキャッシュの設定が有効になっているため、正規化された Accept-Encoding ヘッダーが含まれます。詳細については、「圧縮のサポート」を参照してください。
・キャッシュキーに含まれる Cookie: なし。
・キャッシュキーに含まれるクエリ文字列: なし。
・圧縮オブジェクトのキャッシュの設定: 有効。詳細については、「圧縮のサポート」を参照してください。

オリジンリクエストポリシー

CloudFrontからオリジンへのリクエストに関するポリシー。
こちらは、Cookieやクエリ文字列を渡したい時に使うポリシーです。

レスポンスヘッダーポリシー

CloudFrontからクライントへのレスポンスに関するポリシーの設定。
CORSやセキュリティ対策でカスタマイズするケースがある模様。

残念ながら私がCORSを意識して実装しないといけないケースがないため、
別途学習できればと思っています。
同じような境遇の方は、ポリシーを作成してHTTPヘッダーをカスタマイズできるよくらいの理解で大丈夫だと思います。

その他検証に便利なコマンド

CloudFrontキャッシュクリア用。設定変更等行った際は実行します。

aws cloudfront create-invalidation --distribution-id ディストリビューションID --paths "/*"

ただし、いちいちクリアできたか確認するのも面倒なので、
検証時はそもそもビヘイビアのキャッシュポリシーでCachingDisabledの設定にしておくのがおすすめです。

CloudFrontディストリビューション一覧

aws cloudfront list-distributions

ディストリビューションの情報取得

aws cloudfront get-distribution --id <ディストリビューションID>

ローカルからS3へフォルダ同期用

aws s3 sync ./bucket-n s3://バケット --delete

今回ローカルにS3バケットと同じ階層のフォルダを作成し、
aws cliでS3に都度変更を反映させていました。
最初はCDKでやりたかったのですが、このぐらいの検証をやるには面倒に感じ、cli方式で差分反映していました。変更反映も一瞬で非常に使い勝手良かったです。
--deleteオプションはローカル側でファイルを消した際にS3側でも削除してくれるように付加します。

最後に

キャッシュやhttpヘッダー等、あまり意識する機会がなく、不勉強なのを実感しました。
GUIで簡単に操作できるのがAWSの良いところなので、次回はより詳しくポリシーを見ていけたらと思っています。

Discussion