Google Cloud のコンピューティング オプションの選択

2023-01-02

#はじめに

Google Cloud のコンピューティング オプションの選択に関するGoogle Cloud Japan ブログ記事を読んでみて、新しいサービスを立ち上げるにあたって、どこでワークロードを実行すべきかを検討します。

#検討要素

Google Cloud Japan ブログ記事によると下記の観点で選定を検討されています。

Why should I run my stuff?
引用元:どこで実行すべきか。Google Cloud のコンピューティング オプションの選択

上記の検討内容を踏まえつつ、最近のトレンドを考慮して、以下の要素を追加してみます。
最近関わっている案件の多くが、以下の要素を含んでいることが多いです。これらを前提に考えていきます。

#コンテナ技術

ここ6年くらいはずっとコンテナ技術のアーキテクチャで開発しています。
主にサーバーサイドはGo言語、フロントエンドはNode.js(vue.jsなど)を使っています。
高い可搬性とVMよりも効率的に動作させられることから、昨今、コンテナが欠かせない要素の一つです。
そうすると、GKE, Cloud Runに絞られます。

#マイクロサービスアーキテクチャ

大規模なサービス開発ではマイクロサービスアーキテクチャを採用している事例が多くなっている感じがあります。
多くのマイクロサービスがあり、それぞれ別々のマイクロサービスチームで独立して開発・運用していくのには、GKEが向いていると思いました。
例えば、Workload Identityによる権限制御や、Istioによるサービスメッシュなど、マイクロサービスアーキテクチャを独立して構築する上で必要な機能が揃っているからです。
Cloud Runでも実現することはできると思います。ネットワーク制約で内部トラフィックのみにしたら、外部からの通信は遮断できますし、サービスアカウントを各サービスに割り当てることで、Google Cloudのサービスアクセスを制限したり、またサービス間の通信も制限できます。
Cloud Runのマークロサービスに関する記事はこちらが参考になります。

#gRPC

昨今、マイクロサービスアーキテクチャと合わせて、gRPCを使うことが多かったです。
gRPCは、HTTP/2をベースにしたRPCフレームワークです。
そのため、App Engineでは、HTTP2をサポートしていないためgRPCを使うことができません。
gRPCを扱うことができるのは、GKE, Cloud Runに絞られます。

#総合的に検討する

上記の検討要素に加えて、いくつかの要素を加えて表にまとめました。

要素 GKE(Autopilot) Cloud Run App Engine
コンテナ ×
マイクロサービスアーキテクチャ ×
gRPC ×
チームの規模 大規模向き
(SREの専門家がいるなど)
小規模向き 小規模向き
ステートフル × ×
学習コスト 高い 低い 低い
運用コスト 高い 低い 低い

#チームの規模

開発チームの立ち上げ時、少人数でスタートすると、あまり運用負荷をかけたくないです。
Google Cloud Japan ブログ記事によると、Cloud Functionsがもっとも運用負荷が低いことになっていますが、これ単体ではWebサービスの開発には向いていないです。Cloud Functionsはイベントドリブンアーキテクチャな部分で利用することになると思います。
例えば、Firebase Authenticationのイベントをトリガーに、Cloud Functionsでユーザーの登録処理を行うとかです。

運用負荷を低くすることを重視すると、次の選択肢は、App Engine, Cloud Run, GKE(Autopilot)です。

Webアプリの開発であれば、LoadBalancerや、バンドルサービス(Memcacheなど)、デプロイのオプションが豊富だったりして全部入りなので、かなりアプリケーション開発に集中できると思います。第2世代のApp Engineでもバンドルサービスにアクセスできるようになり、こうしたものが必要な場合、別途インフラリソースを調達する必要がなくなり便利です。

しかし、便利な反面、マネージド範囲が広くて、柔軟性が低いです。
Go言語のランタイムは最近になってやっとGo v1.18,v1.19がプレビューで使えるようになりました。かなり長い間、v1.16までしか使えなかったのです。
またGo言語でデプロイするときは、プライベートパッケージの扱いが難しいです。記事参照

こうしたプラットフォーム特有の課題を受け入れてでも運用負荷を軽減させる場合、有力な選択肢になります。

Cloud Runは、コンテナ技術なのでApp Engineに比べて柔軟性が高いです。
単体でウェブトラフィックアクセスを受け付けることができますし、グローバル外部 HTTP(S) ロードバランサからのトラフィックを受け付けることもできます。
以前は、リクエストに応じてCPUが割り当てられる設定しかできませんでしたが、CPU常時割り当てができるようになってからは、扱いやすくなりました。また、まだプレビュー段階ですがCloud Run ジョブという機能があり、バックグラウンド処理をCloud Runで実行することができます。
ただし、ステートフルなアプリケーションは向きません。

ステートフルでHelmで提供されているようなミドルウェア、例えば、Elasticsearchや、Redisなどを使う場合、GKEが向いています。
また、Cloud Runでは利用できない、GPUやTPUなどを使うコンピューティングリソースを利用する場合はGKEが選択肢になります。
GKE Autopilotは、Nodeプールの運用管理から解放されるので、Serverlessと同様に運用が楽になります。
もちろんKubernetes自体の学習コストが高いので、開発チームで運用するとなるとKubernetesやHelmなどの知識が必要になります。
Autopilotモードならではの制約があるので、慎重に選択する必要があります。

#料金

固定費の面では、GKEが高くつきそうですが、vCPU,メモリの従量課金の面ではCloud Run, App Engineの方が高くなるかもしれません。料金の計算の仕方が若干違うので、GCPの料金シミュレータで比較するのが良いでしょう。

GKEの場合、デプロイの仕組みを構築する必要があります。実用的にはHelmチャートをhelmfileで各環境ごとにArgoCD経由でデプロイしたり、または、Google Cloudの場合は、Cloud Deployや、Cloud Buildでgke-deployも使えそうです。

戦略としては、初めからステートフルのワークロードが必要になる場合は、GKEを選択するのが良いでしょう。また将来的にステートフルなワークロードが必要になる場合も、移行にかかるコストを考えると、最初からGKEを選択するのが良いでしょう。
一方、将来的にもステートレスなワークロードだけでサービスが構成できるようであれば、Cloud Runを選択するのが良いでしょう。
実際この判断はかなり難しいです。新しい技術がどんどん出てきて、使いたい技術が必ずしもステートレスな設計ではないからです。

もう一つの戦略としては、Cloud Run(or App Engine)とGKEを組み合わせる方式です。この場合は、それぞれデプロイプロセスを構築する必要があるのと、GKEとそれ以外を使い分ける必要があり、少し複雑になりそうです。Cloud Run(or App Engine)ではじめて、あとからGKEに移行するために一時的にGKEと組み合わせるのはありかなと思います。

#まとめ

Google Cloud上で、新しいサービスを立ち上げるにあたって、どこでワークロードを実行すべきかを検討しました。
結果として昨今のコンテナ技術やマイクロサービスアーキテクチャ、gRPCを採用しようとするとGKEとCloud Runの2つの選択肢に絞られました。
AutopilotモードがなかったころのGKEだと、スモールスタートでサービスを立ち上げようとするのに向いてなさそうだなと躊躇してました。しかし、Autopilotによりノードの管理が不要になり運用面のコスト低減が期待できるのと、料金面でも一部固定費があるものの従量課金でスタートできるので採用するハードルが下がったと思います。