Cloud RunとCloud Spanner、Cloud Tasksで実現する最強のサーバレスRails環境

# はじめに
ここ1年ほどGoogle CloudでRailsアプリを運用してみて、Google Cloudの各種サービスはRailsに無限のパワーを与えてくれる・・・！と感じたのでそのまとめ記事です。
アーキテクチャの全体像とそれぞれのサービスの所感をざっくりと紹介する形にしたので、少しでもGoogle Cloudの魅力を感じてもらえたら嬉しいです。

**Google Cloudは良いぞ・・・！！**

# ほぼ無限にスケールするRails用のインフラ、欲しくない？
ソニックガーデンで色々なお客様と二人三脚でシステムを開発していると、負荷がおとなしめのサービスから高負荷なサービスまで様々なものと出会います。
その中で常々思っているのが

- 純然たるRailsアプリを
- シンプルな構成のインフラで
- 様々な負荷状況に応じて自在にスケールさせたい

という事です。
いままでも色々なクラウド環境でこれを実現するために色々と試行錯誤してきたのですが、今年Google Cloudと戯れた事でついに一つの答えにたどり着けたのでは？と思っています。

いまGoogle Cloudで動いてるとあるRailsアプリだと、データベースの容量は数TBに達しており、この記事を書いてる最中にも元気に秒間あたり数百〜数千のActiveJobやリクエストを捌いています。

それを、特殊なミドルウェアを使ったり複雑な構成のインフラにすることなく捌けてしまうとしたら、最高じゃないですか？
そんなインフラをGoogle Cloudなら作ることができます。

**Google Cloudは良いぞ・・・！！（2度目**

# Google Cloudの素敵なサービス群
ここでは実際に利用しているサービスの紹介と、どういう所が気に入ってるのかを説明していきます。
ざっくりアーキテクチャ図はこんな感じ。

![google_cloud2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16746/cc201ce2-4f67-e484-2fe7-34416388dcc2.png)


Cloud Buildでデプロイして、Cloud RunでRailsを動かし、データベースはCloud Spannerを利用し、Cloud TasksでActiveJobによる非同期Jobを扱うって感じの構成です。
とてもシンプルで綺麗な構成じゃないですか？

Cloud Buildでデータベースのマイグレーションも行えるため、コンテナ系のデプロイ時にどうするか困るそういった部分も難なく扱えます。
一応Cloud Storageも図に入れてますが、今回の本題ではないので記事では省いています。

## Cloud Run
まずはじめに紹介しないといけないのは何をおいてもCloud Run！
公式の説明を引用すると

> Cloud Run は、Google のスケーラブルなインフラストラクチャ上でコンテナを直接実行できるマネージド コンピューティング プラットフォームです。
> [- Cloud Runの公式ドキュメントより](https://cloud.google.com/run/docs/overview/what-is-cloud-run?hl=ja)

となっており、複雑な設定をせずともいい感じでスケールしてくれるコンテナ実行環境です。
1インスタンスで同時に受け付けられるリクエスト数を指定しておけば、それを超えるアクセスがあると自動的にインスタンス数を増やしてスケールしてくれます。
とっても楽ちん！

リクエストがない場合は設定によってはインスタンス数を0まで落としてくれるし、課金もリクエストを処理してる時間の100ミリ秒単位での切り上げ課金になっています。
1日の間でピーク時とそれ以外の差が激しい場合などは特に使いやすいです。

デフォルトだと1つのサービスにつき100インスタンスまでの制限がありますが、緩和申請すれば増やすことができます。

気になった方は是非とも[公式ページ](https://cloud.google.com/run?hl=ja)を眺めてみてください。
ネットワーク周りも柔軟に設定できたり、定期実行ジョブを動かせたりと色々な便利機能が備わってます。

Dockerイメージをデプロイする形なので、普段からコンテナを使ってる人は特に苦労せずに使えると思います。

## Cloud Spanner
次に紹介すべきはCloud Spanner！
公式の説明を引用すると

> Spanner は、リレーショナル、グラフ、Key-Value、検索を統合したフルマネージドのミッション クリティカル データベース サービスです。グローバルなトランザクション整合性、高可用性のための自動の同期レプリケーション、2 つの SQL 言語（GoogleSQL（拡張機能を含む ANSI 2011）と PostgreSQL）が含まれています。
> [- Cloud Spannerの公式ドキュメントより](https://cloud.google.com/spanner/docs?hl=ja)

となっているのですが、こいつの何が凄いかって「書き込み」すら負荷分散してくれるところです。
詳しい話は[公式ページ](https://cloud.google.com/spanner?hl=ja)や2012年に発表されてる[論文](https://research.google.com/archive/spanner-osdi2012.pdf)などを読んでもらえればと思うのですが、一貫性を保ちつつスループットを上げるために原子時計とGPSを使ってたりするあたりに狂気を感じる(褒めてる)一品となっています。
こういうぶっ飛び方めちゃ良いですよね、大好きです。

Cloud Spannerのおかげで、Cloud Run側でインスタンス数がめっちゃ増えたとしても怖くありません。
Cloud Run側を高負荷時に100インスタンス程度で使ってる限り、いわゆるRDBで遭遇するコネクション数の問題に遭遇したこともないです。
現時点ではプレビューながらオートスケール（なんとスケールインもする！）にも対応してるので、Cloud Run側がそれ以上になってもいい感じでスケールしてくれると期待しています。

また、Railsから使う場合はGoogleSQLモードに対応したActiveRecord用のアダプタが準備されています。

https://github.com/googleapis/ruby-spanner-activerecord

Railsの最新版に対応させるためのpull-reqをいくつか投げたりしましたが、とても親切に対応してもらえています。
もし気になる挙動とかあれば是非pull-reqを送ってみてください。

ただ一般的なRDBと違うのでいくつか注意点もあります。

- GoogleSQLなのでクエリにちょっと癖がある場合がある
- indexがよくあるRDBのB-treeではないのでソート順が大事だったりする
- DDL系の実行に結構時間がかかる（でもダウンとかはしない
- etc...

そういったいくつかの注意点を押さえておけば信じられないスケール性能をもったRDBとして使えます。
料金も最低構成であれば月額2万円弱くらいです。

## Cloud Tasks
次はActiveJobを使う場合にとても便利なバックエンド、Cloud Tasks！
公式の説明を引用すると

> Cloud Tasks は、大量の分散タスクの実行、ディスパッチ、配信を管理できるフルマネージド サービスです。ユーザー リクエストの外部で作業を非同期で処理できます。タスクは App Engine または任意の HTTP エンドポイントで実行できます。
> [- Cloud Tasksの公式ドキュメントより](https://cloud.google.com/tasks/docs?hl=ja)

となっており、キューの管理をフルマネージドで行えます。
Railsから使う場合は```cloudtasker```というgemがとても便利です。

https://github.com/keypup-io/cloudtasker

このgemを使うと、ActiveJobのJobをCloud Tasksにキューイングして、そのJobをCloud Runで実行することができます。
つまり、Jobの実行環境すらCloud Runでスケールさせる事ができてしまいます。

インフラ構築時に非同期Jobの実行環境をどうやってスケールさせるかで悩むことがままあると思うのですが、Cloud Runでスケールさせる事ができるのでその悩みからも解放されます。

Cloud Tasks側でキューごとの同時ディスパッチ数なども設定できるので、気になる方は[公式ドキュメント](https://cloud.google.com/tasks/docs?hl=ja)を眺めてみてください。

## Cloud Build（おまけ
そして最後におまけ的に紹介するのはCloud Build！
公式の説明を引用すると

> Cloud Build は、Google Cloud でビルドを実行するサービスです。
>
> Cloud Build は、さまざまなリポジトリやクラウド ストレージ スペースからソースコードをインポートし、仕様に合わせてビルドを実行し、Docker コンテナや Java アーカイブなどのアーティファクトを生成できます。
> [- Cloud Buildの公式ドキュメント](https://cloud.google.com/build/docs/overview?hl=ja)

となっていますが、DBのマイグレーションなども行える優れものです。

ここまで読んでCloud RunにRailsアプリをデプロイしてみたくなった場合は、以下のページなどが参考になります。

https://cloud.google.com/ruby/rails/run#automation_with

ここで出てくる```gcr.io/google-appengine/exec-wrapper```イメージはとても便利で、オプションの指定によって```Cloud SQL Auth Proxy```経由でのmigrationも実行できます。
今回紹介しているSpannerの場合は```-s```オプションを使わず、IAMで権限を付与しておけばmigrationを実行できます。

# まとめ
ざっくりと個人的に考え得る最強のサーバレスRails環境を作る上での各種サービスの特徴・注意点などをまとめてみました。
データベースまで含めて、フルマネージドでオートスケールにできるのが個人的にポイント高くて最高です。

ただ、この組み合わせにも課題が無いわけではなく、例えばいわゆるone-offタスクや「rails c」をどうするのかといった課題はまだ残っていたりします。
ですが、Google Cloudはその課題を吹き飛ばしてくれるくらいのスケール力を持っており、それによりコードやインフラ構成をシンプルに保ちながらも恐るべき処理能力を発揮する事が可能になっています。

もちろん冒頭に書いたような秒間で数百〜数千のActiveJobやリクエストを捌こうとすると安くはないインフラ費用がかかりますが、重要なポイントは

**「シンプルなコードやインフラ構成のままに、現実的な範囲の課金で容易にフルマネージドでスケールさせられる」**

という点だと思っています。

2025年はそんなGoogle Cloudともっと仲良くなろうと思っているので、この記事を2024年のまとめとして残しておきます。

**Google Cloudは良いぞ・・・！！（3度目**