SPA アプリケーションのフロントエンド配信を AWS CloudFront + S3 にした話

アイキャッチ

はじめに

こんにちは!インフラチームの若さ担当、高畑です。 最近はウィンタースポーツのやりすぎでブログ書くのをだいぶサボってしまったので気合い入れて思いの丈を綴っていこうと思います。

今回は、コンテンツ制作に特化したオンラインの編集チームを構築するサービスである「エディトル」のフロントエンド配信を AWS EC2 から CloudFront + S3 に切り替えた話をします!

client.editoru.jp

これまでの構成

今までのエディトルはざっくりこんな感じで、フロント(React + TypeScript)と API でインスタンスを分けて Nginx からそれぞれコンテンツを返すような構成でした。

切り替え前の構成図

エディトルはいわゆる SPA アプリケーションと呼ばれるもので、フロントサーバは HTML と JavaScript を返却するために稼働をしており、PHP のように何か処理を行った結果を返却するわけでもないので、サーバのリソースはいつの時でも有り余っているような状態となっていました。

CPUリソースのグラフ

メモリリソースのグラフ

なぜ今の構成から変えるのか

今動いている環境から CloudFront + S3 配信へ切り替えには様々な理由があったりするのですが、その中でも「サーバコスト」と「耐障害性の向上」が主な理由です。 静的コンテンツを配信するために EC2 インスタンスを動かしていると、上述したようにサーバリソースを持て余すことになったりします。 その上で耐障害性を担保するために冗長構成を取っているため、コストパフォーマンスに見合わない状態となっていました。

そこで、CloudFront + S3 に置き換えることによって実際に利用した分だけ従量課金でかかるようになり、結構なコスト削減が見込めるのではないかと思いました。 また、EC2 で運用を行っていることによりインスタンス障害やリタイアメントの影響を受けたりと、安定稼働を行うために考えておくことが山積みな状態となっていました。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instance-retirement.html

これを CloudFront + S3 配信に切り替えることにより、S3(標準ストレージクラス) の SLA 99.99%、CloudFront の SLA 99.9% を掛け合わせた SLA 99.89% の恩恵を受けられることになります。

あとは余談ですが、SPA を配信するならサーバレスでやりたいという欲求も一つの理由ですね。

CloudFront + S3 配信の構成

実際に CloudFront + S3 配信に切り替えた時のざっくり構成図はこんな感じになりました。

切り替え後の構成図

フロント部分をごっそり CloudFront + S3 に持っていくことにより、これまで運用していた EC2 サーバを削減することに成功しました。 ユーザがエディトルにアクセスすると、CloudFront へリクエストが飛び S3 に配置された静的コンテンツを返すような仕組みになっています。 SPA アプリケーションなので、ブラウザから叩きにくる API は EC2 + ALB で運用を行っています。

移行してまだ然程たっていないのですが、CloudFront の料金は大体月あたり $5 前後で推移しています。

移行に際して悩んだこと

社内に CloudFront のナレッジが全然ない

これまで画像配信に CloudFront を利用するケースはちょっぴりあったのですが、SPA アプリケーションを CloudFront で配信するナレッジが社内になかったため、いろいろと手探りで構築を行いました。 様々な事例を参考にさせていただきなんとか実現することができたので、社内のナレッジとしてドキュメントにまとめたりしていました。

CloudFrontの社内ドキュメント

メンテナンスの時どうやってメンテナンスモードにしよう

これまでは Nginx から 503 ステータスを返すなり、ALB から 503 レスポンスを返すなりで対応できていたのですが、 CloudFront + S3 の場合どのようにメンテナンスモードへ移行するか議論を行いました。 フロント側で 503 ステータスを返すにしても、ブラウザキャッシュの影響等で一斉にメンテナンスモードに移行するのは難しかったので、API 側で 503 ステータスを返せるようにしました。

これにより、エディトルを利用しているユーザ全て同時にメンテインできるようになったので、突然のメンテナンスが仮に起こっても問題ない状態となりました。

今後の展望(野望)

今後は API 側も API Gateway + Lambda 構成などにしてサーバレスなサービス運用を行えれば良いなと勝手に企んでいます。 これに関してはアプリケーション側とのすり合わせを入念に行う必要があるため、時間はかかるかもしれませんが近い将来実現できたら良いなと思っています。

また、現状 CloudFront のアクセスログ解析が十分にできるような状態ではないため、こちらは早急に進めていければと思っています。

おわりに

今回、EC2 で配信していた SPA アプリケーションを CloudFront + S3 配信に切り替えを行いましたが、まだまだやらなければいけないことが山積みなのでどんどん改良していければ良いなと思っています。 「目指せ夢のサーバレス」を目標に今後も頑張っていきます!