Terraformを使って、Google Cloud Runへの自動デプロイを構築してみる

2024/11/26に公開

はじめに

最近、簡単なWebサービスやバックエンドサーバーのデプロイ先に、Google Cloud Runをよく使用しています。

Cloud Runはコンテナ環境をそのままGoogle Cloud上で動かせるサービスで、Webサービスも簡単に置くことができます。使用されていない間は自動でスケールダウンしてくれるのでコストがかかりずらく、個人開発向きだと思っています(以下、参考記事)。
https://qiita.com/massie_g/items/5a9ce514eaa7c460b5e3

さて、Cloud Runへデプロイする際は、Google CloudとGithub ActionsをOIDC連携して、自動デプロイのワークフローを組んでいました。その際の方法をまとめた記事がこちらです。
https://zenn.dev/kakuhito/articles/565c5dda9082a3

ただGoogle Cloud上での設定が結構多いです。この作業をなんとか自動化できないかと模索した結果、Terraformを使用した自動化が存外簡単に実現できました!
本記事では全体の流れを軽く記載しつつ、TerraformでのGoogle Cloud構築の仕方をメインで話します。

サンプルはこちらです。
https://github.com/Suke-H/terraform-gcp-wif

※Terraformの仕組みについてはほとんど触れません。あらかじめご了承ください。

全体の流れ

  1. サービスを用意
  2. コンテナ環境を用意
  3. TerraformによるGoogle CloudとGithubのWIF連携
  4. Github Actionsのworkflow設定

1と2の用意はしてもらった上で、3を自動化できる、という内容です。
Terraformを実行することでGoogle CloudとGithubが連携できるので、あとは4でGithub Actionsによる自動デプロイを設定します。

3のイメージ


CI/CD実行時のイメージ

本記事で紹介する方法は、Workload Identity 連携(Workload Identity Federation, 通称WIF)を用いて、Github Actions内でサービスアカウントを一時的に呼び出し、そのアカウントを使ってデプロイを実行していく流れとなります。このWorkload Identityを経由する方法によりサービスアカウントのキー管理が必要なくなり、かわりにGitHubとGoogle Cloudの間でOpenID Connect(OIDC)認証を使用した安全な認証を行えます。

Workload Identity 連携をするために、次のような準備が必要になります。

  • サービスアカウントの作成(ロール付与)
  • Workload Identityプールとサービスアカウントとの紐づけ
  • Workload IdentityプロバイダとGithubとのOIDC認証の設定


Workload Identity 連携の準備

先ほどの記事では、この3点の準備を手動で実施していきましたが、これをTerraformにより自動化させます。
前回の記事で実施していったgcloudコマンドの通りに、Terraformファイルにて設定を記載していった感じとなります。
https://github.com/Suke-H/terraform-gcp-wif/tree/main/terraform

例:サービスアカウントへのロール付与

CLIでのコマンド実施だと以下。

$ gcloud projects add-iam-policy-binding <PROJECT_ID> \
    --member="serviceAccount:<SA_EMAIL>" \
    --role="roles/iam.serviceAccountUser"
$ gcloud projects add-iam-policy-binding <PROJECT_ID> \
    --member="serviceAccount:<SA_EMAIL>" \
    --role="roles/artifactregistry.writer"
$ gcloud projects add-iam-policy-binding <PROJECT_ID> \
    --member="serviceAccount:<SA_EMAIL>" \
    --role="roles/run.admin"

Terraformでの書き方は以下のようになります。

resource "google_project_iam_member" "binding" {
  for_each = toset(var.roles)
  
  project = var.project
  role    = each.key
  member  = "serviceAccount:${var.service_account_email}"
}

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

以下のドキュメントを参考にして作成しています。
https://registry.terraform.io/providers/hashicorp/google/latest/docs/


手順

それでは、ここから実際にサービスをCloud Runへデプロイするまでの作業をしていきます。
先ほどの1〜4に従って進めていきます。

1. サービスを用意

デプロイするWebサービスを用意。サンプルではViteを使って構築しています。

2. コンテナ環境を用意

Webサーバーが立ち上がるようなコンテナを構築すべく、dockerfileを用意します。
サンプルではnginxを利用しています。

サンプルDockerfileとnginx

3. TerraformによるGoogle CloudとGithubの連携

ここでGoogle CloudとGithubをWIF連携させるためにTerraformを動かしますが、
少し事前準備が必要です。

Terraformインストールはこちらになります(Windowsだと環境変数の設定も必要です)
https://developer.hashicorp.com/terraform/install

事前準備

Terraformで自動化できない部分を済ませます。主にプロジェクト作成と、課金設定になります。

# 端末内でGoogle Cloudにログイン
gcloud auth login
# プロジェクト作成
gcloud projects create new-project-id # (作成済であれば下のコマンドだけ)
gcloud config set project new-project-id

この後GUIの管理画面にて、プロジェクトの課金設定を行ってください。

Terraform用意

さて、メインの部分です。
このterraformフォルダ配下の通りに、ファイルを用意します。
https://github.com/Suke-H/terraform-gcp-wif/tree/main/terraform

また、各自で設定ファイルが必要になります。terraform.tfvarsを用意して、以下6項目を書き込んでください。

# 必須項目
project_id  = "..."                             # プロジェクトID
github_repo = "user-name/repo-name"             # GitHubのユーザー名/リポジトリ名
artifact_registry_repo_name = "..."             # Artifact Registryのリポジトリ名

# Github ActionsとのWIF連携時に使用する設定
github_actions = {
  service_account_name            = "..."       # 作成するサービスアカウント名
  workload_identity_pool_name     = "..."       # 使用するWI Pool名
  workload_identity_provider_name = "..."       # 使用するWI Provider名
}

一旦はこの3項目で問題ないですが、以下項目も任意で指定できます(指定しなければデフォルト)

任意の項目
# 任意の項目

# リージョン(指定しなければ"asia-northeast1")
region      = "asia-northeast1"                 

# Terraform用サービスアカウントの名前(指定しなければデフォルト)
terraform_sa_name = "terraform-sa"

# 追加するAPI、ロールがあれば(指定しなければデフォルト)

# プロジェクトに対して有効化するAPIのリスト
enabled_apis = [
  "iam.googleapis.com",
  "iamcredentials.googleapis.com",
  "cloudresourcemanager.googleapis.com",
  "run.googleapis.com",
  "artifactregistry.googleapis.com"
]

# Terraform用サービスアカウントに付与するIAMロールのリスト
terraform_sa_roles = [
  "roles/iam.serviceAccountAdmin",
  "roles/iam.workloadIdentityPoolAdmin",
  "roles/serviceusage.serviceUsageAdmin"
]

# GitHub Actions用サービスアカウントに付与するIAMロールのリスト
github_actions_roles = [
  "roles/run.admin",
  "roles/iam.serviceAccountUser",
  "roles/artifactregistry.writer"
]
# Terraform
.terraform
*.tfvars
*.tfstate
*.tfstate.*

tfファイルと.terraform.lock.hclのみGitに共有します。

Terraform実施

以上を済ませたら、terraform/にて以下を実行します。

terraform init
terraform plan
terraform apply

問題なく通れば完了です!
また、完了時にターミナルからの出力を確認します。

github_actions = {
  "PROJECT_ID" = "..."
  "SA_EMAIL" = "..."
  "WIF_PROVIDER" = "..."
  "ARTIFACT_REGISTRY_REPO_NAME" = "..."
}

4. Github Actionsのworkflow設定

先ほどの出力に基づいて、4つの変数をSecretsに設定します(参考記事)。
https://qiita.com/mkin/items/75a4928a1fafe5eacd17

そして、以下のようにActionsのワークフローファイル(.yaml)を作成します。
https://github.com/Suke-H/terraform-gcp-wif/blob/main/.github/workflows/cd.yaml

あとはmainにpushすることで、自動デプロイが実施されれば完了です!

まとめ

WIFが少し面倒な印象だったので、ここが簡単に行えるようになって効率よくなりました!今後もCloud Runは使っていきたいです。色々サービスデプロイしていきたい。

Discussion