はじめに
今回Cloud RunにてCloud Storageのバケットをterraformを使用してマウントする方法を紹介したいと思います。
概要
公式ドキュメントには以下のやり方が載っています。
resource "google_cloud_run_v2_service" "default" { name = "cloudrun-service" location = "us-central1" deletion_protection = false template { execution_environment = "EXECUTION_ENVIRONMENT_GEN2" containers { image = "us-docker.pkg.dev/cloudrun/container/hello" volume_mounts { name = "bucket" mount_path = "/var/www" } } volumes { name = "bucket" gcs { bucket = google_storage_bucket.default.name read_only = false } } } } resource "google_storage_bucket" "default" { name = "cloudrun-service" location = "US" }
ただlocationがUS前提になっていたり、サービスアカウントの設定をしないとGCS上のデータを取得できなかったりとしたため、自身で上手くいった方法を紹介したいと思います。
GCSの構築
# GCSバケット構築 resource "google_storage_bucket" "default" { name = "-------" location = "ASIA-NORTHEAST1" force_destroy = true }
nameは被りのないような名前にしないといけません。またforce_destoryを設定することで、バケット内にオブジェクトが存在していてもTerraformがバケットを削除できるようにします。
IAM・サービスアカウントの設定
# 外部からアクセスするようにIAM Policy設定 # allUsers(全てのユーザー)にroles/run.invoker(サービスとジョブの呼び出し、ジョブ実行のキャンセルが可能)を付与する data "google_iam_policy" "noauth" { binding { role = "roles/run.invoker" members = ["allUsers"] } } # IAMポリシーをCloud Runに適応する resource "google_cloud_run_v2_service_iam_policy" "policy" { location = "asia-northeast1" name = google_cloud_run_v2_service.default.name policy_data = data.google_iam_policy.noauth.policy_data } # Cloud Run用のサービスアカウントを作成 resource "google_service_account" "cloud_run_service_account" { account_id = "cloud-run-service-account" display_name = "Cloud Run Service Account" } # Cloud RunのサービスアカウントにGCSのAdmin権限を付与 resource "google_project_iam_member" "cloud_run_storage_admin" { project = var.project_id role = "roles/storage.objectAdmin" member = "serviceAccount:${google_service_account.cloud_run_service_account.email}" }
IAMを使用したアクセス制御により、Cloud Runに外部からアクセスできるようにしました。このあたりは適宜変更してください。
またCloudRunからGCSにアクセスするためにサービスアカウントを定義してあげます。定義したサービスアカウントはCloud Runに設定してあげないと適応されないので注意してください。
Cloud Runの定義
resource "google_cloud_run_v2_service" "default" { name = "sample" location = "asia-northeast1" ingress = "INGRESS_TRAFFIC_ALL" deletion_protection = false template { service_account = google_service_account.cloud_run_service_account.email execution_environment = "EXECUTION_ENVIRONMENT_GEN2" containers { image = "asia-northeast1-docker.pkg.dev/-----:latest" volume_mounts { name = "bucket" mount_path = "/mnt/gcs" } } volumes { name = "bucket" gcs { bucket = google_storage_bucket.default.name read_only = false } } } }
service_accountに対して、先ほど定義したサービスアカウントを設定してあげてください。
GCS上のファイルを表示するC#コード
正しくmountできているのかを確認できるようなサーバーを構築する.NETのプロジェクトを作成し、Artifact Registoryにアップロードしました。
// Program.cs using System.Text; var builder = WebApplication.CreateBuilder(args); var port = Environment.GetEnvironmentVariable("PORT") ?? "8080"; var url = $"http://0.0.0.0:{port}"; var app = builder.Build(); app.MapGet("/", () => { var sb = new StringBuilder(); var directoryPath = "/mnt/gcs"; if (Directory.Exists(directoryPath)) { var files = Directory.GetFiles(directoryPath, "*", SearchOption.AllDirectories); foreach (var file in files) { sb.AppendLine($"File: {file}"); sb.AppendLine(File.ReadAllText(file)); } } else { sb.AppendLine("Directory does not exist."); } return sb.ToString(); }); app.Run(url);
terraformにてGCSを/mnt/gcsフォルダにマウントしています。ですのでそのディレクトリ以下に対して、ファイルが存在したら表示をしています。
アップロード方法等は以下記事を参照してみてください。
www.hanachiru-blog.com
実際に動作している様子

Cloud Console上でCloudRunのリビジョンからVOLUMESを確認すると、確かにCloud Storageバケットにマウント先が設定されていました。