最近 S3とCloudFrontでReactJSアプリの運用コストを削減 できる方法が効果的ではないかかという悩みがインタネット上で頻度が高く寄せられています。 ここ数ヶ月、サーバー担当者として弊社最大規模のプロジェクトにジョインしていました。規模が大きいですから、お客様がAWSに支払わなくてはならないコストの大きさも半端ではありません。ジョインから3ヶ月ぐらいの時に、運用の安定性を保ったままコストを削減できる方法はないかと、リクエストを頂きました。 色々考えた末、1つの点に思い当たりました。すべてのソースコードはElasticBeanstalk経由でEC2にデプロイされています。AWSの費用が決して安くないことは皆さんもご存知でしょう。
解決方法
EC2の費用が安くないとすると、他の何かに変えてみたらどうでしょうか? もしできるとしたらどのリポジトリでしょうか? 本プロジェクトには巨大なソースコード群が存在し、そのソースが各リポジトリに分割され、ヘッドレスモデル的に構築されています。つまり、クライアントのリポジトリ(ReactJSでコード)があり、バックエンドのリポジトリ(PHPでコードされたAPI)もあります。そして改めて検討すると、EC2にデプロイする必要がないリポジトリが見つかりました。それは、ReactJSでコードされたクライアントリポジトリです。 なぜ必要ないのでしょうか? それは、一度ソースコードをデプロイしてしまえば、私達が取得するのは静的なhtmlファイル、cssファイル、js、画像ファイルだけだからです。そして、そのようなファイルを最も安価かつ簡単に保存できるのは? 間違いなくS3でしょう。 しかし、S3はEC2のように自動スケーリングできないため、アクセス数が多い場合に、どのように処理させたらよいでしょうか。その答えはCloudFrontです。 最終的には、S3とCloudFrontを組み合わせて、顧客のコスト削減問題を実現することにしました。
前提
用意するもの
- 静的HTMLファイル、画像、CSS、JSを含むWebサイトコンテンツを保存するS3バケット
- CDNおよびドメインでウェブサイトコンテンツを配信するCloudFrontディストリビューション
- SSL証明書を発行して、ドメインの認証を行うACM
- ドメイン
実行手順
ステップ1:S3バケットを作成
参考: S3 バケットの作成方法 ポイント:セキュリティを確保するために、新規作成されたS3バケットを公開しないのがおすすめです。
ステップ2:CloudFront ディストリビューションを作成
参考:CloudFront ディストリビューションの作成方法 ディストリビューションを作成した後、ディストリビューションIDをメモしておいてしてください。 このディストリビューションIDがS3バケットポリシーの設定に必要となります。
ステップ3:S3バケットポリシーを作成
前述のように、セキュリティを確保するために、新しいS3バケットは公開しません。 Cloudfrontがコンテンツを取得するために、作成したS3バケットポリシーの作成が必要です。 参考:S3 bucket allow access only from CloudFront Distribution
ステップ4:CI CDを使用してReactJSビルドファイルをS3にデプロイ
2ステップでデプロイしましょう。 まず、S3に組み込まれた後に、すべての変更を同期する必要があります。aws s3 sync コマンドを使います。 aws s3 sync $DEPLOY_DIR/ s3://$S3_BUCKET/ 次に、変更をすぐに有効にするには、CloudFrontがキャッシュしたすべてのデータを無効にする必要があります。aws cloudfront create-invalidationコマンドをを使います。 aws cloudfront create-invalidation –distribution-id $DEV_CLOUDFRONT_ID –paths ‘/*’
結果
ソリューションを実装してから2か月後、結果は明白でした。 システム運用コストが顧客の期待どおりに削減されていることは、以下のAWSアカウントの請求詳細に示されています。 2019年11月:21,800ドル 2019年12月:20,200ドル(1,600ドル減)
検討課題
多くのWebサイトでは、アクセスを制限できるようににbasic認証が必要です。そのようなWebサイトでS3とCloudFrontを使用する場合、無名関数(lambda 関数)の追加が必要になります。 このやり方は、使用するフレームワークに関係なく、どの静的なウェブサイトでもに適していると思います。