はじめに
当社の健康管理システム「mediment」は長らく GCP Compute Engine(VM)上にソースコードを直接配置 する構成で運用してきました。サービス初期はこの構成でも十分でしたが、利用者の増加やサービスの成長に伴い、運用上の課題が顕在化してきました。
本記事では、従来のVM構成が抱えていた課題と、Cloud Run + コンテナ構成に移行した経緯・メリットについてご紹介します。
従来構成:GCP VM + ソースコード直接配置
従来のシステム構成は、GCP Compute Engine 上にWebサーバーとアプリケーションのソースコードを直接配置するオーソドックスな構成でした。デプロイの際は、SSHでVMに接続し、ソースコードの更新・依存ライブラリのインストール・サーバーの再起動といった手順を手動で実施していました。
⚠ 課題 1:デプロイの工数と手順が煩雑
デプロイのたびに、各VMへSSH接続し、git pull → 依存関係インストール → サーバー再起動 という一連の手作業が必要でした。VMが複数台ある場合、この作業をすべてのインスタンスに対して繰り返す必要があり、デプロイ1回あたりの所要時間と手順ミスのリスクが増大していました。
また、デプロイ手順がドキュメントと属人的な知識に依存しており、担当者によって微妙に手順が異なるケースもありました。
⚠ 課題 2:スケーリングと保守コストの増大
サービスの利用率が上がるにつれ、1台のVMでは処理が追いつかなくなり、VMの台数を増やして負荷分散 する必要がありました。しかし、VMが増えるたびにOSのパッチ適用、ランタイムのバージョン管理、セキュリティアップデートなどの保守工数が線形に増加していきました。
未使用時でもVMが起動し続けるため、コスト効率の面でも最適とは言えない状態でした。
新構成:Cloud Run + コンテナ
✓ 解決:デプロイの簡素化・一元化
GitHub Actions の workflow_dispatch により、ブランチとデプロイ先(staging / production)を選択して「Run workflow」を実行すると、コンテナイメージのビルドと Artifact Registry への push までが自動で行われます。その後、Cloud Run へのデプロイは手動で実施しますが、従来のように各VMへSSH接続してソースコードを更新する必要がなくなり、手順が大幅に簡素化されました。VMの台数に関係なくコンテナイメージ1つをデプロイするだけで済むため、工数とミスのリスクが大きく削減されています。
✓ 解決:自動スケーリングと保守コスト削減
Cloud Run はリクエスト数に応じて コンテナインスタンスを自動でスケールアウト / スケールイン します。トラフィックがない時はインスタンス数を0まで縮小できるため、コスト効率も大幅に改善。VM個別のOS管理やパッチ適用といった保守作業からも解放されました。
なぜ自動デプロイではなく手動デプロイなのか?
Cloud Run への自動デプロイ(CI/CDパイプラインからの直接デプロイ)は技術的には可能ですが、現時点ではあえて手動デプロイを採用しています。その理由は、非同期処理の特性にあります。
本サービスでは、SQLへの検索やファイルの書き出しなど時間のかかる処理を Celery Worker による非同期処理で実行しています。Celery Worker は実行中のタスクが完了するまでプロセスを維持する必要がありますが、デプロイ時に新しいコンテナへ切り替わると、実行中のタスクが中断されてしまう可能性があります。つまり、Celery Worker の更新を Zero Downtime で行うことが難しいのです。
このため、デプロイのタイミングを人が判断し、非同期タスクの実行状況を確認した上で安全にデプロイを行う運用としています。将来的にはGraceful Shutdownの仕組みを整備し、自動デプロイへの移行も検討していきたいと考えています。
GitHub Actions によるビルド・デプロイの流れ
今回の移行では、コンテナイメージのビルドとデプロイのトリガーに GitHub Actions の workflow_dispatch を採用しました。GitHub の UI 上から3ステップの操作だけで、コンテナのビルドから Artifact Registry への push までを実行できます。
下記は GitHub 上での操作画面です。
① ビルド対象のブランチを選択
② デプロイ先の環境を選択
③ ビルドを実行
上記の Workflow を実現した GitHub Actions の YAML ファイルから、主要なステップを抜粋して紹介します。
Step 1: ソースコードの取得
Step 2: GCP認証
Step 3: コンテナイメージのビルド
Step 4: Artifact Registry へ Push
Step 5: デプロイ(Staging のみ)
まとめ
GCP VM + ソースコード構成から Cloud Run + コンテナ構成への移行により、デプロイ工数の大幅な削減とヒューマンミスのリスク低減を実現できました。また、Cloud Run の Auto Scaling により、サイトのスケーラビリティが向上し、将来の拡張にも柔軟に対応できる基盤が整いました。
GitHub Actions の活用は CI/CD パイプラインの構築にとても役立ち、ビルドからデプロイまでの流れを大きく効率化できました。
今後の課題としては、Celery Worker の Graceful Shutdown の仕組みを整備し、Production 環境でも自動デプロイを実現していきたいと考えています。