Amazon S3にブログを移行
(更新日時 )

ブログにCloudFlareを利用していましたが、今回Amazon S3に移行してみました。 しばらく運用してみて、費用などを見て見直すかもしれませんが。
(2024-11-05更新)
S3のStatic website hostingをdisabledにしS3は純粋のストレージとし、
CloudFrontがコンテンツ配信とURL制御を担当するよう見直しました。
Amazon S3に移行した訳
以前はNetlifyを長らく使っていましたが、ビルド環境が古くMermaidのプラグインが 使えないなどの問題があったため8月にCloudFlareに移行させたばかりです。
今回CloudFlareで問題があったわけではないのですが、次のような理由からS3に移行 させてみました。
- ローカルで確認のためにビルドしているので、CI/CDの乗せて再度ビルドするのは 無駄のような気がした。
- いずれCloudFlareでもNetlify のように環境が合わない状況に陥る可能性はある。
- S3でまじめにホスティングしたことないので、技術的な興味のため
Amazon S3にコンテンツを乗せる手順
おおまかな手順としては次の通りです。
- S3 Bucketを作成する
- AWS Certification Manager(ACM)で証明書を作成する
- CloudFrontでDistributionを作成する
想定費用
実施する前に、Amazon S3を利用する場合CloudFlareと違って無料枠ではないので、ある 程度見込み立てておきましょう。
AWS静的ウェブサイトホスティングの月間コスト見積もり
前提条件をまとめてると、私のブログは過疎っているので下表のような感じです。平 均転送量については、もっと小さいかもしれません。
| 項目 | 値 |
|---|---|
| コンテンツ総容量 | 300 MB |
| 1日のアクセス回数 | 100 回 |
| 1アクセスあたりの平均転送量 | 3 MB |
上記の条件でざっくり月額を見積もると、下表のようになります。
| サービス | コスト項目 | 月間コスト (USD) |
|---|---|---|
| S3 | ストレージ | $0.0075 |
| S3 | GET リクエスト | $0.0012 |
| ACM | 証明書 | $0 |
| CloudFront | データ転送 | $0.765 |
| CloudFront | HTTPS リクエスト | $0.00225 |
| 合計 | $0.78 |
見積もりは概算で、実際には更新頻度やアクセスパターンで変わってきますが、 S3はとっても安価でACMは無料なのでそれほど大きくブレることはないでしょう。
S3 Bucketの作成と設定
今回作成したBucketの設定内容とBucket Policyです。
| 項目 | 値 |
|---|---|
| バケット名 | notes.inegales.com |
| ロケーション | ap-northeast-1 |
| バージョニング | none |
| 有効期限ルール | none |
| パブリックアクセスブロック | on(Default) |
| CORS | none |
| ACL | FULL_CONTROL |
| S3 static website hosting | Enable |
| Hosting Type | Host a static website |
| Website endpoint | 自動設定されたものを利用 |
| index document | index.html |
| error document | (None) |
Bucket Policyを以下のようにセットしてCloud Frontからアクセスできるようにしま す。実際には以下のコードはCloudFrontでOACの設定を行うとコードを生成してくれ るので、その後コピー&ペーストすれば大丈夫です。
{ "Version": "2008-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [ { "Sid": "AllowCloudFrontServicePrincipal", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::notes.inegales.com/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::376851978118:distribution/E10OX2LDNXKC9Z" } } } ] }
ACM証明書の作成
AWSで証明書を作成しますが、ここで重要なのはリージョンをus-east-1に切り替 える必要があります。理由は、証明書を利用するCloudFrontはグローバルサービスで us-east-1のACM証明書のみを利用できるからです。
設定内容な次の通りです。
| 項目 | 値 |
|---|---|
| ドメイン名 | notes.inegales.com |
| 検証方法 | DNS検証 |
| キーアルゴリズム | ECDSA P-256 |
検証方法に「DNS検証」を設定したため、DNSの設定を行います。私はGodaddyを使用 しているので以下の設定は、Godaddy上で行っています。
設定方法は、ACMのDomainsにCNAME nameとCNAME valueが表示されているので、それ をコピーして、DNSでCNAMEレコードを作成します。
CNAMEレコードを作成すると、証明書(Certicate)のステータスがIssuedに変わりま
す。(DNSの反映に時間がかかることがあります)
Cloud Frontの設定
Cloud Frontの設定内容は次の通りです。
| 設定項目 | 値 |
|---|---|
| Origin Domain | (S3 Bucket website endpointの値) |
| Origin access | Origin access control setteings |
| Origin access control | (Create new OACにより作成します。) |
| Viewer Protocol Policy | Redirect HTTP to HTTPS |
| Cache policy name | 次表参照 |
| Reponse headers policy | Managed-SecurityHeaderPolicy |
| Allowed HTTP Methods | GET, HEAD |
| Price class | Use all edge locations |
| Alternate Domain Names (CNAME) | notes.inegales.com |
| Custom SSL Certificate | ACM証明書 |
| Compress Objects Automatically | Yes |
| Default Root Object | index.html |
| Security Policy | TLSv1.2_2021 |
| WAF | Do not enable security protections |
| Standard Logging | Off |
| IPv6 | On |
WAFとログ記録は、今回静的コンテンツを載せるだけなので無効にしています。
"Create new OAC"を行うとS3のBucket Policyを生成してくれるので、コピーしてS3 のBucket Policyに貼り付けます。
キャッシュポリシーを以下のように設定します。
| Policy名 | ShortTTL-Policy-HTML-RSS | LongTTL-Policy-images |
|---|---|---|
| Path Pattern | /images/* | Default(*) |
| Minimum TTL | 0 | 0 |
| Maximum TTL | 60 | 31536000 |
| Default TTL | 60 | 31536000 |
| Compression | Gzip/Brotli | Gzip/Brotli |
(2024-11-05追記)
CloudFrontがS3のREST APIエンドポイントを使用している場合、サブディレクトリのindex.htmlファイルを自動的に解決することができません。
例えば、/about/というパスへのリクエストは、S3では/about/index.htmlとして解決されず、アクセス拒否エラーとなります。これを解決するために、CloudFront Functionsを使用してURLのパスを適切に変換する必要があります。以下がそのコードです。
function handler(event) { var request = event.request; var uri = request.uri; // URIが/で終わる場合、index.htmlを追加 if (uri.endsWith('/')) { request.uri += 'index.html'; } // 拡張子がない場合もindex.htmlを追加 else if (!uri.includes('.')) { request.uri += '/index.html'; } return request; }
このFunctionをPublishしたら、
CloudFrontディストリビューションのViewer Requestイベントに関連付け
ます。
ローカルからS3へのアップロード方法
GitLabリポジトリから自動ビルドをやめてしまうので、自身でローカルで生成したコ ンテンツをアップロードする必要があります。
ブログの生成にはNikolaを使用しており、一連の作業はターミナルで実施しているの
でコマンドラインから実施アップロードできる方法としてs3cmdを使用することに
します。Macの場合 Homebrewがインストールされていればbrew install s3cmdでイ
ンストールできます。
s3cmdには同期コマンドがあるので、次のようにS3にアップロードを行います。
s3cmd sync --check-md5 --delete-removed "./output/" s3://notes.inegales.com
これで、次のことが行われます。
- md5チェックサムを計算し、チェックサムが変更されているファイルのみ同期対象 となる。
- ローカルから削除されたファイルは、S3 Bucketからも削除される。
単純に日付で差分を取っていないのは、Nikolaの問題でたまに全ファイル生成する場 があるためです。
まとめ
今回はどちらかという技術的な興味から移行してみました。
Amazon S3&CloudFrontでの静的ウェブサイトホスティングは、AWSでシステムをやっているとどこかで遭遇する対応なので 継続するかどうかはともかくやり方は確認しておたほうがよいと思いました。
CloudFlareと比較すると、可用性の高いS3とCloudFrontのグローバルな高速配信が安 価で使用でき、AWSエコシステムとの統合が容易なのは魅力的だと思います。
ただ、デメリットとしては、CloudFlareと比較してコスト管理がより複雑がちです し、一部の高度なDDoS保護機能がCloudFlareほど包括的でなかったりします。 自動デプロイを組もうとするとAWSの場合CodeCommitの行方が不明確なのでちょっと 戸惑いますね。
しばらく運用してみて飽きて戻すかもしれませんが・・・