使用 Terraform 建立觸發條件

本文說明如何使用 Terraform 和 google_eventarc_trigger 資源,為下列 Google Cloud目的地建立 Eventarc 觸發條件:

如要進一步瞭解如何使用 Terraform,請參閱 Terraform on Google Cloud 說明文件。

本指南中的程式碼範例會轉送 Cloud Storage 的直接事件,但可調整為任何事件供應器。舉例來說,如要瞭解如何將直接事件從 Pub/Sub 轉送至 Cloud Run,請參閱 Terraform 快速入門

事前準備

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Make sure that billing is enabled for your Google Cloud project.

  6. Enable the Cloud Resource Manager and Identity and Access Management (IAM) APIs.

    Enable the APIs

  7. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  8. Terraform 已整合至 Cloud Shell 環境,您可以使用 Cloud Shell 部署 Terraform 資源,而無須安裝 Terraform。

    準備部署 Terraform

    部署任何 Terraform 資源前,您必須建立 Terraform 設定檔。您可以使用 Terraform 語法,透過 Terraform 設定檔定義基礎架構的偏好最終狀態。

    準備 Cloud Shell

    在 Cloud Shell 中,設定要套用 Terraform 設定的預設 Google Cloud 專案。您只需為每個專案執行這項指令一次,而且可以在任何目錄中執行:

    export GOOGLE_CLOUD_PROJECT=PROJECT_ID

    PROJECT_ID 替換為您的 Google Cloud 專案 ID。

    請注意,如果您在 Terraform 設定檔中設定明確的值,系統會覆寫環境變數。

    準備目錄

    每個 Terraform 設定檔都必須有專屬的目錄 (也稱為「根模組」)。在 Cloud Shell 中建立目錄,並在該目錄中建立新檔案:

    mkdir DIRECTORY && cd DIRECTORY && touch main.tf

    副檔名必須包含 .tf 副檔名,例如在本文件中,檔案會稱為 main.tf

    定義 Terraform 設定

    將適用的 Terraform 程式碼範例複製到新建立的 main.tf 檔案中。您也可以從 GitHub 複製程式碼。如果 Terraform 程式碼片段是端對端解決方案的一部分,建議採用這種做法。

    通常您會一次套用整個設定。不過,您也可以指定特定資源。例如:

    terraform apply -target="google_eventarc_trigger.default"

    請注意,Terraform 程式碼範例會使用插補功能,用於替換參照變數、資源屬性和呼叫函式等項目。

    啟用 API

    Terraform 範例通常會假設您已在Google Cloud 專案中啟用必要的 API。請使用下列程式碼啟用 API:

    Cloud Run

    # Enable Cloud Run API
    resource "google_project_service" "run" {
      service            = "run.googleapis.com"
      disable_on_destroy = false
    }
    
    # Enable Eventarc API
    resource "google_project_service" "eventarc" {
      service            = "eventarc.googleapis.com"
      disable_on_destroy = false
    }
    
    # Enable Pub/Sub API
    resource "google_project_service" "pubsub" {
      service            = "pubsub.googleapis.com"
      disable_on_destroy = false
    }

    GKE

    # Enable GKE API
    resource "google_project_service" "container" {
      service            = "container.googleapis.com"
      disable_on_destroy = false
    }
    
    # Enable Eventarc API
    resource "google_project_service" "eventarc" {
      service            = "eventarc.googleapis.com"
      disable_on_destroy = false
    }
    
    # Enable Pub/Sub API
    resource "google_project_service" "pubsub" {
      service            = "pubsub.googleapis.com"
      disable_on_destroy = false
    }

    工作流程

    # Enable Workflows API
    resource "google_project_service" "workflows" {
      service            = "workflows.googleapis.com"
      disable_on_destroy = false
    }
    
    # Enable Eventarc API
    resource "google_project_service" "eventarc" {
      service            = "eventarc.googleapis.com"
      disable_on_destroy = false
    }
    
    # Enable Pub/Sub API
    resource "google_project_service" "pubsub" {
      service            = "pubsub.googleapis.com"
      disable_on_destroy = false
    }

    建立服務帳戶並設定存取權

    每個 Eventarc 觸發事件都會在建立時與 IAM 服務帳戶建立關聯。使用下列程式碼建立專用服務帳戶,並授予使用者代管的服務帳戶特定身分與存取權管理角色,以便管理事件:

    Cloud Run

    # Used to retrieve project information later
    data "google_project" "project" {}
    
    # Create a dedicated service account
    resource "google_service_account" "eventarc" {
      account_id   = "eventarc-trigger-sa"
      display_name = "Eventarc Trigger Service Account"
    }
    
    # Grant permission to receive Eventarc events
    resource "google_project_iam_member" "eventreceiver" {
      project = data.google_project.project.id
      role    = "roles/eventarc.eventReceiver"
      member  = "serviceAccount:${google_service_account.eventarc.email}"
    }
    
    # Grant permission to invoke Cloud Run services
    resource "google_project_iam_member" "runinvoker" {
      project = data.google_project.project.id
      role    = "roles/run.invoker"
      member  = "serviceAccount:${google_service_account.eventarc.email}"
    }

    啟用 Pub/Sub API 時,系統會自動建立 Pub/Sub 服務代理。如果 Pub/Sub 服務代理是在 2021 年 4 月 8 日當天或之前建立,且服務帳戶沒有 Cloud Pub/Sub 服務代理角色 (roles/pubsub.serviceAgent),請將 服務帳戶憑證建立者角色 (roles/iam.serviceAccountTokenCreator) 授予服務代理。詳情請參閱「為服務專員建立及授予角色」。

    resource "google_project_iam_member" "tokencreator" {
      project  = data.google_project.project.id
      role     = "roles/iam.serviceAccountTokenCreator"
      member   = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-pubsub.iam.gserviceaccount.com"
    }

    GKE

    1. 建立服務帳戶前,請先啟用 Eventarc 來管理 GKE 叢集:

      # Used to retrieve project_number later
      data "google_project" "project" {}
      
      # Enable Eventarc to manage GKE clusters
      # This is usually done with: gcloud eventarc gke-destinations init
      #
      # Eventarc creates a separate Event Forwarder pod for each trigger targeting a
      # GKE service, and  requires explicit permissions to make changes to the
      # cluster. This is done by granting permissions to a special service account
      # (the Eventarc P4SA) to manage resources in the cluster. This needs to be done
      # once per Google Cloud project.
      
      # This identity is created with: gcloud beta services identity create --service eventarc.googleapis.com
      # This local variable is used for convenience
      locals {
        eventarc_sa = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-eventarc.iam.gserviceaccount.com"
      }
      
      resource "google_project_iam_member" "computeViewer" {
        project = data.google_project.project.id
        role    = "roles/compute.viewer"
        member  = local.eventarc_sa
      }
      
      resource "google_project_iam_member" "containerDeveloper" {
        project = data.google_project.project.id
        role    = "roles/container.developer"
        member  = local.eventarc_sa
      }
      
      resource "google_project_iam_member" "serviceAccountAdmin" {
        project = data.google_project.project.id
        role    = "roles/iam.serviceAccountAdmin"
        member  = local.eventarc_sa
      }
    2. 建立服務帳戶:

      # Create a service account to be used by GKE trigger
      resource "google_service_account" "eventarc_gke_trigger_sa" {
        account_id   = "eventarc-gke-trigger-sa"
        display_name = "Evenarc GKE Trigger Service Account"
      }
      
      # Grant permission to receive Eventarc events
      resource "google_project_iam_member" "eventreceiver" {
        project = data.google_project.project.id
        role    = "roles/eventarc.eventReceiver"
        member  = "serviceAccount:${google_service_account.eventarc_gke_trigger_sa.email}"
      }
      
      # Grant permission to subscribe to Pub/Sub topics
      resource "google_project_iam_member" "pubsubscriber" {
        project = data.google_project.project.id
        role    = "roles/pubsub.subscriber"
        member  = "serviceAccount:${google_service_account.eventarc_gke_trigger_sa.email}"
      }
      

    工作流程

    # Used to retrieve project information later
    data "google_project" "project" {}
    
    # Create a service account for Eventarc trigger and Workflows
    resource "google_service_account" "eventarc" {
      account_id   = "eventarc-workflows-sa"
      display_name = "Eventarc Workflows Service Account"
    }
    
    # Grant permission to invoke Workflows
    resource "google_project_iam_member" "workflowsinvoker" {
      project = data.google_project.project.id
      role    = "roles/workflows.invoker"
      member  = "serviceAccount:${google_service_account.eventarc.email}"
    }
    
    # Grant permission to receive events
    resource "google_project_iam_member" "eventreceiver" {
      project = data.google_project.project.id
      role    = "roles/eventarc.eventReceiver"
      member  = "serviceAccount:${google_service_account.eventarc.email}"
    }
    
    # Grant permission to write logs
    resource "google_project_iam_member" "logwriter" {
      project = data.google_project.project.id
      role    = "roles/logging.logWriter"
      member  = "serviceAccount:${google_service_account.eventarc.email}"
    }

    啟用 Pub/Sub API 時,系統會自動建立 Pub/Sub 服務代理。如果 Pub/Sub 服務代理是在 2021 年 4 月 8 日當天或之前建立,且服務帳戶沒有 Cloud Pub/Sub 服務代理角色 (roles/pubsub.serviceAgent),請將 服務帳戶憑證建立者角色 (roles/iam.serviceAccountTokenCreator) 授予服務代理。詳情請參閱「為服務專員建立及授予角色」。

    resource "google_project_iam_member" "tokencreator" {
      project  = data.google_project.project.id
      role     = "roles/iam.serviceAccountTokenCreator"
      member   = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-pubsub.iam.gserviceaccount.com"
    }

    建立 Cloud Storage bucket 做為事件供應器

    使用以下程式碼建立 Cloud Storage 值區,並將 Pub/Sub 發布者角色 (roles/pubsub.publisher) 授予 Cloud Storage 服務代理。

    Cloud Run

    # Cloud Storage bucket names must be globally unique
    resource "random_id" "bucket_name_suffix" {
      byte_length = 4
    }
    
    # Create a Cloud Storage bucket
    resource "google_storage_bucket" "default" {
      name          = "trigger-cloudrun-${data.google_project.project.name}-${random_id.bucket_name_suffix.hex}"
      location      = google_cloud_run_v2_service.default.location
      force_destroy = true
    
      uniform_bucket_level_access = true
    }
    
    # Grant the Cloud Storage service account permission to publish pub/sub topics
    data "google_storage_project_service_account" "gcs_account" {}
    resource "google_project_iam_member" "pubsubpublisher" {
      project = data.google_project.project.id
      role    = "roles/pubsub.publisher"
      member  = "serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"
    }

    GKE

    # Cloud Storage bucket names must be globally unique
    resource "random_id" "bucket_name_suffix" {
      byte_length = 4
    }
    
    # Create a Cloud Storage bucket
    resource "google_storage_bucket" "default" {
      name          = "trigger-gke-${data.google_project.project.name}-${random_id.bucket_name_suffix.hex}"
      location      = "us-central1"
      force_destroy = true
    
      uniform_bucket_level_access = true
    }
    
    # Grant the Cloud Storage service account permission to publish pub/sub topics
    data "google_storage_project_service_account" "gcs_account" {}
    resource "google_project_iam_member" "pubsubpublisher" {
      project = data.google_project.project.id
      role    = "roles/pubsub.publisher"
      member  = "serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"
    }

    工作流程

    # Cloud Storage bucket names must be globally unique
    resource "random_id" "bucket_name_suffix" {
      byte_length = 4
    }
    
    # Create a Cloud Storage bucket
    resource "google_storage_bucket" "default" {
      name          = "trigger-workflows-${data.google_project.project.name}-${random_id.bucket_name_suffix.hex}"
      location      = google_workflows_workflow.default.region
      force_destroy = true
    
      uniform_bucket_level_access = true
    }
    
    # Grant the Cloud Storage service account permission to publish Pub/Sub topics
    data "google_storage_project_service_account" "gcs_account" {}
    resource "google_project_iam_member" "pubsubpublisher" {
      project = data.google_project.project.id
      role    = "roles/pubsub.publisher"
      member  = "serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"
    }

    建立事件接收器做為事件目標

    使用下列任一 Terraform 資源建立事件接收器:

    Cloud Run

    建立 Cloud Run 服務,做為 Eventarc 觸發條件的事件目的地:

    # Deploy Cloud Run service
    resource "google_cloud_run_v2_service" "default" {
      name     = "hello-events"
      location = "us-central1"
    
      deletion_protection = false # set to "true" in production
    
      template {
        containers {
          # This container will log received events
          image = "us-docker.pkg.dev/cloudrun/container/hello"
        }
        service_account = google_service_account.eventarc.email
      }
    
      depends_on = [google_project_service.run]
    }

    GKE

    為簡化本指南,請在套用 Terraform 設定之間,建立 Google Kubernetes Engine 服務做為 Terraform 以外的事件目的地。

    1. 如果您之前未在這個 Google Cloud 專案中建立觸發條件,請執行下列指令來建立 Eventarc 服務代理

      gcloud beta services identity create --service eventarc.googleapis.com
    2. 建立 GKE 叢集:

      # Create an auto-pilot GKE cluster
      resource "google_container_cluster" "gke_cluster" {
        name     = "eventarc-cluster"
        location = "us-central1"
      
        enable_autopilot = true
      
        depends_on = [
          google_project_service.container
        ]
      }
    3. 在 GKE 上部署 Kubernetes 服務,使用預先建立的 Cloud Run 映像檔,接收 HTTP 要求和記錄事件:us-docker.pkg.dev/cloudrun/container/hello

      1. 取得驗證憑證以與叢集互動:

        gcloud container clusters get-credentials eventarc-cluster \
           --region=us-central1
        
      2. 建立名為 hello-gke 的部署:

        kubectl create deployment hello-gke \
           --image=us-docker.pkg.dev/cloudrun/container/hello
        
      3. 將部署作業公開為 Kubernetes 服務:

        kubectl expose deployment hello-gke \
           --type ClusterIP --port 80 --target-port 8080
        
      4. 確認 Pod 是否正在執行:

        kubectl get pods
        

        畫面會顯示如下的輸出內容:

        NAME                         READY   STATUS    RESTARTS   AGE
        hello-gke-5b6574b4db-rzzcr   1/1     Running   0          2m45s
        

        如果 STATUSPendingContainerCreating,表示 Pod 正在部署。請稍候一分鐘,等待部署作業完成,然後再次檢查狀態。

      5. 確認服務是否正在執行:

        kubectl get svc
        

        畫面會顯示如下的輸出內容:

        NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
        hello-gke    ClusterIP   34.118.230.123   <none>        80/TCP    4m46s
        kubernetes   ClusterIP   34.118.224.1     <none>        443/TCP   14m
        

    工作流程

    部署工作流程,在 Cloud Storage 值區中更新物件時執行:

    # Create a workflow
    resource "google_workflows_workflow" "default" {
      name            = "storage-workflow-tf"
      region          = "us-central1"
      description     = "Workflow that returns information about storage events"
      service_account = google_service_account.eventarc.email
    
      deletion_protection = false # set to "true" in production
    
      # Note that $$ is needed for Terraform
      source_contents = <<EOF
      main:
        params: [event]
        steps:
          - log_event:
              call: sys.log
              args:
                text: $${event}
                severity: INFO
          - gather_data:
              assign:
                - bucket: $${event.data.bucket}
                - name: $${event.data.name}
                - message: $${"Received event " + event.type + " - " + bucket + ", " + name}
          - return_data:
              return: $${message}
      EOF
    
      depends_on = [
        google_project_service.workflows
      ]
    }

    定義 Eventarc 觸發條件

    Eventarc 觸發條件會將事件從事件提供者轉送至事件目的地。使用 google_eventarc_trigger 資源,在 matching_criteria 中指定 CloudEvents 屬性並篩選事件。如需詳細資訊,請按照為特定提供者、事件類型和目的地建立觸發條件的操作說明操作。系統會將符合所有篩選條件的事件傳送至目的地。

    Cloud Run

    建立 Eventarc 觸發條件,將 Cloud Storage 事件轉送至 hello-event Cloud Run 服務。

    # Create an Eventarc trigger, routing Cloud Storage events to Cloud Run
    resource "google_eventarc_trigger" "default" {
      name     = "trigger-storage-cloudrun-tf"
      location = google_cloud_run_v2_service.default.location
    
      # Capture objects changed in the bucket
      matching_criteria {
        attribute = "type"
        value     = "google.cloud.storage.object.v1.finalized"
      }
      matching_criteria {
        attribute = "bucket"
        value     = google_storage_bucket.default.name
      }
    
      # Send events to Cloud Run
      destination {
        cloud_run_service {
          service = google_cloud_run_v2_service.default.name
          region  = google_cloud_run_v2_service.default.location
        }
      }
    
      service_account = google_service_account.eventarc.email
      depends_on = [
        google_project_service.eventarc,
        google_project_iam_member.pubsubpublisher
      ]
    }

    GKE

    建立 Eventarc 觸發條件,將 Cloud Storage 事件轉送至 hello-gke GKE 服務。

    # Create an Eventarc trigger, routing Storage events to GKE
    resource "google_eventarc_trigger" "default" {
      name     = "trigger-storage-gke-tf"
      location = "us-central1"
    
      # Capture objects changed in the bucket
      matching_criteria {
        attribute = "type"
        value     = "google.cloud.storage.object.v1.finalized"
      }
      matching_criteria {
        attribute = "bucket"
        value     = google_storage_bucket.default.name
      }
    
      # Send events to GKE service
      destination {
        gke {
          cluster   = "eventarc-cluster"
          location  = "us-central1"
          namespace = "default"
          path      = "/"
          service   = "hello-gke"
        }
      }
    
      service_account = google_service_account.eventarc_gke_trigger_sa.email
    }

    工作流程

    建立 Eventarc 觸發條件,將 Cloud Storage 事件轉送至名為 storage-workflow-tf 的工作流程。

    # Create an Eventarc trigger, routing Cloud Storage events to Workflows
    resource "google_eventarc_trigger" "default" {
      name     = "trigger-storage-workflows-tf"
      location = google_workflows_workflow.default.region
    
      # Capture objects changed in the bucket
      matching_criteria {
        attribute = "type"
        value     = "google.cloud.storage.object.v1.finalized"
      }
      matching_criteria {
        attribute = "bucket"
        value     = google_storage_bucket.default.name
      }
    
      # Send events to Workflows
      destination {
        workflow = google_workflows_workflow.default.id
      }
    
      service_account = google_service_account.eventarc.email
    
      depends_on = [
        google_project_service.eventarc,
        google_project_service.workflows,
      ]
    }

    套用 Terraform

    使用 Terraform CLI 根據設定檔佈建基礎架構。

    如要瞭解如何套用或移除 Terraform 設定,請參閱「基本 Terraform 指令」。

    1. 初始化 Terraform。這項操作只需對每個目錄執行一次。

      terraform init

      如要使用最新的 Google 供應器版本,請視需要加入 -upgrade 選項:

      terraform init -upgrade
    2. 檢查設定,確認 Terraform 將要建立或更新的資源符合您的預期:

      terraform plan

      視需要修正設定。

    3. 執行下列指令,並在提示訊息中輸入 yes,即可套用 Terraform 設定:

      terraform apply

      等待 Terraform 顯示「Apply complete!」(套用完成) 訊息。

    確認資源建立作業

    Cloud Run

    1. 確認服務已建立:

      gcloud run services list --region us-central1
      
    2. 確認已建立觸發條件:

      gcloud eventarc triggers list --location us-central1
      

      畫面會顯示如下的輸出內容:

      NAME: trigger-storage-cloudrun-tf
      TYPE: google.cloud.storage.object.v1.finalized
      DESTINATION: Cloud Run service: hello-events
      ACTIVE: Yes
      LOCATION: us-central1
      

    GKE

    1. 確認服務已建立:

      kubectl get service hello-gke
      
    2. 確認已建立觸發條件:

      gcloud eventarc triggers list --location us-central1
      

      畫面會顯示如下的輸出內容:

      NAME: trigger-storage-gke-tf
      TYPE: google.cloud.storage.object.v1.finalized
      DESTINATION: GKE: hello-gke
      ACTIVE: Yes
      LOCATION: us-central1
      

    工作流程

    1. 確認工作流程已建立:

      gcloud workflows list --location us-central1
      
    2. 確認已建立 Eventarc 觸發條件:

      gcloud eventarc triggers list --location us-central1
      

      畫面會顯示如下的輸出內容:

      NAME: trigger-storage-workflows-tf
      TYPE: google.cloud.storage.object.v1.finalized
      DESTINATION: Workflows: storage-workflow-tf
      ACTIVE: Yes
      LOCATION: us-central1
      

    產生及查看事件

    您可以產生事件,並確認 Eventarc 觸發條件是否正常運作。

    1. 擷取先前建立的 Cloud Storage 值區名稱:

      gcloud storage ls
      
    2. 將文字檔案上傳至 Cloud Storage 值區:

      echo "Hello World" > random.txt
      gcloud storage cp random.txt gs://BUCKET_NAME/random.txt
      

      BUCKET_NAME 替換為您在上一個步驟中擷取的 Cloud Storage 值區名稱。例如:

      gcloud storage cp random.txt gs://BUCKET_NAME/random.txt

      上傳作業會產生事件,而事件接收器服務會記錄事件的訊息。

    3. 確認是否已收到事件:

      Cloud Run

      1. 篩選服務建立的記錄項目:

        gcloud logging read 'jsonPayload.message: "Received event of type google.cloud.storage.object.v1.finalized."'
        
      2. 尋找類似下列內容的記錄項目:

        Received event of type google.cloud.storage.object.v1.finalized.
        Event data: { "kind": "storage#object", "id": "trigger-cloudrun-BUCKET_NAME/random.txt", ...}
        

      GKE

      1. 找出 pod ID:

        POD_NAME=$(kubectl get pods -o custom-columns=":metadata.name" --no-headers)
        

        這個指令會使用 kubectl格式化輸出內容

      2. 查看 Pod 的記錄:

        kubectl logs $POD_NAME
        
      3. 尋找類似下列內容的記錄項目:

        {"severity":"INFO","eventType":"google.cloud.storage.object.v1.finalized","message":
        "Received event of type google.cloud.storage.object.v1.finalized. Event data: ...}
        

      工作流程

      1. 如要確認是否已觸發工作流程執行作業,請列出最近五次的執行作業:

        gcloud workflows executions list storage-workflow-tf --limit=5
        

        輸出結果應包含執行作業的清單,其中包含 NAMESTATESTART_TIMEEND_TIME

      2. 取得最近一次執行作業的結果:

        EXECUTION_NAME=$(gcloud workflows executions list storage-workflow-tf --limit=1 --format "value(name)")
        gcloud workflows executions describe $EXECUTION_NAME
        
      3. 確認輸出內容與下列內容相似:

        ...
        result: '"Received event google.cloud.storage.object.v1.finalized - BUCKET_NAME, random.txt"'
        startTime: '2024-12-13T17:23:50.451316533Z'
        state: SUCCEEDED
        ...
        

    清除所用資源

    如要移除先前透過 Terraform 設定套用的資源,請執行下列指令,並在提示中輸入 yes

    terraform destroy

    您也可以刪除 Google Cloud 專案,以免產生費用。刪除 Google Cloud 專案後,系統就會停止對專案使用的所有資源收取費用。

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    後續步驟