GAEからCloud Runへの移行に挑戦した話 ~アクセス変動の激しいインバウンド向けサービスを、柔軟&低コストに運用するまでの道のり~

2025/01/15に公開

はじめに

近年、日本国内におけるインバウンド需要は飛躍的に高まっています。観光客や在住外国人の増加に伴い、日本の文化体験やツアーをオンライン上で予約できるサービスは競争力を増しています。しかし、インバウンド需要には大きな季節変動や時期的な偏りがあり、インフラ設計や運用コストの最適化が大きな課題となります。

本ブログでは、あるインバウンド向けの日本文化体験予約サイトを例に取り上げ、Google App Engine(以下、GAE)からGoogle Cloud Runへの移行を行った際の具体的なデータ規模や設計思想、さらには料金面(コスト最適化)でどのようなメリットを得たのかを、約1万文字のボリュームで詳しく解説します。アクセス数・予約件数が多いサービスを運用している方や、サーバレスアーキテクチャへの移行を検討中の方の参考になれば幸いです。


サービス概要と現状の課題

サービス概要

  • サービス内容
    海外旅行者・在住外国人・日本人ユーザー向けに、日本文化や体験プログラム(茶道、着物着付け、和菓子作りなど)をオンライン予約できるプラットフォームを提供。

  • 機能一覧(例)

    1. ユーザー登録/ログイン(多言語・多通貨対応)
    2. 体験プログラムの検索・一覧表示
    3. 予約・決済フロー
    4. クライアント(事業者・店舗)向けの在庫管理/予約管理
    5. 管理者向けダッシュボード(レポート表示、クーポン発行 など)
  • 従来アーキテクチャ(GAE中心)

    • バックエンド: GAE Standard (Python/Node.jsなど)
    • データベース: Cloud SQL (MySQL)
    • フロントエンド: 別途ホスティング+SPA(もしくはSSR)
    • スケーリング: GAEの自動スケール機能に依存
    • イベント駆動やバッチ系:GAE Cron / Cloud Tasks など

この構成である程度うまく運用していたものの、アクセス数やユーザー数が増えるにつれ、下記のような課題や不満が浮上してきました。

現状の主な課題

  1. アクセスのピーク・オフピークの差が激しい

    • 観光シーズンには海外からの予約リクエストが急増し、1日に数百万リクエストに達することもある一方、オフシーズンや深夜帯はアクセスが激減する。
    • GAE Standardだと、一時的なトラフィック急増によってインスタンスが大量にスケールアウトし、その分コストが増大するケースがあった。
  2. GAE Standardランタイムの制限

    • GAE Standardでは使用できるライブラリやランタイムが制限されており、特に最新バージョンを使いたいときに足かせになる場合があった。
    • 多言語対応や特殊なミドルウェア導入を検討しても、GAEでは制限を回避する方法が複雑になることもあった。
  3. 同時実行数(Concurrency)の問題

    • GAE Standardは1インスタンスあたりの同時処理数に制限があり、大量アクセス時に必要以上のインスタンスが立ち上がることが多かった。
    • 結果として「ピーク時のコスト」がかさむばかりか、オフピークでもアイドルインスタンスが残りがちになる等、無駄な費用負担が発生していた。
  4. 開発効率と運用の柔軟性

    • コンテナ化が当たり前になってきた昨今、DockerやKubernetesを活用した開発フローの方が標準化された環境を整えやすい。
    • GAEだとローカル環境との乖離が大きくなるケースがあり、新人エンジニアや外部パートナーが参画した際の環境構築でつまずくこともあった。

データ規模とチームの優先事項

DB・ユーザー・リクエストの規模(仮定の例)

  • DBテーブル数: 約20~30

    • ユーザー管理、予約管理、体験プログラム情報、事業者情報、決済履歴、クーポン、メッセージ履歴、など機能ごとにテーブルを分割。
  • 主要テーブル例

    1. users: ユーザー情報(約80万~100万レコード)
    2. experiences: 体験プログラム情報(約4万~6万レコード)
    3. reservations: 予約データ(約200万~400万レコード)
    4. clients: 事業者(約5千~1万レコード)
  • ユーザー数:

    • 登録ユーザーは累計で100万人規模。
    • 月間アクティブユーザー(MAU)は約30万人。日本人と海外ユーザーが混在。
  • 1日あたりのリクエスト数:

    • 平均で50~100万リクエスト/日。
    • 繁忙期には200万リクエスト/日を超えることもある。

チームの優先事項

  1. 高い可用性とスケーラビリティ

    • 予約サービスなので、機会損失を防ぐためシステムダウンは最小化したい。
    • 大量リクエストにも耐えられる自動スケールを実現しつつ、オフピーク時にはコストを抑える構成を目指す。
  2. 多言語・多通貨対応

    • 海外ユーザーを意識し、英語・中国語を中心とした表示切り替え。
    • 決済時の通貨切り替え(円、ドル、ユーロなど)と為替レート管理も重要。
  3. 開発効率と継続的デリバリー(CI/CD)

    • 予約機能やUIを頻繁にアップデートしており、機能追加のスピードが求められる。
    • Docker化とGitHub Actionsなどによる自動デプロイで、素早いリリースサイクルを回したい。
  4. セキュリティとデータ保護

    • インバウンド客のクレジットカード決済も取り扱うため、PCI DSSなどの準拠を意識。
    • GCPのIAM、VPCコネクタ、ネットワーク分離などで最小権限を徹底する。
  5. 料金面の最適化

    • 観光シーズンやオフシーズンの差が大きい業態なので、無駄なインスタンス稼働を抑えたい。
    • “使った分だけ支払う” スキームを最大限に活用し、ピーク時にもオフピーク時にも柔軟に対応する。

GAEからCloud Runへの移行を決断した理由

上記のような要件と課題を踏まえ、チームはGoogle Cloud Runへの移行を決断しました。主な理由は以下のとおりです。

  1. コンテナベースの自由度

    • Cloud Runはコンテナをそのままデプロイできるので、ランタイムの制限が少ない。
    • Python, Node.js, Go, Javaなどを複数バージョンで使いたい場面や、特殊なライブラリ導入も容易。
  2. 高いConcurrency設定

    • GAE Standardは1インスタンスあたりの並列処理数が制約されがちだが、Cloud Runでは同時実行数を柔軟に設定可能。
    • 1コンテナあたりの同時リクエストを増やしやすく、不要なスケールアウトを抑えられる。
  3. アイドル時の費用削減

    • Cloud Runではトラフィックがないときにコンテナ数が0にまでスケールダウンし、ほとんど課金が発生しない。
    • オフシーズンや深夜帯はアクセスが激減する観光系サービスにとって大きなメリット。
  4. CI/CDとの相性の良さ

    • Dockerfileをベースにしたビルド・デプロイフローが標準的に構築可能。
    • GitHub ActionsやCloud Buildを活用して自動化することで、開発効率が上がる。
  5. 将来的な拡張性・マイクロサービス化

    • 予約機能、決済機能、レビュー機能などをコンテナ単位で分割しやすい。
    • 大規模になった際はさらに複数のCloud RunサービスやKubernetes(GKE)などへシームレスに移行できる可能性が高い。

移行時に考慮した点と具体的ステップ

1. コンテナ化の準備

  • Dockerfile作成

    • 既存のGAE Standard向けソースから、Dockerで動かすための依存関係を洗い出し。
    • OSやランタイムバージョン、ライブラリのインストール順序を整理し、ビルドキャッシュを効率的に利用。
  • 環境変数・シークレットの扱い

    • GAEでは app.yaml に書いていた設定をCloud Run向けに変更。
    • Secret Managerやカスタムの環境変数ファイルで、APIキーやDB認証情報を安全に管理。
  • ローカルテスト

    • Docker Composeを使い、Cloud SQL(MySQL)やRedisなども含めてローカルで起動テスト。
    • GAEエミュレータとは異なるアプローチだが、本番に近い環境を用意しやすいメリットがある。

2. Cloud SQLとネットワーク設定

  • VPCコネクタの利用

    • Cloud RunコンテナがプライベートIPでCloud SQLにアクセスできるよう、VPCコネクタを設定。
    • これにより外部からの不正アクセスを防ぎつつ、DB接続を安定化。
  • DB接続プールの調整

    • Cloud Runはスケールアウト時にコンテナ数が増えるため、各コンテナで無制限にコネクションを張るとDBがパンクするリスクがある。
    • コネクションプールの上限を設定し、トータル接続数が上限を越えないよう制御。

3. 負荷テストとブルーグリーンデプロイ

  • ステージング環境での検証

    • テスト用プロジェクトを用意してCloud Runにデプロイ。
    • 負荷ツール(Locustやk6など)で大量リクエストをシミュレーションし、コールドスタートやスケーリング挙動、レスポンスタイムを確認。
  • トラフィック切り替え計画

    • Blue-Green DeploymentやCanary Release的に、最初はトラフィックの10%をCloud Runに流し、問題なければ25%、50%、最終的に100%へ切り替え。
    • 予約フローの整合性に注意しつつ、旧GAE環境と数日~数週間並行稼働する形でリスクを低減。

4. 運用開始後のモニタリングとチューニング

  • Stackdriver(Cloud Logging/Monitoring)で可視化

    • CPU使用率、メモリ使用率、同時実行数、レスポンスタイムなどのメトリクスを定期チェック。
    • 過剰スケールやコンテナ再起動を発見しやすく、迅速な対応が可能。
  • Concurrencyの微調整

    • あまりに高く設定しすぎると1コンテナあたりの負荷が大きくなり、レスポンス遅延が増えるリスクあり。
    • 逆に低すぎるとコンテナ数が増えすぎてコストがかさむ。定期的にアクセス傾向を分析し、最適値を模索。
  • スケジューラ(Cloud Scheduler)でのバッチ処理

    • バッチ処理やレポート生成はコンテナ起動型に移行し、一時的に起動して処理完了後に停止する仕組みを整備することで、常時インスタンスを維持する必要がなくなる。

料金面(コスト最適化)の具体的な成果

ここが本ブログの重要ポイントの一つです。実際にCloud Runへ移行した際、以下のようなメリットを得られたと想定しています(数値はあくまで例示)。

  1. 従量課金+コンテナ数0によるアイドルコスト削減

    • 従来のGAE Standardでは、ある程度のアイドルインスタンスが常に起動していたため、アクセスの少ない時間帯でも固定費が発生していた。
    • Cloud Runではリクエストがなければコンテナを0にでき、深夜帯やオフシーズンにほぼ課金が発生しない。
    • これにより、月あたりのインフラコストが約20~30%削減されたケースが見られた。
  2. 同時実行数(Concurrency)の最適化

    • 1コンテナで10~20件のリクエストを同時処理できる設定にすることで、アクセスが急増しても必要最小限のコンテナ数で捌けるように。
    • ピーク時にも無駄なスケールアウトが減り、ピークタイムのコストを抑えられた
  3. ピーク時のスケールアウトも柔軟

    • プロモーション施策や大型連休など急激にリクエストが増える場合でも、Cloud Runが即座にコンテナを増やし対応できる。
    • 過去の経験ではGAE Standardの初期インスタンス設定を見誤り、うまく捌ききれないことがあったが、今回はユーザー体験のダウンタイムを減らしつつ、コストも予測しやすい状況を実現。
  4. 運用コスト(人件費含む)の削減

    • サーバOSのパッチやバージョン管理などの負担がほぼ無いため、運用担当者がインフラ周りで火消しをする機会が減った。
    • そのリソースを新機能開発やUI改善に回せるため、実質的なコスト削減+価値創出につながる。
  5. 将来的なマイクロサービス戦略

    • 今後、予約機能・決済機能・レビュー機能などを分割運用する際も、Cloud Runベースなら小さなサービス単位でデプロイ管理ができる。
    • スケール戦略を機能ごとに変えられるなど、開発チームの自由度が上がる。将来的にはさらにコストを最適化できる余地がある。

運用後に見えた課題と今後の展望

1. コールドスタート問題

  • Cloud Runはアクセスがゼロから始まる場合、初回リクエストでコンテナが起動するため、1~2秒の遅延が生じることがある。
  • オフシーズンや深夜帯にトラフィックが途絶えたあと、ユーザーの最初のアクセスが遅くなる場合がある。
  • 対策としてはコンテナを少数キープするオプションやCaching戦略を検討しているが、コストとのトレードオフがあるので最適解を試行錯誤中。

2. ログの一元管理

  • GAE時代はLogs Explorer上でGAEアプリログをまとめて見られたが、Cloud Run+他のサービス(Pub/Sub、Scheduler、Firebaseなど)を組み合わせると、ログがやや分散する印象がある。
  • ログにラベルやフィルタを設定して一元的に可視化する仕組みづくりが必要。

3. ステートフルな処理との共存

  • 予約システムにはセッション管理や在庫ロックが絡むため、本来ステートレスであるはずのサーバレス環境とどう折り合いをつけるかが課題。
  • トランザクションや在庫ロックはDBレベルで行うなど、アプリをできるだけステートレス化してクラウドの自動スケールを活かす努力が続いている。

4. 海外リージョンへの展開

  • インバウンド需要が増えれば、海外ユーザー向けにリージョンを分散させる必要性が高まるかもしれない。
  • Cloud Runのサポートするリージョンは増えているが、GAEと比べて若干少ないと感じるケースもあるため、ユーザーのアクセス元を考慮した最適なデプロイ戦略を検討中。

まとめ

GAE StandardからCloud Runへの移行は、一見すると同じGCP内のサービス切り替えのようでいて、アーキテクチャの大幅な変化を伴います。コンテナをベースにした開発・運用へシフトすることで、チームとして得られたメリットは大きく、特に以下の5点が印象的でした。

  1. スケーラビリティの最適化

    • 同時実行数を高めに設定し、必要以上にコンテナが増えない設計が可能。
    • 観光シーズンの急激なアクセス増にも即応できる。
  2. オフピーク時のコスト削減

    • リクエスト0件でコンテナ数を0にし、ほぼ課金ゼロに。
    • GAE Standardに比べて月間トータルのインフラ費が20~30%下がった事例も。
  3. コンテナ化による開発効率向上

    • Dockerfileでランタイムを自由に選択。
    • ローカル環境とのギャップが減り、CI/CDパイプラインも標準化しやすい。
  4. セキュアなネットワーク構成

    • VPCコネクタやIAMロールによる権限管理で、内部/外部アクセスを厳格に制御。
    • クレジットカード情報などの機微情報を安全に取り扱える環境を強化。
  5. 将来的なマイクロサービス化

    • 予約機能や決済機能をそれぞれ独立したCloud Runサービスとして展開できる見通し。
    • 大規模化しても段階的に分割しやすく、リリースの影響範囲を抑えられる。

一方で、コールドスタート問題ログの分散ステートフルな処理との両立など、移行後に新たな課題が出てくる点も考慮する必要があります。それでも「アクセスの波が大きい業態」「利用言語やライブラリの自由度を高めたいチーム」にとって、Cloud Runがもたらすメリットは非常に大きいと感じられます。

今後は、マイクロサービス化をさらに進めてコンポーネントごとにスケール戦略を立てたり、海外リージョン展開を検討して海外ユーザーのレスポンス向上を図るなど、さらなる成長フェーズへ進む予定です。インバウンド需要の動向に合わせ、サービスの高可用性とコスト最適化を追求するために、こうしたサーバレス×コンテナアーキテクチャは今後ますます重要になるでしょう。


おわりに

本ブログでは、インバウンド向け日本文化体験サービスを例に、GAEからCloud Runへの移行による コスト最適化スケーラビリティ の向上について詳しく紹介しました。以下に主なポイントを再掲します。

  • DBテーブル数やユーザー・リクエスト規模 を明示して、具体的なデータ量がどの程度あったか示す。
  • チームの優先事項(可用性、コスト最適化、多言語対応、開発効率など)を整理し、選んだ技術的決定の背景を明確にする。
  • Cloud Runのメリット(コンテナ化の自由度、同時実行数設定、アイドル時にコンテナ0、CI/CDしやすさ)を活用して、ピーク時・オフピーク時両方の課題を解消。
  • 実際の料金面での効果(アイドル時の課金削減、ピーク時のインスタンス過剰スケール防止、運用工数減など)を数字でイメージできるように説明。

Discussion