皆さん、こんにちは! 昨日の@iwadoooo_77さんの記事にてご紹介いただいた25卒内定者の@koinunopochiです!
やりたかったこと
- 個人ブログを持つのが夢であるので、運用できる範囲で公開したい。
- せっかくなのでほかの人も記載が可能な形にしたい。
当初は1. 個人ブログを持つのが夢であるので、運用できる範囲で公開したい。を行いたい程度で、サクッと公開するつもりだったので利用したことのある技術を利用して作成しました。
この段階では、いつも通りのコスト感覚でした...
具体的には以下の構成で行うつもりでした。
- バックエンド
- Laravel
- MYSQL
- フロントエンド
- React SPA
そしておおよそ次のような構成で公開する予定でした。
金銭的な余裕はないので、冗長化は行わない予定でした。
冗長化がない以外は特別変な構成ではなく比較的ありふれた構成だと思います。
問題の発生
ただ作っている間に一つ問題が発生しました。
AWSのアカウントを作成してから1年が経過しまったのです。
そろそろ個人アカウントの無料枠が切れることはわかっていたのですが、最小構成であればそこまでの金額にならないだろうと、それまで楽観視していました...
問題の発覚
とりあえず最低限見ることのできる体裁が整ったので、IP制限でもして構築しようと改めて金額を計算したところ次のようになりました。
今回の計算は、以下のサイトを利用して概算で出しています。
あくまでも概算用のツールですが便利なので重宝しています。
前提:
月間1万PVも行くとは思わないものの、1万PVで計算していきます。
また、計算を簡単にするために1ページ2mbとします。
2 * 10000 / 1024 ≒ 20GB
今まで個人では無料枠を利用していたので、基本t2.microしか利用したことがなかったのですが、新しいほうが安いんですね...
知らなかった...
ざっくり1,000円~3,000円程度で維持できるようです。
金欠なので基本は最小構成を選択します。
次に、RDSの金額を概算します
写真以外の記事などの情報を保存する予定です。
そもそも利用量ベースでも固定費として3,000円近くかかるようです。
個人で運用する分には、3,000円~4,000円程度が月の金額になりそうです。
個人的にはこれだけでもコストオーバーです...orz
次に、S3を概算します。
記事の写真やアイコンなどを保存する予定ですが、Iconはプリセットからの指定に制限するので、実質的には記事の画像が大部分が占める形になります。
こちらもざっくり1枚2MB程度として、平均記事に2枚程度あると仮定します。
記事の量は5,000記事分もあれば2~3年後の月間料金を求められそうです。
容量
2 * 2 * 5000 / 1024 ≒ 20GB
データ転送量
2 * 2 * 10000 / 1024 ≒ 40GB
分かっていましたが、S3は安いですね...
次にCloudFrontを概算します。
S3のアクセスはすべて通すつもりなのでこのような感じにしました。
これまでの中で最も安くて安心します...
次にELBについて概算しようと思います。
負荷分散は今回利用できないので、証明書とサーバーの監視で利用しようと考えています。
ELBも思ったより高いですね...
アクセスがほとんどないだろうと概算してこれなので、金欠運用では利用を躊躇してしまいます。
次にRoute53を計算します。
名前解決を行うために、利用します。
安くて安心して利用できます...
概算結果をまとめてみる
- EC2: 1,137円
- RDS: 2,621円
- S3: 775円
- CloudFront: 110円
- ELB: 3,617円
- Route53: 94円
初月の維持費がざっくり8,000~ということになりそうです...
流石にこれだけの金額を毎月趣味に投入できるほどの余裕がありません。
ELBは本来の用途では利用していないためなくてもよいですがそれでも予算オーバーです。
ある程度DDD的な思想でプロジェクトを構成していたため、RDSをS3に移行しても問題はないですがS3にこれまでのDBの中身をまとめるのは難しいと感じます。
Athenaを利用すれば、S3を全文検索して記事を取ってくることは可能であるものの効率が悪く高くむしろついてしまうというのもS3に全部載せるのを躊躇してしまうポイントです。
スケールメリットを捨ててEC2OnDBという悪法を行うことも可能ですが、やはりデメリットのほうが大きいと感じます。
そこで次のような構成を考えたました。
新しい構成
変更点は、ロードバランサーをなくした点と、Cognitoを導入しRDSからDynamoDBに変更した点です。
また現状はLaravelをEC2に配置していますが、将来的にはLambdaに完全に移行したいと考えています。
それぞれを解説していこうと思います。
ロードバランサーの不採用
まずロードバランサーは、個人で運用するには高すぎました...
今回の要件としてはHTTPSからのアクセスかつ、S3からのアクセスに限定してやることが重要です。
このような具合にCloudFrontを利用してやれば最低限アクセス制限は可能そうです。
ひとまず目的を達成することができるので今回はロードバランサーは利用しないこととします。
CognitoとDynamoDBの採用理由
Cognitoを利用して認証を行うように変更した理由としては、RDBからNoSQLへ移行したことが根本にあります。
RDBでは必要がないですが、NoSQLではトランザクションなどの管理をアプリケーション側で持つ必要があります。
きちんと対処すれば解決ですが、手間がかかるので今回は見送った形になります。 (本来の用途外のものをいじくりまわしてもいいことないですし...)
DynamoDBを採用した理由としては無料枠が使えるからです。
それ以上でも以下でもありません。
今回の用途であれば検索の柔軟性などの点からRDBを利用したいので、本来であれば候補には上がりませんでした。しかし、25GBまでであれば無料で利用できることで、相当数の記事が増えない限りは通信コストだけで運用が可能であるため
利用する予定です。
ただし記事などの情報を直接保存してしまうと容量を早期に食いつぶす危険性があるため、基本的には記事のメタ情報などを保存してindex的に利用する予定です。
EC2からLambdaへ
EC2から移行することで、最終的な運用コストのほとんどがS3ストレージの料金とすることが可能です。
最終的な金額
- EC2: 1,137円 (Lambdaに移行すると0円)
RDS: 2,621円-> DynamoDB: 0円- S3: 775円
- CloudFront: 110円
ELB: 3,617円-> 廃止のため0円- Route53: 94円
≒ 2,200円
Lambdaに移行すればさらに1,000円程度下がる予定です。
コストと引き換えにしたもの
本題のコスト削減(月額8,000円→2,200円)には成功しましたが、いくつかの重たい制約を受け入れることになりました。
AWSへの依存度の増加
当初はLaravelとMySQLという標準的な構成だったため、他のクラウドサービスへの移行も選択肢でした。しかし新しい構成では、Lambda、DynamoDB、Cognitoといったサービスに深く依存します。将来的にAWSの料金が上がったり、より安いサービスが登場しても、移行には大規模な書き直しが必要になるでしょう。
できることが限られる
データベースをNoSQL(DynamoDB)に変更したことで、記事の検索方法が制限されます:
- 複数のタグやカテゴリを組み合わせた複雑な検索
- コメント機能のような、データ間の関連付けが必要な機能
- 記事の並び替えや絞り込み
これらの実装が難しくなるか、処理が複雑になります。「こんな機能があったら便利だな」と思いついても、技術的な制約で諦めざるを得ないケースが増えそうです。
構造化して直接紐づけてしまうなど対策はいろいろとあれど、ベストプラクティスから外れることで普通では発生しないなどニッチな問題にも多く遭遇することになりそうです。
開発のしづらさ
サーバーレス構成では:
- ローカル環境でのテストが面倒
- エラーが発生したときの原因特定が困難
- 新機能追加時の実装が複雑化
特にチーム開発では、これらの課題への対応方法の共有も必要です。
今のところ個人開発ですが、今後チーム開発などを行う場合は全体像の把握など難易度が上がってしまいます。
動作の安定性への影響
Lambdaを使用することで、アクセスが少ないときに最初のレスポンスが遅くなる「コールドスタート」という問題が発生します。現状の個人ブログの運用としては許容範囲ですが、サービスの成長に従って見直しが必要になる可能性があります。
これまでのバックエンドを捨てる
当初のLaravelプロジェクトには愛着があります。DDD(ドメイン駆動設計)の考えを取り入れ、比較的きれいなアーキテクチャで設計していました。また他の人の記事も投稿できるようにと、認証やロールの仕組みもある程度実装済みでした。
これをコスト削減のためにすべて捨て、Lambda+DynamoDBという制約の多い構成に移行することには、エンジニアとして、作成者として少し寂しさを感じます。とはいえ、月8,000円という個人ブログの運用コストは現実的ではありません。
ただ、このような制約のある環境でやりたいことを行うのはなんだかんだで楽しそうです。
しばらく運用した後に、運用時のコストを考えすぎて運用・改修がにっちもさっちも行かなくなった話
とならないようにしたいものです。
まとめ
今後も個人開発では「運用コスト > 技術的な柔軟性」というトレードオフを迫られそうです。やはり毎月の固定費を抑えることが重要になってきます。
ただし、セキュリティに関する部分はコストを惜しまないようにしたいと考えています。公開時にはAWS WAF
の導入も検討しています。セキュリティに関するコストは、インシデント対応を考えると十分な価値があるでしょう。
アクティブユーザーが5万人を超えるとCognitoのコストも考慮が必要になってきますが...そこまでの規模になることは期待できそうにありません... orz
結局のところ、システム設計は「コスト」「運用性」「セキュリティ」など、様々な要素のバランスを取る必要があります。今回の場合、コストを重視した結果として技術的な制約を受け入れることになりました。組織として重視する点は異なるかもしれませんが、システム設計時にはその組織やプロジェクトにとって重要な要素を見極め、適切なバランスを取ることが大切だと実感しました。