AWS S3にブログを移行

(更新日時 )

カテゴリー:  Tech タグ:  aws cloud s3 weblog

AWS

ブログにCloudFlareを利用していましたが、今回AWS S3に移行してみました。 しばらく運用してみて、費用などを見て見直すかもしれませんが。

(2024-11-05更新)

S3のStatic website hostingをdisabledにしS3は純粋のストレージとし、 CloudFrontがコンテンツ配信とURL制御を担当するよう見直しました。

AWS S3に移行した訳

以前はNetlifyを長らく使っていましたが、ビルド環境が古くMermaidのプラグインが 使えないなどの問題があったため8月にCloudFlareに移行させたばかりです。

今回CloudFlareで問題があったわけではないのですが、次のような理由からS3に移行 させてみました。

  • ローカルで確認のためにビルドしているので、CI/CDの乗せて再度ビルドするのは 無駄のような気がした。
  • いずれCloudFlareでもNetlify のように環境が合わない状況に陥る可能性はある。
  • S3でまじめにホスティングしたことないので、技術的な興味のため

AWS S3にコンテンツを乗せる手順

おおまかな手順としては次の通りです。

  1. S3 Bucketを作成する
  2. AWS Certification Manager(ACM)で証明書を作成する
  3. CloudFrontでDistributionを作成する

想定費用

実施する前に、AWS 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の問題でたまに全ファイル生成する場 があるためです。

まとめ

今回はどちらかという技術的な興味から移行してみました。

AWS S3&CloudFrontでの静的ウェブサイトホスティングは、AWSでシステムをやっているとどこかで遭遇する対応なので 継続するかどうかはともかくやり方は確認しておたほうがよいと思いました。

CloudFlareと比較すると、可用性の高いS3とCloudFrontのグローバルな高速配信が安 価で使用でき、AWSエコシステムとの統合が容易なのは魅力的だと思います。

ただ、デメリットとしては、CloudFlareと比較してコスト管理がより複雑がちです し、一部の高度なDDoS保護機能がCloudFlareほど包括的でなかったりします。 自動デプロイを組もうとするとAWSの場合CodeCommitの行方が不明確なのでちょっと 戸惑いますね。

しばらく運用してみて飽きて戻すかもしれませんが・・・

コメント

Comments powered by Disqus