+ 作るログイン
1 / 22
AWS でサービスを作る ― 知識ゼロから、構成を自分で考えられるまで / 全32章

AWS 15:S3 と CloudFront ― 写真をサーバーの外に置き、世界へ速く配る

発行
アニメモ公式
版
第2版
改訂
コマ
全22

写真を Web サーバーのディスクに置くと、入れ替わったときに消え、別のサーバーからは見えず、配るたびにサーバーが重くなります。オブジェクトストレージ S3 のバケットとキー、公開しないための設定と IAM ロール、写真をサーバーを通さずに直接置く署名付き URL、ストレージクラスとライフサイクル、そして CloudFront のエッジとキャッシュ、S3 を閉じたまま配る OAC までを、フォトログの写真の投稿と表示を例に説明します。

写真を Web サーバーに置くと、消えるし、見えないし、重い

第14章で、フォトログは https://example.com という名前で安全に開けるようになりました。残る大きな問題は、フォトログの主役である写真です。

いまのフォトログは、投稿された写真を、投稿を受けた Web サーバーのディスク(第10章の EBS)に保存しています。すると、図のようなことが起きます。

起きることなぜ困るか
Aさんの写真は Web 1 のディスクにしかないALB が Web 2 に振った人には、写真が表示されない
Auto Scaling が Web 1 を入れ替えた写真がディスクごと消える(第12章の「サーバーは使い捨て」)
数 MB の写真を何万回も配るWeb サーバーの回線と CPU が写真の配送で埋まり、肝心のアプリが遅くなる

では、第13章の RDS に入れればいいかというと、それも違いました。写真は1枚が数 MB と大きく、DB に入れると、ディスクもバックアップも膨らみ、読み書きも遅くなります。

必要なのは、大きなファイルをたくさん、安く、失くさずに置けて、どのサーバーからも同じものが見える置き場です。それが S3 です。さらに、その写真を世界中へ速く配るために CloudFront を使います。

※2026年9月時点の情報です。画面・料金・細部は変わることがあります。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 1 / 22
  • 写真を Web サーバーに置くと、消えるし、見えないし、重い
  • サーバー
  • Web 1
  • サーバー
  • Web 2
  • サーバー
  • Web 1(入れ替え後)
  • ディスクに写真 A
  • 写真 A が無い
  • 写真 A が消えた
  • NG
  • Web 2 に振られた人には、Aさんの写真が表示されない
  • NG
  • Auto Scaling が Web 1 を入れ替えると、写真はディスクごと消える
  • NG
  • 数 MB の写真を配るたびに、Web サーバーの回線と CPU が埋まる
  • DB(第13章)には写真そのものを入れない。大きすぎて、DB もバックアップも膨らむ
  • → 大きなファイル専用の、安くて壊れない置き場が要る。それが S3
  • ひらめき
  • サーバーは使い捨て(第12章)。写真のような大きなファイルは、サーバーの外に置き場が要る。

S3 は「オブジェクトストレージ」:番号札で預ける、巨大な倉庫

Amazon S3(Simple Storage Service)は、AWS でいちばん古いサービスの1つで、ファイルを預かる倉庫です。

ストレージ(データの置き場)には、大きく3つの種類があります。

ブロック(EBS)ファイル(EFS)オブジェクト(S3)
たとえ自分の机の引き出し部署の共有の本棚番号札で預ける巨大な倉庫
つながる相手1台のサーバー複数のサーバーどこからでも(HTTPS で)
一部だけ書き換えできるできるできない。丸ごと置き直す
容量先に決めて確保する使った分使った分。実質無制限
向いているものOS や DB のディスク複数台で共有するフォルダ写真・動画・バックアップ・ログ

オブジェクトストレージは、ファイルを丸ごと預け、名前を言えば丸ごと返してくれる仕組みです。コートを預けて番号札をもらうクロークに似ています。途中を少し書き換えることはできませんが、その代わりに、いくらでも預けられ、どこからでも取り出せます。

写真は「一度投稿したら書き換えず、表示するときは丸ごと読む」ものです。まさにオブジェクトストレージが向いている使い方です。

S3 は VPC(第5章)の中に置くものではなく、リージョンごとに AWS が用意している大きな倉庫です。HTTPS の API で、どこからでも読み書きします(ただし、許された人だけ。後で見ます)。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 2 / 22
  • S3 は「オブジェクトストレージ」:番号札で預ける、巨大な倉庫
  • EBS(第10章)
  • EFS
  • S3
  • たとえ
  • 机の引き出し
  • 共有の本棚
  • 番号札の倉庫
  • 種類
  • ブロックストレージ
  • ファイルストレージ
  • オブジェクトストレージ
  • つながる相手
  • 1台のサーバー
  • 複数のサーバー
  • どこからでも(HTTPS)
  • 一部だけ書き換え
  • できる
  • できる
  • できない(丸ごと置き直す)
  • 容量
  • 決めて確保する
  • 使った分
  • 使った分・実質無制限
  • 向いているもの
  • OS・DB のディスク
  • 共有フォルダ
  • 写真・動画・バックアップ
  • 写真は「一度置いたら書き換えず、丸ごと読む」ので、S3 がいちばん向いている
  • ひらめき
  • ファイルを丸ごと預け、名前を言えば丸ごと返してくれる。容量の上限を気にしなくてよい。

バケットとキー:倉庫の名前と、荷物の番号札

S3 の言葉を3つ覚えます。

言葉意味例
バケット入れ物。リージョンを選んで作るphotolog-photos
キー中身の名前(番号札)uploads/u123/a1b2.jpg
オブジェクト中身そのもの+付帯情報(種類・大きさ・日時など)写真のデータ

図の左がバケットの中身の例です。uploads/u123/ のように、フォルダがあるように見えますが、実は S3 にフォルダはありません。キー全体が1つの名前で、/ で区切った頭の部分(プレフィックス)が、画面上でフォルダのように見えているだけです。

バケットの名前には決まりがあります。

決まり内容
名前の重なり従来のバケット名は、全世界の AWS の利用者の間で重なってはいけない
新しい選択肢2026年から、名前の末尾に自分のアカウント番号とリージョンを付けて、自分専用の範囲で名前を付ける方法も選べる
使える文字小文字・数字・ハイフンなど。後から名前は変えられない

名前が世界で重ならないように、photolog-photos- の後ろに自分だけの文字を足すのがふつうです。この章では説明のため photolog-photos と書きます。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 3 / 22
  • バケットとキー:倉庫の名前と、荷物の番号札
  • フォルダ
  • バケット:photolog-photos
  • バケット
  • 入れ物。リージョンに作る
  • 写真
  • uploads/u123/a1b2.jpg
  • 2.4 MB
  • キー
  • 中身の名前(番号札)
  • 写真
  • uploads/u123/c3d4.jpg
  • 3.1 MB
  • オブジェクト
  • 中身そのもの+付帯情報
  • 写真
  • uploads/u456/e5f6.jpg
  • 1.8 MB
  • プレフィックス
  • キーの頭。フォルダに見える
  • 写真
  • thumbs/u123/a1b2.webp
  • 40 KB
  • ひらめき
  • バケット(倉庫)の中に、キー(名前)で中身を置く。フォルダに見えるのは名前の一部。

S3 は、預けたものをまず失くさないように作られている

S3 のいちばんの強みは、預けたものを失くさないことです。

ふつうの(Standard の)S3 は、1つのリージョンの中の複数の AZ(第2章)に、データを分けて保存しています。図のように、AZ が1つ丸ごと止まっても、写真は他の AZ に残っています。

性質内容
耐久性99.999999999%(9が11個)を目標に設計されている
容量実質無制限。先に確保する必要はない
読み直し書いた直後から、最新の内容が読める
入口HTTPS の API。SDK や CLI、コンソールから使う

耐久性は「預けたものが失われない確かさ」のことです。9が11個というのは、1000万個のファイルを預けても、平均して1万年に1個失うかどうか、という水準です。

ただし、これは機械の故障から守る話です。第13章の RDS の Multi-AZ と同じで、あなたが間違って消したものは戻りません。間違いに備えるには、バージョニング(上書きや削除をしても古い版を残す設定)を有効にしておく方法があります。消した版も保管料がかかるので、ライフサイクル(後で説明)と組み合わせます。

なお、図の下の注記のとおり、安さと引き換えに1つの AZ だけに置く種類もあります。これも後で見ます。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 4 / 22
  • S3 は、預けたものをまず失くさないように作られている
  • AZ-a
  • AZ-c
  • AZ-d
  • 耐久性
  • 9が11個の 99.999…%
  • ディスク
  • ディスク
  • ディスク
  • 容量
  • 実質無制限。確保は不要
  • 写真 A の写し
  • 写真 A の写し
  • 写真 A の写し
  • 読み直し
  • 書いた直後から最新が読める
  • 入口
  • HTTPS の API(どこからでも)
  • ※「1つの AZ だけに置く」安いストレージクラスもある(後で説明)
  • ひらめき
  • S3 は1つのリージョンの複数の AZ にデータを分けて持つ。1つの AZ が丸ごと止まっても消えない。

バケットは公開しない。「ブロックパブリックアクセス」はオンのまま

S3 で起きる情報流出の事故の多くは、S3 が破られたのではなく、バケットを「誰でも読める」設定にしてしまったことが原因です。

そのため、S3 にはブロックパブリックアクセスという安全装置があります。これがオンの間は、どんな設定を書いても、バケットが公開されることはありません。

新しいバケットの既定(2023年から)内容
ブロックパブリックアクセス4つの設定がすべてオン
ACL無効。昔の細かい権限の方式を使わず、持ち主がすべてを管理する
暗号化置いたものは自動で暗号化して保存される

図では、知らない人が S3 を直接読もうとして、止められています。

「でも、写真はみんなに見せたい。公開しないとどうやって見せるの?」と思うかもしれません。答えは2つあります。

見せ方この章の説明
投稿のとき署名付き URL で、決まった名前に決まった時間だけ置かせる
表示のときCloudFront に S3 を読ませ、利用者は CloudFront から受け取る(OAC)

どちらも、バケットは閉じたままです。バケットを公開する必要がある場面は、ほとんどありません。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 5 / 22
  • バケットは公開しない。「ブロックパブリックアクセス」はオンのまま
  • VPC
  • サーバー
  • Web(EC2)
  • データベース
  • 盾
  • パブリックアクセス
  • ブロック:オン(既定)
  • RDS
  • スマホ
  • 利用者
  • 写真を投稿
  • 新しいバケットの既定
  • ブロックパブリックアクセス
  • 4つともオン
  • フォルダ
  • S3 バケット
  • 人
  • ACL(古い権限の方式)
  • 無効
  • NG
  • photolog-photos
  • 知らない人
  • ひらめき
  • S3 の流出事故のほとんどは「誰でも読める」設定のミス。新しいバケットは最初から閉じている。

Web サーバーは IAM ロールで S3 を使う。鍵を置かない

Web サーバーのアプリが S3 を使うには、AWS に「私は使ってよい者です」と示す必要があります。

ここで、アクセスキー(第3章)をアプリの設定ファイルに書くのはやめます。漏れたら誰でもバケットを使えますし、取り替えるのも大変です。

代わりに、EC2 に IAM ロールを付けます(第3章の「ロールをかぶる」考え方)。

仕組み内容
ロール「このバケットに置く・読む」だけを許したポリシーを付けた役割
EC2 に付けるインスタンスプロファイルとして、起動テンプレート(第12章)で指定する
資格の配り方AWS が期限付きの資格を自動で配り、自動で取り替える。アプリの SDK が勝手に読む

図の下の板は、ロールに付けるポリシーの中心部分です。

json
{
  "Effect": "Allow",
  "Action": ["s3:PutObject", "s3:GetObject"],
  "Resource": "arn:aws:s3:::photolog-photos/*"
}

Resource でバケットを1つに絞り、Action で必要な操作だけを許しています。最小権限(第3章)です。削除(s3:DeleteObject)が必要なら、そのときに足します。

Auto Scaling で増えた Web サーバーも、同じ起動テンプレートから生まれるので、全員が同じロールで S3 を使えます。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 6 / 22
  • Web サーバーは IAM ロールで S3 を使う。鍵を置かない
  • VPC
  • サーバー
  • Web(EC2)
  • データベース
  • RDS
  • ロール:photolog-web
  • スマホ
  • 利用者
  • ロールの権限で読み書き
  • 写真を投稿
  • フォルダ
  • S3 バケット
  • "Action": ["s3:PutObject", "s3:GetObject"],
  • photolog-photos
  • "Resource": "arn:aws:s3:::photolog-photos/*"
  • ひらめき
  • アクセスキーを書かない。EC2 にロールを付ければ、AWS が期限付きの資格を配る。

写真を Web サーバー経由で S3 に送ると、サーバーが2回運ぶ

置き場が決まったので、投稿の流れを考えます。素直に作ると、図のようになります。

回運ぶ区間何が起きるか
1回目利用者 → Web サーバーWeb が写真を丸ごと受け取る
2回目Web サーバー → S3Web が写真を S3 へ渡し直す

これでも動きますが、困りごとがあります。

困りごと内容
Web が忙しくなる数 MB の写真の受け渡しで、回線とメモリを使う
待たされる利用者の回線が遅いと、その間ずっと Web サーバーがつかまる
台数が増える写真の中継のために Auto Scaling が台数を増やし、お金がかかる
上限にぶつかる大きな動画などは、ALB やアプリの受け付けられる大きさの上限にぶつかりやすい

写真の中身は、Web サーバーが見る必要のないものです。Web サーバーが知りたいのは「誰が、どの写真を投稿したか」だけです。

だったら、写真は利用者から S3 へ直接送ってもらえばいいはずです。でも、バケットは閉じていて、利用者は S3 に置く権限を持っていません。

そこで使うのが署名付き URLです。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 7 / 22
  • 写真を Web サーバー経由で S3 に送ると、サーバーが2回運ぶ
  • VPC
  • サーバー
  • Web(EC2)
  • データベース
  • RDS
  • 写真 3MB
  • スマホ
  • 利用者
  • 写真を投稿
  • フォルダ
  • S3 バケット
  • 1回目:利用者 → Web(受け取る)
  • photolog-photos
  • 2回目:Web → S3(渡し直す)
  • ひらめき
  • 利用者 → Web → S3 と中継すると、大きな写真で Web の回線と待ち時間が埋まる。

署名付き URL ①:Web サーバーは「置いてよい URL」だけを渡す

署名付き URL(presigned URL)は、「この URL を使えば、この名前で、この期限まで、S3 に置いて(または読んで)よい」という許可証つきの URL です。権限を持つ Web サーバーが、自分の権限で署名して作ります。

図の番号の順に見ます。

順番起きること
1利用者のアプリが Web サーバーに「写真を投稿したい」と伝える(写真はまだ送らない)
2Web サーバーがキー(置き場所の名前)を決め、署名付き URL を作って返す

2で返すのは小さな文字列だけです。Web サーバーの仕事は一瞬で終わります。

たとえるなら、倉庫の受付(Web)が、「この番号の棚に、今から5分以内なら置いてよい」と書いた入館証を渡すようなものです。受付は荷物を運びません。

署名付き URL は、作るときに AWS へ問い合わせる必要すらありません。Web サーバーが持っているロールの資格で、手元で計算して作れます。だから速く、何枚でも作れます。

次に、利用者がこの URL を使って写真を置くところを見ます。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 8 / 22
  • 署名付き URL ①:Web サーバーは「置いてよい URL」だけを渡す
  • VPC
  • サーバー
  • Web(EC2)
  • データベース
  • 1
  • RDS
  • スマホ
  • 利用者
  • 写真を投稿
  • 2
  • ① 利用者「写真を投稿したい」
  • ② Web「この URL に置いて」(署名付き)
  • フォルダ
  • S3 バケット
  • 署名付き URL
  • photolog-photos
  • ひらめき
  • Web は写真を受け取らない。「この名前で、5分以内なら置いてよい」と署名した URL を返す。

署名付き URL ②:写真は S3 へ直接。Web は名前だけを DB に書く

続きです。

順番起きること
3利用者のアプリが、受け取った URL に写真を直接送る(PUT)。図の緑の小包
4置けたら、アプリが Web サーバーに「置けました」と伝え、Web がそのキーを RDS の photos の表に記録する(第13章)

写真は S3 が直接受け取るので、Web サーバーは写真の大きさに関係なく、小さな文字のやり取りだけで済みます。

Web 経由署名付き URL
Web が運ぶもの写真そのもの(数 MB)許可証とキー(数百文字)
写真の通り道利用者 → Web → S3利用者 → S3
大きなファイル上限にぶつかりやすいS3 が受け止める

4を忘れると、S3 に写真はあるのに、どの投稿の写真かが DB に残りません。反対に、3が失敗したのに4を記録すると、存在しない写真を指す投稿ができます。置けたことを確かめてから記録する順番が大事です。

S3 には、置かれたことを知らせる通知の仕組み(イベント通知)もあります。第24章の非同期の話で、これを使って縮小画像を作ります。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 9 / 22
  • 署名付き URL ②:写真は S3 へ直接。Web は名前だけを DB に書く
  • VPC
  • サーバー
  • Web(EC2)
  • データベース
  • 4
  • RDS
  • スマホ
  • 利用者
  • 写真を投稿
  • 3
  • 写真 3MB
  • フォルダ
  • S3 バケット
  • ③ 写真を S3 へ直接 PUT
  • photolog-photos
  • ④「置けた」と Web に知らせ、Web がキーを RDS に記録
  • ひらめき
  • 重い写真は S3 が直接受け取る。Web は「どのキーに置いたか」を RDS に記録するだけ。

署名付き URL の中身と、守りのための決めごと

Web サーバー(Node.js)で署名付き URL を作るコードは、図の上の板のくらいの短さです。

ts
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

const s3 = new S3Client({ region: "ap-northeast-1" });
const key = `uploads/${userId}/${crypto.randomUUID()}.jpg`;
const url = await getSignedUrl(
  s3,
  new PutObjectCommand({ Bucket: "photolog-photos", Key: key, ContentType: "image/jpeg" }),
  { expiresIn: 300 }, // 5分で無効
);

署名付き URL は「持っている人なら誰でも使える」許可証です。だから、発行のしかたで守ります。

決めごと理由
期限は短く(数分)漏れても使える時間が短い。最長は7日だが、一時的な資格で作ると、その資格の期限で切れる
キーはサーバーが決める利用者に名前を選ばせると、他人の写真のキーを指定して上書きされる
種類を決めるContentType を署名に含め、画像以外を置かせない
大きさを制限したいならPUT の代わりに、大きさの範囲を条件にできる「署名付き POST」を使う
ブラウザから送るならバケットに CORS(どのサイトから送ってよいか)を設定する

CORS は、ブラウザが「別の名前のサイトへ送ってよいか」を相手に確かめる仕組みです。フォトログの画面(example.com)から S3 へ送るので、S3 側で https://example.com からの PUT を許す設定を書きます。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 10 / 22
  • 署名付き URL の中身と、守りのための決めごと
  • const key = `uploads/${userId}/${crypto.randomUUID()}.jpg`;
  • const url = await getSignedUrl(s3,
  • new PutObjectCommand({ Bucket: "photolog-photos", Key: key, ContentType: "image/jpeg" }),
  • { expiresIn: 300 }); // 5分で無効
  • 期限は短く
  • 数分で十分。最長でも7日(一時的な資格で作ると、その資格の期限で切れる)
  • キーはサーバーが決める
  • 利用者に名前を選ばせない(他人の写真を上書きされる)
  • 種類を決める
  • ContentType を固定し、画像以外を置かせない
  • ブラウザから送るなら
  • バケットに CORS(どのサイトから送ってよいか)を設定
  • ひらめき
  • URL は「誰が・何を・いつまで」の許可証。短い期限・決めた名前・決めた種類で発行する。

ストレージクラス:読む頻度で置き場を分ける

S3 には、料金と性質の違うストレージクラスがあります。オブジェクトごとに選べます。

クラス向いているもの注意
S3 Standardよく読むもの。迷ったらこれ保管料はいちばん高い
S3 Intelligent-Tiering読む頻度がわからないもの読まれ方を見て自動で安い層へ移す。1件ごとに少額の見張り料
S3 Standard-IA月に数回も読まないもの取り出すたびに料金。最低30日分の保管料
S3 One Zone-IA作り直せるもの(縮小画像など)1つの AZ だけに置く。その AZ が壊れると消える
S3 Glacier Instant Retrieval年に数回だけ読む保管物最低90日分。取り出し料は高め
S3 Glacier Flexible Retrieval / Deep Archive法律で残す記録、長期の控え取り出しに数分〜数時間以上かかる

IA は Infrequent Access(まれにしか読まない)の略です。

考え方は「保管料が安いほど、取り出しが高い・遅い」の天秤です。よく読むものを安いクラスに置くと、取り出し料でかえって高くなります。

フォトログでの例クラス
投稿されたばかりの写真Standard(みんなが見る)
1か月以上たった写真の原本Standard-IA(たまにしか見られない)
数年前の退会者のデータの控え必要なら Glacier 系

どれを選ぶか迷ったら、まず Standard で始め、Cost Explorer(第4章)で S3 の料金が目立ってから見直すので十分です。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 11 / 22
  • ストレージクラス:読む頻度で置き場を分ける
  • クラス
  • 向いているもの
  • 注意
  • S3 Standard
  • よく読むもの(まずはこれ)
  • 保管料はいちばん高い
  • Intelligent-Tiering
  • 読む頻度がわからないもの
  • 自動で移す。1件ごとの見張り料
  • Standard-IA
  • 月に数回も読まないもの
  • 取り出し料。最低30日分の保管料
  • One Zone-IA
  • 作り直せるもの
  • 1つの AZ だけ。AZ が壊れると消える
  • Glacier Instant Retrieval
  • 年に数回読む保管物
  • 最低90日分。取り出し料は高め
  • Glacier Flexible・Deep
  • 法律で残す記録など
  • 取り出しに数分〜数時間以上
  • 写真 SNS なら:新しい写真は Standard、1か月後から読まれにくい原本は IA へ、が1つの型
  • ひらめき
  • めったに読まないものほど保管料が安く、代わりに取り出しに料金や時間がかかる。

ライフサイクル:日数で自動的に移し替え、要らなくなれば消す

ストレージクラスを手で移し替えるのは大変です。S3 にはライフサイクルという規則を書けます。

規則の例内容
移し替えuploads/ のオブジェクトを、置いて30日後に Standard-IA へ
削除一時ファイルの tmp/ は7日後に消す
古い版の片付けバージョニングの古い版は90日後に消す
途中物の片付け途中で止まった大きなアップロードの破片を7日後に消す

最後の「途中物」は見落としがちです。大きなファイルは何回かに分けて送る(マルチパートアップロード)ことがあり、途中で止まると、画面の一覧には出ない破片が残って課金され続けます。どのバケットにも付けておくとよい規則です。

図の下の板は、ライフサイクルの規則を JSON で書いた例です。コンソールでは「管理」の画面から同じことを設定できます。

json
{
  "Rules": [
    { "ID": "originals-to-ia", "Status": "Enabled",
      "Filter": { "Prefix": "uploads/" },
      "Transitions": [ { "Days": 30, "StorageClass": "STANDARD_IA" } ] },
    { "ID": "abort-mpu", "Status": "Enabled",
      "Filter": { "Prefix": "" },
      "AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 7 } }
  ]
}

小さなファイル(目安として128KB 未満)は IA に移しても安くならない決まりがあるので、縮小画像のような小さなものは移さないのが一般的です。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 12 / 22
  • ライフサイクル:日数で自動的に移し替え、要らなくなれば消す
  • 0日
  • 30日
  • 365日
  • 置いた日
  • IA へ移す
  • Glacier へ
  • 場所
  • 場所
  • 場所
  • { "ID": "originals-to-ia", "Status": "Enabled", "Filter": { "Prefix": "uploads/" },
  • "Transitions": [ { "Days": 30, "StorageClass": "STANDARD_IA" } ] },
  • { "ID": "abort-mpu", "Status": "Enabled", "Filter": { "Prefix": "" },
  • "AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 7 } }
  • ひらめき
  • 「30日で IA へ」「途中で止まったアップロードは7日で消す」のような規則を書く。

S3 は東京にある。パリの利用者には、遠くて遅い

写真の置き場はできました。次は配り方です。

フォトログの S3 バケットは東京リージョンにあります。東京の利用者にはすぐ届きますが、パリの利用者はどうでしょう。

通信は光の速さで進みますが、地球の反対側まで行って戻るには、どうしても時間がかかります。この往復の時間をレイテンシー(遅延)と呼びます。1回の差は一瞬でも、写真が何十枚も並ぶタイムラインでは、その遅さが積み重なり、「重いサイト」になります。

困りごと内容
遠い遠い利用者ほど、写真1枚ごとの往復に時間がかかる
同じものを何度も運ぶ人気の写真は、同じデータを東京から何万回も送り出す
外への通信料S3 から直接インターネットへ出すと、そのたびに転送料がかかる

解決策は、利用者の近くに写しを置いておくことです。1度パリまで運んだら、パリに置いておけば、次のパリの利用者にはすぐ渡せます。

これを世界規模でやってくれる仕組みを CDN(コンテンツ配信ネットワーク)と呼び、AWS の CDN が CloudFront です。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 13 / 22
  • S3 は東京にある。パリの利用者には、遠くて遅い
  • 人
  • 東京の利用者
  • 近い:すぐ届く
  • フォルダ
  • S3(東京)
  • 写真の本体
  • 人
  • パリの利用者
  • 遠い:往復に時間がかかる
  • NG
  • しかも全員が S3 から直接読むと、同じ写真を何万回も運ぶ
  • ひらめき
  • 地球の裏側までは往復に時間がかかる。写真が何十枚も並ぶ一覧では、遅さが積み重なる。

CloudFront:世界中の「エッジ」に写しを置き、近くから配る

Amazon CloudFront は、世界中の数百か所にエッジロケーション(配送の拠点)を持っています。利用者は、自動的に近くのエッジにつながります。

言葉意味
ディストリビューションCloudFront の設定のまとまり。1つ作ると d1234abcd.cloudfront.net のような名前がもらえる
オリジン本体の置き場。フォトログでは S3 バケット
エッジ利用者の近くの拠点。写しを覚えておく
キャッシュエッジが覚えている写し

図の流れはこうです。

回起きること
1回目パリの利用者 → パリのエッジ。エッジは写しを持っていないので、東京の S3 から取ってきて渡し、覚えておく(キャッシュミス)
2回目からパリの利用者 → パリのエッジ。覚えている写しをすぐ返す(キャッシュヒット)。S3 には行かない

CloudFront を挟むと、次のことが一度に良くなります。

良くなること理由
速い近くのエッジから届く
S3 が楽同じ写真を何度も運ばなくてよい
守りやすい入口が CloudFront だけになる。WAF(第27章)も付けられる
通信料S3 から CloudFront への転送は無料。外への配信は CloudFront の料金で数える
  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 14 / 22
  • CloudFront:世界中の「エッジ」に写しを置き、近くから配る
  • 人
  • 東京の利用者
  • インターネット
  • エッジ(東京)
  • 1回目だけ
  • フォルダ
  • S3(東京)
  • オリジン(本体)
  • 人
  • パリの利用者
  • インターネット
  • エッジ(パリ)
  • 1回目だけ
  • 写真(写し)
  • 2回目からは、パリの利用者もパリのエッジから受け取る
  • ひらめき
  • 1回目はエッジが S3 から取ってきて覚える。2回目からは近くのエッジがすぐ返す(キャッシュ)。

OAC:S3 は閉じたまま、CloudFront だけに読ませる

CloudFront を通しても、S3 のバケットが公開されていたら、S3 の URL を直接叩けば写真が読めてしまいます。それでは CloudFront の守りも、キャッシュも迂回されます。

そこで OAC(Origin Access Control、オリジンへのアクセスの制御)を使います。

仕組み内容
CloudFront 側オリジンの S3 に取りに行くとき、署名を付けて「CloudFront のこのディストリビューションです」と名乗る
S3 側バケットポリシーに「このディストリビューションからの読み取りだけ許す」と書く
結果S3 は閉じたまま(ブロックパブリックアクセスもオンのまま)。S3 の URL を直接叩くと拒否される

図の下の板は、バケットポリシーの中心部分です。

json
{
  "Effect": "Allow",
  "Principal": { "Service": "cloudfront.amazonaws.com" },
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::photolog-photos/*",
  "Condition": { "StringEquals": {
    "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/E1ABCDEFGHIJKL"
  } }
}

Condition で自分のディストリビューションだけに絞っているのが大事です。これが無いと、他人の CloudFront からでも読めることになります。コンソールで OAC を選ぶと、このポリシーをコピーできるように表示してくれます。

以前は OAI という似た仕組みが使われていました。新しく作るなら OAC を選びます。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 15 / 22
  • OAC:S3 は閉じたまま、CloudFront だけに読ませる
  • 人
  • 東京の利用者
  • インターネット
  • エッジ(東京)
  • OAC(署名つき)
  • フォルダ
  • S3(東京)
  • 閉じたまま
  • NG
  • 人
  • 直接叩く人
  • "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject",
  • "Condition": { "StringEquals": { "AWS:SourceArn": "…:distribution/E1ABC…" } }
  • ひらめき
  • バケットポリシーで「この CloudFront だけ読んでよい」と書く。S3 を直接叩いても読めない。

キャッシュの期限と、「中身を変えたら名前も変える」

エッジは、写しをいつまで覚えておくのでしょうか。

決めごと内容
TTL写しを覚えておく時間。CloudFront のキャッシュポリシーと、オリジンが返す Cache-Control ヘッダーで決まる
無効化「この写しを捨てて」とエッジに命じる。すぐ効くが、一定数を超えると有料
キャッシュキー何が違えば別物として覚えるか。URL のほか、一部のヘッダーやクッキーを含めるかを決める

困るのは、同じ名前のまま中身を変えたときです。エッジは TTL の間、古い写しを返し続けます。無効化すれば消えますが、毎回それをするのは面倒で、お金もかかります。

よい方法は、中身を変えたら名前も変えることです。

やり方例
新しいキーで置く写真を差し替えたら …/b7c8.jpg という別の名前で置き、DB の s3_key を書き換える
名前に版を入れる画面の CSS や JS なら app.3f9a.css のように中身から作った文字を入れる

フォトログは、投稿ごとに crypto.randomUUID() で新しいキーを作っているので、同じ名前が別の中身になることがありません。だから TTL を長くしても困りません。

なお、特定の人にだけ見せたい写真(鍵付きのアカウントなど)は、CloudFront の署名付き URL・署名付きクッキーで、見てよい人にだけ許可証を渡す方法があります。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 16 / 22
  • キャッシュの期限と、「中身を変えたら名前も変える」
  • 決めごと
  • 内容
  • TTL(覚える時間)
  • キャッシュポリシーや Cache-Control ヘッダーで決める
  • 無効化
  • 「この写しを捨てて」とエッジに命じる。すぐ効くが、多用すると有料
  • 名前を変える
  • 中身を変えたら新しいキーで置く。古い写しは誰も呼ばなくなる
  • キャッシュキー
  • 何が違えば別物として覚えるか(URL・一部のヘッダーなど)
  • OK
  • フォトログは写真ごとに新しいキー(uuid)なので、長い TTL にしても困らない
  • ひらめき
  • エッジは TTL の間、写しを返し続ける。写真は上書きせず新しいキーで置けば悩まない。

作り方:6つの手順で、置き場と配り口ができる

図の番号の順に作ります。

順番やることポイント
1バケットを作る東京リージョン。ブロックパブリックアクセスはオンのまま
2ロールに権限Web のロールに、このバケットへの Put/Get だけ
3署名付き URLアプリで発行。バケットに CORS を設定
4ライフサイクルIA への移し替えと、途中物の片付け
5CloudFrontオリジンに S3 を選び、OAC を作ってバケットポリシーに貼る
6名前を付けるus-east-1 で img.example.com の証明書を作り、CloudFront に付け、Route 53 でエイリアス(第14章)

バケットを CLI で作る例です。東京リージョンに作るときは、場所の指定が要ります。

bash
aws s3api create-bucket --bucket photolog-photos \
  --region ap-northeast-1 \
  --create-bucket-configuration LocationConstraint=ap-northeast-1
aws s3api put-bucket-lifecycle-configuration --bucket photolog-photos \
  --lifecycle-configuration file://lifecycle.json

作り終わったら、S3 の URL を直接開くと拒否されること、https://img.example.com/uploads/… なら写真が表示されることを確かめます。CloudFront の設定の変更は、世界中のエッジに行き渡るまで数分かかります。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 17 / 22
  • 作り方:6つの手順で、置き場と配り口ができる
  • フォルダ
  • バケットを作る
  • 鍵
  • ロールに権限
  • コード
  • 署名付き URL
  • 東京・公開ブロックはオン
  • Put/Get をこのバケットだけ
  • アプリで発行・CORS 設定
  • 更新
  • ライフサイクル
  • インターネット
  • CloudFront
  • 場所
  • 名前を付ける
  • IA へ移す・途中物を消す
  • オリジン=S3・OAC
  • us-east-1 の証明書+エイリアス
  • 確かめ方:S3 の URL を直接開くと「拒否」、https://img.example.com/… なら写真が出る
  • CloudFront の設定の反映には数分かかる。その間に試して「動かない」と慌てない
  • ひらめき
  • バケット → 権限 → アプリ → 規則 → 配り口 → 名前。CloudFront の証明書は us-east-1 で。

フォトログでは:投稿は S3 へ直接、表示は CloudFront から

ここまでで、フォトログの通り道は3本に分かれました。

通り道何が通るか経路
example.com画面・一覧の文字(JSON や HTML)ALB → Web → RDS
img.example.com写真の表示CloudFront → (初回だけ)S3
署名付き URL写真の投稿利用者 → S3 へ直接

キーの付け方も決めておきます。

プレフィックス中身
uploads/{利用者}/{uuid}.jpg投稿された原本
thumbs/{利用者}/{uuid}.webp一覧用の縮小画像(第24章で自動で作る)

一覧の画面では、RDS から写真の s3_key を読み、https://img.example.com/ を頭に付けて画像の URL にします。

これで、写真の出入りから Web サーバーが外れました。Web サーバーは小さな文字のやり取りだけを受け持てばよくなり、少ない台数で多くの利用者をさばけます。Auto Scaling で入れ替わっても、写真は S3 にあるので何も失いません。第12章の「サーバーは使い捨て」が、ようやく完全に成り立ちました。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 18 / 22
  • フォトログでは:投稿は S3 へ直接、表示は CloudFront から
  • ネットワーク
  • example.com
  • ページと一覧の文字:ALB
  • ALB → Web → RDS
  • 写真の表示:CloudFront
  • 写真の投稿:S3 へ直接
  • スマホ
  • 利用者
  • インターネット
  • img.example.com
  • CloudFront
  • OAC
  • フォルダ
  • S3
  • uploads/ と thumbs/
  • アップロード
  • 署名付き URL
  • 投稿のときだけ
  • ひらめき
  • 写真の出入りから Web サーバーが外れた。Web は小さな JSON と HTML だけを扱えばよくなる。

お金:置いた量、呼んだ回数、外へ出した量

S3 と CloudFront の料金は、主に次のものに対してかかります。

課金されるもの単位メモ
S3 の保管GB × 月。クラスで単価が違うIA などは最低保管日数と取り出し料がある
S3 のリクエストPUT・GET などの回数小さなファイルが大量にあると効いてくる
S3 から外への転送GBCloudFront に渡す分は無料
CloudFront の転送GB。利用者の地域で単価が違う毎月一定量までの無料枠がある
CloudFront のリクエスト回数同上
無効化一定数を超えると有料名前を変える運用なら、ほぼ使わない

2025年からは、CloudFront に定額プラン(Free・Pro など)も選べるようになりました。CDN・WAF・DNS などがまとめて月額に含まれ、アクセスが急に増えても追加料金が出ない形です。趣味や小さなサービスでは、料金を読みやすくする選択肢になります。

いちばん気をつけるのは外への転送です。写真や動画のサービスでは、保管料より配信の料金が大きくなりがちです。CloudFront でキャッシュを効かせ、縮小画像を使って運ぶ量そのものを減らします。

単価・無料枠・定額プランの中身は変わるので、料金ページで確かめてください。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 19 / 22
  • お金:置いた量、呼んだ回数、外へ出した量
  • 課金されるもの
  • 単位
  • メモ
  • S3 の保管
  • GB × 月(クラスで単価が違う)
  • IA などは最低日数と取り出し料
  • S3 のリクエスト
  • PUT・GET などの回数
  • 小さなファイルが大量だと効く
  • S3 から外への転送
  • GB
  • CloudFront 経由なら S3 側は無料
  • CloudFront の転送
  • GB(地域で単価が違う)
  • 毎月の無料枠あり
  • CloudFront のリクエスト
  • 回数
  • 定額プラン(Free〜)も選べる
  • 無効化
  • 一定数を超えると有料
  • 名前を変える運用なら不要
  • 単価・無料枠・定額プランの中身は変わるので、料金ページで確かめる
  • ひらめき
  • S3 から CloudFront への転送は無料。CloudFront には無料枠や定額プランもある。

よくある落とし穴

S3 の事故の多くは、「公開してしまった」と「消えるはずのものが残った」のどちらかです。

事故何が起きるか防ぎ方
バケットを公開する写真以外のもの(バックアップ・ログ)まで読まれるブロックパブリックアクセスはオンのまま。見せるのは CloudFront で
アクセスキーを埋め込む漏れて他人にバケットを使われるIAM ロールを使う
署名付き URL の期限が長いURL が広まって使い回される数分にする
キーを利用者に決めさせる他人の写真を上書きされるキーはサーバーが uuid で作る
途中のアップロードの破片一覧に出ないまま課金され続けるライフサイクルで7日後に消す
バージョニングの古い版消したつもりの版が残って課金されるライフサイクルで古い版を消す
CloudFront の証明書を東京で作るCloudFront の画面で選べないus-east-1 で作る(第14章)

もう1つ、S3 のバケットを同じ名前で作り直そうとして作れない、という戸惑いもよくあります。従来のバケット名は世界で1つなので、消した直後の名前がしばらく使えなかったり、他人に取られたりします。名前はあまり使い回さないのが無難です。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 20 / 22
  • よくある落とし穴
  • NG
  • 手っ取り早く見せたくて、ブロックパブリックアクセスを外してバケットを公開する
  • NG
  • アクセスキーをアプリに埋め込み、漏れて他人にバケットを使われる
  • NG
  • 署名付き URL の期限を7日にし、URL が広まって使い回される
  • NG
  • 利用者にキーを決めさせ、他人の写真を上書きされる
  • NG
  • 途中で止まった大きなアップロードの破片が、見えないまま課金され続ける
  • NG
  • CloudFront 用の証明書を東京で作り、選べずに迷う(第14章)
  • ひらめき
  • S3 の事故の多くは「公開してしまった」と「消えるはずのものが残った」。どちらも設定で防げる。

片付け:CloudFront を止めて消し、バケットは空にしてから消す

片付けにはそれぞれ順番があります。

順番消すもの補足
1CloudFront のディストリビューションまず「無効化(Disable)」し、反映が終わってから削除する
2バケットの中身バケットは空でないと消せない。コンソールの「空にする」が使える
3バケット空になったら削除
4img.example.com のレコードと証明書Route 53 のエイリアスと、us-east-1 の証明書(第14章)

CLI で中身ごと消す例です(本当に消えてよいか、バケット名を必ず確かめてから)。

bash
aws s3 rm s3://photolog-photos --recursive
aws s3api delete-bucket --bucket photolog-photos

バージョニングを有効にしていた場合、ふつうの削除では古い版が残るので、コンソールの「空にする」を使うか、古い版も消します。

最後に確かめること。

確かめるもの理由
OAC とキャッシュポリシー料金はかからないが散らかる
Web のロールの S3 の権限要らなければ外す(最小権限)
翌日の請求S3 と CloudFront の料金が止まったか
  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 21 / 22
  • 片付け:CloudFront を止めて消し、バケットは空にしてから消す
  • インターネット
  • CloudFront
  • ファイル
  • オブジェクト
  • フォルダ
  • バケット
  • 場所
  • 名前と証明書
  • 無効化してから削除
  • 全部消す(空にする)
  • 空になったら削除
  • img. と us-east-1
  • OK
  • バージョニングを使っていたら、古い版も消えているか
  • OK
  • ロールに付けた S3 の権限も、要らなければ外す
  • OK
  • 翌日の請求で S3 と CloudFront の料金が止まったか
  • ひらめき
  • CloudFront は「無効化 → 反映を待つ → 削除」。バケットは中身が残っていると消せない。

まとめ:写真は S3 に預け、CloudFront で近くから配る

この章で見たことをまとめます。

項目内容
S3番号札で預ける倉庫(オブジェクトストレージ)。容量は実質無制限、複数 AZ に保管
バケットとキー入れ物と中身の名前。フォルダに見えるのはキーの頭
公開しないブロックパブリックアクセスはオン。サーバーはロールで使う
署名付き URL写真は利用者から S3 へ直接。Web は許可証を渡し、キーを DB に書くだけ
ストレージクラス読む頻度で置き場を分ける。ライフサイクルで自動化、途中物も片付ける
CloudFront世界中のエッジに写しを置き、近くから配る
OACS3 は閉じたまま、自分の CloudFront だけに読ませる
キャッシュTTL の間は写しを返す。中身を変えたら名前を変える

これで、00〜15章の部品がすべてそろいました。

役割部品
つなぐVPC・サブネット・IGW・NAT・ALB・Route 53・CloudFront
計算するEC2・Auto Scaling
しまうEBS・RDS・S3
守るIAM・セキュリティグループ・ACM

でも、部品を1つずつ学んだだけでは、「全部をどう並べ、どの順に作ればいいのか」はまだ見えにくいはずです。次の第16章では、これらを1つの3層の Web 構成に組み上げ、利用者のリクエストが最初から最後までどこを通るのかを追いかけます。

  • AWS でサービスを作る 15 ― S3 と CloudFront
  • 22 / 22
  • まとめ:写真は S3 に預け、CloudFront で近くから配る
  • S3
  • 番号札の倉庫。容量無制限・複数 AZ に保管
  • バケットとキー
  • 倉庫の名前と荷物の名前。フォルダは名前の一部
  • 公開しない
  • ブロックパブリックアクセスはオン。権限はロールで
  • 署名付き URL
  • 写真は S3 へ直接。Web は許可証とキーの記録だけ
  • ストレージクラス
  • 読む頻度で置き場を分ける。ライフサイクルで自動化
  • CloudFront
  • エッジにキャッシュし、近くから配る
  • OAC
  • S3 は閉じたまま、CloudFront だけに読ませる
  • キャッシュ
  • 中身を変えたら名前を変える
  • ひらめき
  • 次の第16章:ここまでの部品を1つの Web 構成に組み上げ、リクエストの一生を追う。

0 件のコメント

読み込み中…

権利侵害・不適切な内容の連絡: [email protected]