はじめに
よくあるAPIサーバとStaticコンテンツサーバの構成を廃止して、S3とCloudFrontに移行してコスト削減をした話
背景
世の中には商品などのリリースを出すためのLPサイトが無数にあるのではないでしょうか。
自分が担当していたLPサイトもよく見る下記のようなシステムで動いていました。冗長構成は省きます。

説明すると、
商品情報はMySQLに保存され、登録・更新があるので管理ツールからデータを追加・更新出来ます。管理ツールで登録されたデータはフロントのAjaxから呼び出されAPIサーバ経由で配信されます。
ただ、上記システムだとEC2やMySQLがいるためインフラコストが多大にかかっていました。そこで、更新(API)があるLPページをS3とCloudFron(CF)に移設した際のtipsを説明します。
目指したシステム構成
tips
- staticコンテンツをS3に配置
- APIで配信していたJSONデータをS3に配置しメタデータを付与
- S3をCFで配信
- (おまけ)PCとSPの切り替えはLambda@Edgeでコントロール
staticコンテンツをS3に配置
- S3にstaticコンテンツ配置
- ROOT配下のディレクトリもindex.htmlを参照させたいとき
Webホスティングの設定 を参考にする。
http://domain/hoge/ を /hoge/index.html で配置している場合は↑を設定するのが簡単。
APIで配信していたJSONデータをS3に配置しメタデータを付与
- APIで返していたJSONデータをJSONファイルに書き出す
curlなどを使ってshellで回してJSONを保存すのが良い - JSONファイルをS3に配置
- JSONファイルのメタデータに
Context-Type:application/json; charset=utf-8付ける
(おまけ)PCとSPの切り替えはLambda@Edgeでコントロール
今まではNginxでUAを見てURIの先頭の /pc/ と /sp/ をコントロールしていました。
これをS3+CF環境で実現するためにLambda@Edgeを利用して、URIのコントロールを実現しました。
CloudFrontのビュアーリクエスに下記Lambda@Edgeを仕込むと / をUAを見て判断してくれます。
## python##
import json
sp_list = [
'Android',
'iPhone',
'iPad'
]
def lambda_handler(event, context):
request = event['Records'][0]['cf']['request']
headers = request['headers']
ua = headers['user-agent'][0]['value']
# 書き換え対象
if request['uri'] in ['/', '/index.html', '']:
for sp in sp_list:
if sp in ua:
request['uri'] = '/sp/'
return request
request['uri'] = '/pc/'
return request
今回話さなかったこと
新たなデータを登録したい時はJSONを作る必要がありますが、頑張ってください。
まとめ
EC2とMySQLで作られたシステムを
S3とCFのみを使った簡潔なシステムにリプレイス出来、運用コストを大幅に削減できました。

