はじめに
こんにちは、エンジニアの田畑です。
今回は社内イベントで使用していたWebサービス(以下「サービス」と呼ぶ)のインフラを、FirebaseからAWSに移行した事例を紹介します。
この社内イベントは、普段お世話になっているお客様をオフィスに招き、おもてなしをする場であり、約800名が来場する大規模なイベントです。 そのため、より安定したインフラが求められることから、FirebaseからAWSへ移行しました。この移行は単なるクラウドサービスの切り替えではなく、セキュリティや運用のしやすさを考慮した上で実施しました。
本記事では、旧インフラの構成とその課題を振り返り、新たな設計のポイントを解説するとともに、移行を通じて得られた知見や課題についても共有していきます。
目次
- サービスの要件
- 旧インフラ構成
- 旧インフラ構成の課題
- 新インフラ構成
- 課題をどう解決したか?
- なぜDynamoDBを利用したのか?
- 移行を通じて学んだこと
- 今後の課題
- API Gatewayへのアクセス保護
- 最後に
サービスの要件
本サービスは、イベント会場で来場者をスクリーンにリアルタイム表示させることを目的としています。
まずは、サービスの利用状況や要件について整理します。
人数規模
・約800人
リアルタイム表示
・現在入室している参加者の情報をスクリーンに表示
来場者検知
・入室した参加者をリアルタイムで検知し、情報をサービス内に反映
旧インフラ構成
上記の要件を満たすための、Firebaseを活用した旧インフラ構成は以下の通りです。
処理の概要
① CloudFront経由でS3に配置したサービスにリクエスト
S3は静的webサイトホスティングに利用し、CloudFrontを経由してリクエストを受け付けます。
② フロントエンドでデータを取得
フロントエンドからFirebaseに直接データフェッチを行います。
③ 1分おきにスプレッドシートから最新データを取得しFirebaseに反映
入室者の管理はスプレッドシート上で行います。手動で「入室フラグ」をチェックし、GASを用いて1分おきにデータを取得し、Firebaseに保存します。
最新データ反映までのフロー
- スプレッドシートの「入室フラグ」を手動で更新
- GASが1分ごとにデータ取得
- 最新の入室データをFirebaseに保存
- Firebaseからデータを取得し、スクリーンに表示
旧インフラ構成の課題
画像のリンク切れ
Firebaseに保存した画像URLの有効期限が切れていたり、元データが削除されたりすると、スクリーンに表示できなくなります。また、次回のイベント利用時にも画像リンク切れが発生する可能性があります。
Firebaseの認証キーがブラウザから見えてしまう
フロントエンドから直接Firebaseにアクセスするため、認証キーがブラウザ上に表示されてしまいます。設計上は問題ありませんが、セキュリティ面で不安が残ります。
URLを知っていれば、外部の人でもアクセスできてしまう
URLは非公開ですが、万が一共有された場合、アクセス制限がないため外部の人も閲覧できてしまう恐れがあります。
新インフラ構成
前述の課題を踏まえ、AWSベースの新しいインフラ構成に移行しました。
処理の概要
① CloudFront経由でS3に配置したサービスにリクエスト
S3は静的webサイトホスティングに利用し、CloudFrontを経由してリクエストを受け付けます。そして、CloudFrontにWAF(Web Application Firewall)を設定し、特定のIPアドレスのみアクセス許可するようにセキュリティを強化しました。
② フロントエンドでデータを取得
①で取得したアプリ内でAPI Gatewayへのフェッチを通じてLambdaを呼び出し、LambdaはDynamoDB からデータを取得します。
③ Lambdaがスプレッドシートから最新データを取得し、DynamoDBに反映
1分ごとにEventBridgeがLambdaを起動し、スプレッドシートのデータを取得してDynamoDBに保存します。GASではなくLambdaを使用した理由として、AWSリソースとの統合が容易だからです。
最新データ反映までのフロー
- スプレッドシートの「入室フラグ」を手動で更新
- EventBridgeが1分ごとにLambdaを起動し、データを取得
- 最新の入室データをDynamoDBに保存
- DynamoDBからデータを取得し、スクリーンに表示
課題をどう解決したか?
旧インフラ構成で生じていた課題を踏まえ、それらをどのように解決したのかを新インフラ構成の改良点とともに紹介します。
画像のリンク切れの解決
Firebase→S3
FirebaseではなくS3に画像を保存し、バージョニングを有効化しました。バージョニングを有効にすることで、誤って削除したり上書きしてしまうリスクにも対応できます。
Firebaseの認証キーがブラウザから見えてしまう問題の解決
Firebaseにフェッチ→API Gatewayにフェッチ
API Gateway経由でデータ取得することで、ブラウザから認証キーが見えなくなりました。
URLを知っていれば、外部の人でもアクセスできてしまう問題の解決
CloudFront + WAF
エントリーポイントであるCloudFrontに、指定したIPアドレスのみアクセス可能とするWAFを設定しました。 この対応により、URLが万が一共有された場合でも、外部からのアクセスが制限される構成となっています。
なぜDynamoDBを利用したのか?
DBを選定する際、まずRDSが候補に挙がりました。理由として、個人的に馴染みがあったこと、一方でDynamoDBなどのNoSQLに馴染みがなかったことがあります。 しかしサービスの要件やユースケースを整理した結果、RDSよりDynamoDBの方が適していると判断しました。
その理由を説明する前に、まずRDSとDynamoDBの概要を簡単にまとめます。
RDS
特徴
- フルマネージドなリレーショナルデータベース
- 複雑なデータ操作や柔軟なクエリが可能
料金
- 「稼働時間 ✖️ 性能」で課金される
- 常時稼働するインスタンスに対して料金が発生
参考
DynamoDB
特徴
- Key-valueおよびドキュメントデータモデルをサポートするNoSQLデータベースサービス
- 検索に利用できるのはパーティションキー(Partition Key)とソートキー(Sort Key)の2つまで
- 複雑なデータ操作はできない
料金
- 「読み込みコスト ➕ 書き込みコスト」で課金される
- 使用量ベースの従量課金のため、アクセス頻度が低ければコストを抑えやすい
参考
Amazon DynamoDB の特徴 Amazon DynamoDB 料金
DynamoDBの方が適していた理由
サービスの要件を踏まえた結果、DynamoDBが最適と判断しました。 主な理由は以下の2点です。
1. アクセス数が少ないため、コストを抑えられる
本サービスは来場者をスクリーンに表示する用途であり、不特定多数のユーザーが頻繁にアクセスするわけではありません。DynamoDBは「実際に発生した読み書きの回数」に応じて課金されるため、アクセス頻度が低い場合はRDSよりもコストを抑えられます。
2. 複雑なクエリが不要
サービスの目的は「入室している人をシンプルに表示すること」であり、データの集計や結合などの複雑なクエリは必要ありません。そのため、リレーショナルデータベースの強みを活かす場面がなく、シンプルなKey-Value型のDynamoDBの方が適していると判断しました。
移行を通じて学んだこと
AWSアーキテクチャを設計する中で、最小権限の原則の重要性を改めて学びました。 最小権限の原則とは、ユーザーやリソースに対して必要な最小権限のみを付与するセキュリティ戦略です。
今回は特に、Lambdaに対して不要な権限を与えないことを意識しました。例えば、DynamoDBからデータを取得するLambdaには、以下のような最小限のIAMポリシーをアタッチしています。
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:Scan", "dynamodb:GetItem" ], "Effect": "Allow", "Resource": "arn:aws:dynamodb:ap-northeast-1:xxxxxxxxxxxx:table/table-name", } ] }
このIAMポリシーが適用されているLambdaは、指定したDynamoDBテーブルに対して、以下の操作が可能です。 キーを指定したアイテムの取得(GetItem) テーブル全体のスキャン(Scan) サービスの要件としてはこれで十分であるため、不要な権限は付与していません。 この制限により、不要なデータ操作を防ぎ、セキュリティリスクを最小化できます。
今後の課題
FirebaseからAWSへインフラを移行し、アーキテクチャを構築する中で、設計や運用の観点から見えてきた課題を整理します。実装や運用を通じて浮かび上がった改善点についても触れ、今後の最適化に向けた方向性を考えます。
スプレッドシートのデータを取得する仕組み
現在の構成では1分間隔でLambdaを実行してスプレッドシートのデータを取得していますが、データの変更がない場合は無駄な処理が発生します。 無駄にLambdaが起動することで、その分の料金も発生してしまいます。
改善案
データの更新があった場合のみLambdaを実行するようにする
- GASを使用し、変更時にWebhook経由でLambdaをトリガーする構成にする
- スプレッドシートの変更ログを保持し、更新があった行だけを取得する方式に変更する
API Gatewayへのアクセス保護
現在の構成では、WAFをCloudFrontのみを対象にしていますが、API Gatewayへのアクセスは保護されていません。エントリーポイントにWAFを適用すれば安心だと考えましたが、API Gatewayに対しても不要なリクエストが送られる可能性はあります。
改善案
最後に
今回はWebサービスのインフラをFirebaseからAWSに移行した事例をご紹介しました。移行後は実際にイベントで使用し、安定した動作や運用のしやすさを確認できました。
また、セキュリティ対策の検討やリソース選定を通じて、多くの貴重な経験を得ることができました。
しかし、新たに構築したインフラにも課題やさらなる改善の余地があります。 今後はそれらの課題を解決する取り組みについても、引き続き共有していければと思います。