★★ 中級

08. Cloud Run / Functions

GCP のサーバーレスは Cloud Run が主役。コンテナをそのまま動かせて 0 にもスケールイン。Cloud Functions(旧称)は v2 で Cloud Run の派生サービスに統合されました。

3 つの選択肢

Cloud Run serviceCloud Run jobsCloud Functions v2
形態HTTP コンテナバッチコンテナ関数(コード or コンテナ)
スケール0 → 1000並列実行0 → 1000
料金vCPU・メモリ秒実行時間呼び出し従量
用途Web/API定期バッチ・ETLイベント駆動
AWS 対応Lambda + FargateBatch + ECS TaskLambda

Cloud Run service

resource "google_cloud_run_v2_service" "api" {
  name     = "myapp-api"
  location = "asia-northeast1"
  ingress  = "INGRESS_TRAFFIC_ALL"   # or INTERNAL / INTERNAL_AND_CLOUD_LOAD_BALANCING

  template {
    service_account = google_service_account.app.email

    scaling {
      min_instance_count = 0
      max_instance_count = 100
    }

    containers {
      image = "${google_artifact_registry_repository.main.location}-docker.pkg.dev/${google_artifact_registry_repository.main.project}/${google_artifact_registry_repository.main.repository_id}/api:v1.2.0"

      resources {
        limits = {
          cpu    = "1"
          memory = "512Mi"
        }
        cpu_idle = true   # Request 処理中以外は CPU 0(コスト削減)
      }

      env {
        name  = "LOG_LEVEL"
        value = "info"
      }

      env {
        name = "DB_PASSWORD"
        value_source {
          secret_key_ref {
            secret  = google_secret_manager_secret.db_password.secret_id
            version = "latest"
          }
        }
      }

      ports {
        container_port = 8080
      }

      startup_probe {
        http_get {
          path = "/health"
        }
        initial_delay_seconds = 10
        timeout_seconds       = 5
        period_seconds        = 10
      }
    }

    # VPC アクセス(Cloud SQL Private IP 等)
    vpc_access {
      network_interfaces {
        network    = google_compute_network.main.id
        subnetwork = google_compute_subnetwork.private.id
      }
      egress = "PRIVATE_RANGES_ONLY"
    }
  }

  traffic {
    type    = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
    percent = 100
  }
}

# 全公開(認証なし)。本番は通常付けない
resource "google_cloud_run_v2_service_iam_member" "public" {
  location = google_cloud_run_v2_service.api.location
  name     = google_cloud_run_v2_service.api.name
  role     = "roles/run.invoker"
  member   = "allUsers"
}

output "api_url" {
  value = google_cloud_run_v2_service.api.uri
}

Cloud Run jobs

HTTP リクエストではなく「実行 → 完了」型のバッチ。AWS の ECS RunTask / Batch 相当。

resource "google_cloud_run_v2_job" "nightly" {
  name     = "nightly-cleanup"
  location = "asia-northeast1"

  template {
    template {
      service_account = google_service_account.app.email
      timeout         = "600s"
      max_retries     = 3

      containers {
        image   = "asia-northeast1-docker.pkg.dev/myapp-prd/main/cleanup:latest"
        command = ["./cleanup"]
        args    = ["--mode=full"]

        resources {
          limits = {
            cpu    = "2"
            memory = "1Gi"
          }
        }
      }
    }
  }
}

# Cloud Scheduler で毎日 03:00 JST に起動
resource "google_cloud_scheduler_job" "nightly" {
  name      = "nightly-cleanup"
  schedule  = "0 18 * * *"   # UTC 18:00 = JST 03:00
  time_zone = "Etc/UTC"

  http_target {
    http_method = "POST"
    uri         = "https://${google_cloud_run_v2_job.nightly.location}-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/myapp-prd/jobs/${google_cloud_run_v2_job.nightly.name}:run"

    oauth_token {
      service_account_email = google_service_account.scheduler.email
    }
  }
}

Cloud Functions v2

イベントトリガで動く関数。実体は Cloud Run の薄いラッパー。Eventarc 経由で各種 GCP イベントから起動可能。

resource "google_cloudfunctions2_function" "process_upload" {
  name     = "process-upload"
  location = "asia-northeast1"

  build_config {
    runtime     = "nodejs20"
    entry_point = "handler"
    source {
      storage_source {
        bucket = google_storage_bucket.source.name
        object = google_storage_bucket_object.source.name
      }
    }
  }

  service_config {
    max_instance_count             = 10
    available_memory               = "256M"
    timeout_seconds                = 60
    service_account_email          = google_service_account.app.email
    ingress_settings               = "ALLOW_INTERNAL_ONLY"
  }

  event_trigger {
    trigger_region        = "asia-northeast1"
    event_type            = "google.cloud.storage.object.v1.finalized"
    retry_policy          = "RETRY_POLICY_RETRY"
    service_account_email = google_service_account.app.email

    event_filters {
      attribute = "bucket"
      value     = google_storage_bucket.uploads.name
    }
  }
}

Artifact Registry

resource "google_artifact_registry_repository" "main" {
  location      = "asia-northeast1"
  repository_id = "main"
  format        = "DOCKER"
  description   = "myapp container images"

  cleanup_policies {
    id     = "keep-latest-20"
    action = "KEEP"
    most_recent_versions {
      keep_count = 20
    }
  }

  cleanup_policies {
    id     = "delete-old-untagged"
    action = "DELETE"
    condition {
      tag_state  = "UNTAGGED"
      older_than = "604800s"   # 7 日
    }
  }
}

# Cloud Run の SA に pull 権限
resource "google_artifact_registry_repository_iam_member" "app_reader" {
  location   = google_artifact_registry_repository.main.location
  repository = google_artifact_registry_repository.main.name
  role       = "roles/artifactregistry.reader"
  member     = "serviceAccount:${google_service_account.app.email}"
}

GKE Autopilot との比較

シナリオ推奨
シンプルな API・WebCloud Run
定期バッチCloud Run jobs + Scheduler
イベント駆動(Storage / Pub/Sub)Cloud Functions v2
複雑なマイクロサービス・StatefulSetGKE Autopilot
既存 Kubernetes 資産ありGKE