【Google Cloud】Cloud Runの構築とデプロイを試す

## はじめに

この記事は MicroAd Advent Calendar 2023 の16日目の記事です。

https://qiita.com/advent-calendar/2023/microad

本記事では、Google Cloudのサーバレスサービスの1つであるCloud Runについて、
構築方法やデプロイに関してまとめます。
構築の備忘録を兼ねた記事ですので、参照する際はご注意ください。


## デプロイするアプリ

Cloud Runでよくある構成としては、[Artifact Registy](https://cloud.google.com/artifact-registry/docs/overview?hl=ja)にホストするアプリケーションをPushしておき参照する構成が多いと思います[^1]。
しかしここでは簡略化のため、Docker Hubで公開されている[hashicorp/http-echo](https://hub.docker.com/r/hashicorp/http-echo) を利用することとします。

[^1]: Dockerfileを管理せずコードからデプロイすることも可能です。https://cloud.google.com/run/docs/deploying-source-code?hl=ja

## TerraformによるCloud Run構築

Cloud Run の構成方法には Terraform を利用します。
Googleの公式ドキュメントや、Terraform のリファレンスを参考にコードを書きました。

https://cloud.google.com/run/docs/deploying?hl=ja

https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloud_run_v2_service


作成するコードは、以下のようなファイル構成とします。

```
tree
.
├── backend.tf
├── cloud_run.tf
├── locals.tf
├── output.tf
└── providers.tf

0 directories, 5 files
```

`backend.tf`にはbackendの設定を記述しますが必須ではないため省略します。

`providers.tf`については以下のように記載します。
デフォルトのプロジェクトIDとリージョンはローカル変数にしており、Google Providerは5.9.0を利用しました[^2]。

[^2]:執筆時点の最新バージョンです。https://registry.terraform.io/providers/hashicorp/google/latest

```hcl
# providers.tf
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "5.9.0"
    }
  }
}
provider "google" {
  project = local.project_id
  region  = local.region
}

```

`locals.tf` には各リソース設定で使うローカル変数を記載します。
```hcl
# locals.tf
locals {
  project_id = "my-project-xxx"
  region     = "asia-northeast1"
  run_image = "hashicorp/http-echo:0.2.1"
}
```

`cloud_run.tf`には、メインとなるCloud Runの設定を記載します。
[Cloud Run へのデプロイ](https://cloud.google.com/run/docs/deploying?hl=ja#service)というGoogleのドキュメント内にTerraformのサンプルも記載されているため、それをベースに記述しました。
各設定の要点はコード内のコメントに記載します。
また、各オプションについては、[Terraformのリファレンス](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloud_run_v2_service)を参照してください。

```hcl
resource "google_cloud_run_v2_service" "default" {
  # サービス名は 49 文字以下で、リージョンとプロジェクトごとに一意である必要がある
  name     = "http-echo-service"
  location = local.region
  client   = "terraform"

  ingress = "INGRESS_TRAFFIC_ALL"

  template {
    containers {
      # 起動するコンテナの各種設定
      name  = "http-echo"
      image = local.run_image
      ports {
        container_port = 8080
      }
      # hashicorp/http-echo は引数としてポートとHTMLとして返す文字を指定できる
      # ref. https://hub.docker.com/r/hashicorp/http-echo
      args = [
        "-listen=:8080",
        "-text=\"hello world\"",
      ]
      # お試しのためリソースを制限
      resources {
        limits = {
          cpu    = "1"
          memory = "1024Mi"
        }
      }
    }
    # お試しのためリソースを制限
    scaling {
      max_instance_count = 2
    }
  }
}
resource "google_cloud_run_v2_service_iam_member" "noauth" {
  location = google_cloud_run_v2_service.default.location
  name     = google_cloud_run_v2_service.default.name
  # サービスを外部公開するために、全ユーザにCloud Run起動元のIAMロールを付与
  role   = "roles/run.invoker"
  member = "allUsers"
}
```

最後に`output.tf`ですが、こちらには作成したCloud RunのリビジョンとURIを出力させるようにしています。
```hcl
output "cloud-run" {
  value = [
	google_cloud_run_v2_service.default.latest_ready_revision,
	google_cloud_run_v2_service.default.uri,
  ]
}
```


## デプロイ

`terraform apply` が正常に実行すると、Cloud Runと権限付与の2つのリソース作成として適用されます。
outputにはデプロイしたCloud RunのURIが表示されるのでWebブラウザで開くと確認できます。
```shell
Plan: 2 to add, 0 to change, 0 to destroy.
```

![スクリーンショット 2023-12-15 19.57.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510411/cbcec59b-0e70-ba1d-b90c-fa7b491cd2fc.png)

管理コンソールからもデプロイが確認できます。

![スクリーンショット 2023-12-15 21.14.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510411/e738a124-1f1b-57eb-e8c2-a041b9a36014.png)


## 再デプロイ

次に、`cloud_run.tf`のコンテナの引数を以下のように編集し、再デプロイします。

```hcl
      args = [
        "-listen=:8080",
        "-text=\"hello world v2\"",
      ]
```
デプロイ手順は先ほどと同様に `terraform apply` を実行します。
デプロイ後に管理コンソールを確認すると、新しいリビジョンが作成され、そちらにトラフィックが100%ルーティングされるようになっています。

![スクリーンショット 2023-12-15 21.27.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510411/7cb2a4aa-eded-4df8-30a5-1d732a861f7d.png)

## トラフィックの制御

「トラフィックを管理」の設定からリビジョンごとのトラフィックの割り振り制御をすることができます。

試しに、初回デプロイしたリビジョンへのトラフィックを50%に設定してみます。

![スクリーンショット 2023-12-15 21.28.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510411/f5b95cd8-3d3d-1b6d-4792-ef22c5f889ac.png)

設定後にブラウザやcURLコマンドなどでアクセスしてみると、両方のリビジョンに割り振られることが確認できます。


## おわりに

Cloud Runの構築・デプロイについて、簡単にですが紹介しました。

筆者はまだCloud Runの運用経験はなく調査中ではありますが、Cloud Runを使うことで運用が楽になればと考えています。
まだ未検証ですが、Cloud Deployを使ったカナリアデプロイも気になっており、今後検討できればと思っています。

https://cloud.google.com/deploy/docs/deployment-strategies/canary?hl=ja

以上、この記事が誰かの役に立てれば幸いです。