M1 MacでGCP Cloud RunのQuickstart(ruby版)試したので詰まったポイントをメモ

技術選定のため、

* GCP Cloud RunのQuickstartを
* M1 Macの環境で
* プログラミング言語はRubyで

試してみる。
基本的にはquickstartの手順通りやっていくが、詰まった点の解消方法を書く。

https://cloud.google.com/run/docs/quickstarts/build-and-deploy

なお、GCPの中でWebサービスをする上で初期の低負荷なフェーズであれば、Cloud RunのほうがGoogle App Engineよりもコストが安く上がるらしい。

https://dev.to/pcraig3/cloud-run-vs-app-engine-a-head-to-head-comparison-using-facts-and-science-1225


# 環境構築

* Python(Cloud SDKの動作のため)
* Cloud SDK
* Ruby(開発用)

## Python

cloud sdkのインストールにはバージョン3.5以上のPythonが必要である。(2.7.9も使えるけどもはや推奨しない)
3系のpythonのパスが通ってなかったので、anyenv経由でpyenvをインストールし、そこから3系のpythonを入れる。

anyenvは**env系をまとめて入れられるツール。zshrcにpyenvとrbenvと...と環境設定が増えていくのを避けることができて楽できる。

https://github.com/anyenv/anyenv

注意点として、3.10はCloud SDK側がまだ対応してないので、3.9系を入れたほうがよい。
3.10を入れると以下のようなエラーが出る。

```text
ERROR: gcloud failed to load: module 'collections' has no attribute 'Mapping'
    gcloud_main = _import_gcloud_main()
    import googlecloudsdk.gcloud_main
    from googlecloudsdk.calliope import cli
    from googlecloudsdk.calliope import actions
    from googlecloudsdk.calliope import markdown
    from googlecloudsdk.calliope import usage_text
    from googlecloudsdk.calliope import parser_arguments
    from googlecloudsdk.calliope import parser_completer
    from googlecloudsdk.core.console import progress_tracker
    class _BaseStagedProgressTracker(collections.Mapping):

This usually indicates corruption in your gcloud installation or problems with your Python interpreter.

Please verify that the following is the path to a working Python 2.7 or 3.5+ executable:
    /Users/ryan5500/.anyenv/envs/pyenv/versions/3.10.1/bin/python3

If it is not, please set the CLOUDSDK_PYTHON environment variable to point to a working Python 2.7 or 3.5+ executable.

If you are still experiencing problems, please reinstall the Cloud SDK using the instructions here:
    https://cloud.google.com/sdk/
```

以下のコマンドでpyenv, python3.9を入れる。

```bash
$ anyenv install pyenv
$ exec $SHELL -l
# pyenvを使えるようにshellに設定を反映する
$ pyenv install 3.9.9
$ pyenv global 3.9.9
```


## Cloud SDK

[Cloud SDKのインストール](https://cloud.google.com/sdk/docs/install)

上記のURLからCloud SDKをダウンロードする。
使っているマシンがM1 Macなので、プラットフォームが「macOS 64 ビット（arm64, Apple M1 シリコン）」のtar.gzを落としてきて解凍する。

ブラウザからtar.gzをダウンロードすると、ダウンロードフォルダ以下に保持される。ここでCloud SDKの初期化を行うと、ダウンロードフォルダ以下にgoogle-cloud-sdkフォルダを置き続けることになり、後々面倒である。

そこで、`/opt`以下に動かした上でgcloudコマンドの初期化を行った。

```bash
$ sudo mv ~/Downloads/google-cloud-sdk /opt
$ which gcloud
/opt/google-cloud-sdk/bin/gcloud
$ gcloud init
```

これでgcloud initは通った。


## Ruby

rubyが/usr/bin/rubyでシステムデフォルトのままだった。デフォルトのパスを汚したくないので、pythonと同様にanyenv経由でrbenvを入れ、rbenvからrubyを入れ直す。

```bash
$ anyenv install rbenv
$ exec $SHELL -l
# rbenvを使えるようにshellに設定を反映する
$ rbenv install 3.0.3
$ rbenv global 3.0.3
$ which gem
/Users/ryan5500/.anyenv/envs/rbenv/shims/gem

# bundlerもいるのでインストールする
$ gem install bundler
```

# コード作成

[サンプルアプリケーションを作成する](https://cloud.google.com/run/docs/quickstarts/build-and-deploy#writing)を参考にコードを書いて、bundle installする。


ファイルが揃ったら以下コマンドでコンテナをpushする。

```bash
# cloud-run-quickstart-335405 は私が試した際のプロジェクトIDなので、適宜自分のプロジェクトIDに変更する
$ gcloud builds submit --tag gcr.io/cloud-run-quickstart-335405/helloworld
```

push時にエラーが発生した。

```
Successfully installed bundler-2.2.33
1 gem installed
[DEPRECATED] The `--without` flag is deprecated because it relies on being remembered across bundler invocations, which bundler will no longer do in future versions. Instead please use `bundle config set --local without 'test'`, and stop using this flag
Your bundle only supports platforms ["arm64-darwin-21"] but your local platform
is x86_64-linux. Add the current platform to the lockfile with `bundle lock
--add-platform x86_64-linux` and try again.
The command '/bin/sh -c gem install bundler && bundle install --without test' returned a non-zero code: 16
ERROR
ERROR: build step 0 "gcr.io/cloud-builders/docker" failed: step exited with non-zero status: 16
```

要するに、Gemfile.lockにアーキテクチャ情報が書き込まれている。

```
# Gemfile.lock内
PLATFORMS
  arm64-darwin-21
```

よく読むと対応方法が書いてある。

```bash
$ bundle lock --add-platform x86_64-linux
```

# Cloud Runへのデプロイ

```bash
$ gcloud run deploy --image gcr.io/cloud-run-quickstart-335405/helloworld --platform managed
```

デプロイ先のリージョンを選べと言われる。

```
Operation "operations/acf.p2-347839877005-a282d8b5-e313-4f88-9fea-a38123e45dc1" finished successfully.
Please specify a region:
 [1] asia-east1
 [2] asia-east2
 [3] asia-northeast1
 [4] asia-northeast2
 [5] asia-northeast3
 [6] asia-south1
 [7] asia-south2
 [8] asia-southeast1
 [9] asia-southeast2
 [10] australia-southeast1
 [11] australia-southeast2
 [12] europe-central2
 [13] europe-north1
 [14] europe-west1
 [15] europe-west2
 [16] europe-west3
 [17] europe-west4
 [18] europe-west6
 [19] northamerica-northeast1
 [20] northamerica-northeast2
 [21] southamerica-east1
 [22] southamerica-west1
 [23] us-central1
 [24] us-east1
 [25] us-east4
 [26] us-west1
 [27] us-west2
 [28] us-west3
 [29] us-west4
 [30] cancel
Please enter your numeric choice:
```

asia-northeastではあると思うが、東京はどこなのかわからないので確認する。

https://cloud.google.com/compute/docs/regions-zones

* asia-northeast1: 東京
* asia-northeast2: 大阪

毎度言われるのが大変なので、以下でデフォルトregionを設定できる。

```
To make this the default region, run `gcloud config set run/region asia-northeast1`
```

asia-northeast1の3を選ぶと以下のメッセージが出る。

```
✓ Deploying new service... Done.
  ✓ Creating Revision... Revision deployment finished. Waiting for health check to begin.
  ✓ Routing traffic...
  ✓ Setting IAM Policy...
Done.
Service [helloworld] revision [helloworld-00001-gen] has been deployed and is serving 100 percent of traffic.
Service URL: https://helloworld-ges2ps235q-an.a.run.app
```

デプロイ成功！
初回アクセスは開いてから3秒ぐらい待つ感じ。
2回目以降のアクセスはすごく速い、1秒も待たない。


## コンテナの待機時間　

2回目以降のアクセスが速いのは一度起動したコンテナを起こし続けてるから。
cloud runはコンテナをどれぐらい起こし続けてる感じなんだろう？

https://cloud.google.com/run/docs/about-instance-autoscaling#:~:text=To%20minimize%20the%20impact%20of,of%20a%20sudden%20traffic%20spike.

> Cloud Run は、すべてのリクエストを処理した後、すぐにはインスタンスをシャットダウンしません。コールド スタートの影響を最小限に抑えるために、Cloud Run は一部のインスタンスを最大で 15 分間アイドル状態にすることがあります。