Google Cloud Run vs Google Cloud Functions(コスト編)

主に安さの面でGAEではなくCloud Functionsを使おうと思ったときに、そういえば最近出たCloud Runはどの程度のコストになるんだろというのを調べたメモ

そもそもCloud Runはランタイムが自由であるとか前提が諸々違うがCloud Runのコストがどんなもんか図るのに対抗馬が必要だったので呼び出し回数とか似たような課金項目があるGoogle Cloud Functionsくんに相手をお願いしました

# 最初に
GCPのコスト試算ツール(https://cloud.google.com/products/calculator/) を用いて計算をしましたが、リクエストの集中度合いや処理内容によって大きく増えたり減ったりするのであくまで参考程度に見てください

# それぞれのユースケース
お値段の話をする前にそれぞれどういうケースで使えるか、というのを比較。

`CloudRun vs CloudFunctions` でググると真っ先に公式が出てきて便利
https://cloud.google.com/serverless-options/?hl=ja
ここのページにわかりやすいフローチャートがあったので抜粋。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47979/48710291-91fc-009e-71b3-56e1211ede86.png)

この図を見るとわかるようにCloud RunとCloud Functionsは実行環境上の制約の有無(言語やシステム上のライブラリ)で使い分ければ良いことがわかる。

例えばgoのAPIサーバとかだと基本的には
- HTTPで受ける
- ハードウェアについての要件はない(アプリケーションが走ること以外の制約がない)
- goはサポートされてる
のでGAEかCloud Functions(場合により Cloud Functions + Cloud Endpoints[^1] あたり)の2択になりそう。
[^1]: https://cloud.google.com/endpoints/docs/frameworks/frameworks-extensible-service-proxy?hl=ja


# 課金体系ざっくり

## Cloud Functions
https://cloud.google.com/functions/pricing?hl=ja
呼び出し回数とコンピューティング時間(100ms単位で端数は切り上げ) * スペック(CPU/メモリ)による課金

ついでにCloud Endpointsも見てみたがこっちも呼び出し回数が200万回までは無料。
https://cloud.google.com/endpoints/pricing-and-quotas?hl=ja

## Cloud Run
https://cloud.google.com/run/pricing?hl=ja
こちらも呼び出し回数 + 時間(100ms単位で端数は切り上げ) * スペック(CPU/メモリ)による課金
https://cloud.google.com/run/pricing?hl=ja の `Billable Time` のあたりを見ると、リクエストを処理している間のみ課金されることがわかる。

# 比べてみた
## 同じような数字になるように調整
メモリ消費時間, 帯域等合わせられるだけ合わせてみた。
これだとCloudFunctionsがCloud Runの1/3以下になる。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47979/44effea9-4aed-e791-8c1c-ed5acfc0bdf5.png" height="512px" />

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47979/3b562fb5-cca5-5fdb-c407-054b9c21777a.png" height="300px" />

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47979/11536010-957b-9e31-ae66-0acb859fb9e3.png" height="512px" />

## Cloud Run高くない？というのは誤解
CloudRunが妙に高く見えるが、これはそもそもCloud Runに不利な条件で試算しているから。
Cloud Functionsは呼び出しに対して毎回起動される[^2]がCloud Runはインスタンスが複数のリクエストを受けられるので、ここの並列数を上げていくとCloud RunとCloud Functionsが競ってくる。
直感的にも、  課金の説明のページを見ても単位時間あたりで並列で受けられる限り受けたほうがコストパフォーマンスが高くなる
[^2]: これに合わせるためにここではCloud Runの`concurrent requests per container instance`の項目を1にしている

並列数を上げていくとCPUもメモリも必要になってくるが、どうも公式の試算ツールだと`Cpu Allocated` が2以上に変更できないのでCloud Runを一旦以下のようにしてみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47979/26e4aa29-e956-238e-4c8e-cdf9d9ec379b.png)

差分としては
- メモリ使用量を256KB->1GB
- 並列リクエスト数を1->4

これで Cloud Runの試算額が \\$24.78 -> $6.78 になり、Cloud Functionsより安くなった。

最終的な見積もりはこちら
https://cloud.google.com/products/calculator/?hl=ja#id=504a35e3-7df3-4749-a653-eda289b8ed9e

## それぞれのコストパフォーマンスを高めるには
課金体系から見て、Cloud FunctionsとCloud Runのコストパフォーマンスを高めるにはそれぞれ適切なキャパシティプランニングをしましょうという話にしかならないがもう少し具体的に言うと以下のような感じと思われる。

- Cloud Runは上記の通り、単位時間あたりにリクエストが集中してくれるとインスタンスをフルに活用できてコストパフォーマンスが高まると思われる
- Cloud Functionsは複数のリクエストに対しては複数実行環境が走る(という認識)で、互いに影響しないので基本的にはどれだけ集中しても1リクエストをさばけるギリギリのサイズにスペックを設定するだけ(こちらのほうが考えることが少ない認識)


# まとめと感想
- Cloud FunctionsとCloud Runそれぞれのコストを調べた結果、両方適切に使えば(単体で見る分には)同程度のリクエストをさばいてもそこまでコストに差はでなさそう、というのが結論
- 本当はGAEも比べてみたかったが試算ツールのGAE(Standard Environment)がregionとインスタンス数しか設定項目なくてちょっと比較対象に入れるには粒度があらすぎたので今回は見送り(自分で計算すればできるので誰かしてください)