examlab .net 用最有效率的方法,考取最有價值的證照
本篇導覽 約 18 分鐘

Terraform 與 Google Provider

3,600 字 · 約 18 分鐘閱讀 ·

專業雲端架構師 (Professional Cloud Architect) 使用 Terraform 進行基礎設施即程式碼 (IaC) 的指南,重點在於 Google Cloud provider、狀態管理和最佳實踐。

立即做 20 題練習 → 免費 · 不用註冊 · PCA

GCP 上的 Terraform 簡介

對於專業雲端架構師 (Professional Cloud Architect) 來說,Terraform 是基礎設施即程式碼 (Infrastructure as Code, IaC) 的業界標準工具。它允許你使用聲明式語言 (HCL) 定義 Google Cloud 資源,並透過版本控制的工作流程進行管理。

Google Provider 是 Terraform 與 Google Cloud API 之間的橋樑。

PCA 情境若要求「在數百個 GCP 專案上可重複部署的 Landing Zone」,標準答案是使用 Terraform 搭配 hashicorp/google provider、放在 GCS backend 的遠端 state,以及 Cloud Foundation Toolkit (CFT) 模組。Console 點擊或 gcloud script 在企業級、可稽核的部署場景中都不是正確答案。


白話文解釋(Plain English Explanation)

比喻 1 — IKEA 組裝說明書 vs 手工家具

google provider 就像 GCP 的 IKEA 組裝說明書。說明書 (HCL) 宣告書櫃最終的樣子(google_compute_networkgoogle_storage_bucket);六角扳手 (provider 外掛) 把每個步驟翻譯成正確的 GCP API 呼叫。如果你用 gcloud script 手工打造,每張椅子做出來都會略有差異 —— IaC 確保第 500 張椅子和第 1 張長得一模一樣。

比喻 2 — 雙鑰匙保管箱 (State + Locking)

放在 GCS backend 的 Terraform state 檔案加上 state locking 就像銀行的雙鑰匙保管箱:銀行的鑰匙(GCS object lock)和你的鑰匙(你的憑證)缺一不可。兩位櫃員(兩個 terraform apply 執行)不能同時打開保管箱 —— 一個必須等另一個結束。沒有 locking 的話,兩位櫃員同時更新帳本,結果就是兩份互相矛盾的紀錄,搞不清楚 google_compute_instance 到底屬於誰。

比喻 3 — 樂高大師組 (CFT 模組)

Cloud Foundation Toolkit (CFT) 的 Project Factory 和 IAM 模組就像 Google 出版的官方認證樂高大師組。你不用從零設計太空船(手刻 google_project + google_billing_account_iam_member + 啟用 API),而是直接組合一個 Project Factory 模組,它已經內建翅膀、駕駛艙與安全貼紙 —— Shared VPC 連接預算告警預設 IAM 綁定通通都附好。


Terraform 核心概念

  1. HCL (HashiCorp Configuration Language): 用於編寫 Terraform 檔案 (.tf) 的人類可讀語言。
  2. State (狀態): 一個映射程式碼與 GCP 中實際資源的檔案 (terraform.tfstate)。
  3. Plan (計畫): Terraform 將對你的基礎設施進行更改的預覽。
  4. Apply (套用): 執行計畫並在 GCP 中進行更改的過程。

Terraform 的白話文比喻

比喻 1 — 建築藍圖 (IaC)

想像正在建造一棟摩天大樓。Terraform 就是藍圖。你不是告訴工人「在這裡放一塊磚頭,然後在那裡放一扇窗戶」(這是腳本/CLI 做的事),而是交給他們一張圖紙,上面寫著「這棟建築應該有 50 層樓和 200 扇窗戶」。工人(Terraform)查看圖紙,看現在已經有什麼,然後精確地補上缺少的內容以符合圖紙。

比喻 2 — 收據與庫存清單 (狀態管理)

Terraform 狀態檔案 (State file) 就像是超市的詳細收據結合庫存清單。如果你弄丟了收據,商店 (GCP) 裡雖然還有那些物品,但你不知道你確切買了什麼或放在哪裡。狀態檔案告訴 Terraform:「上次我們檢查時,GCP 中的這個特定 ID 屬於你程式碼中的這個特定資源。」

比喻 3 — 樂高積木 (模組)

Terraform 模組 (Modules) 就像是預先拼好的樂高套裝。你不需要每次都用 500 個微小零件拼出一輛「車子」,而是建立一個「車子模組」。現在,每當你需要一輛車時,只需說 module "my_car" { color = "red" }。這讓你的基礎設施保持一致且易於擴展。


Google Cloud Provider

Provider 負責處理與 GCP 的身分驗證和 API 呼叫。

provider "google" {
  project = "my-project-id"
  region  = "us-central1"
}
  • google provider: 用於正式版 (GA) 資源。
  • google-beta provider: 用於仍處於 Beta 階段的資源或功能。你可以在同一個專案中同時使用兩者。

狀態管理最佳實踐

這是 PCA 考試的一個關鍵主題。

  1. 遠端狀態 (Remote State): 絕對不要將狀態檔案保留在你的本地筆電上。將其存儲在 Cloud Storage Bucket 中。
    • 在 Bucket 上啟用物件版本控制 (Object Versioning),以便從意外的狀態損壞中恢復。
  2. 狀態鎖定 (State Locking): 使用支援鎖定的後端(如 GCS),以防止兩個人同時執行 terraform apply 並導致狀態損壞。
  3. 敏感資料: 請記住,狀態檔案包含純文字形式的敏感資料(如資料庫密碼)。使用 IAM 和加密來保護 GCS Bucket。

進階 Terraform 模式

1. Workspaces

使用 Workspaces 透過相同的程式碼管理不同的環境(Dev、Prod)。然而,對於大型企業級 GCP 環境,許多架構師偏好為每個環境使用獨立的目錄,以實現更好的隔離。

2. 輸出變數 (Output Variables)

使用 output 來導出資訊(如 IP 位址或 Service Account 電子郵件),這些資訊可以被基礎設施的其他部分使用,或與其他團隊共享。

3. 資源目標定位 (Resource Targeting)

如果你需要修復特定的資源而不觸及其他部分:terraform apply -target=google_compute_instance.my_vm。請謹慎使用此功能,因為它可能導致狀態不一致。

::promoted

架構師洞察: 在執行 apply 之前,務必先執行 terraform plan 並檢查輸出。這是你的「安全帶」,可以防止意外刪除生產環境的資料庫。 ::


Provider —— Terraform 的外掛,負責把 HCL 資源宣告轉譯成對目標平台的身分驗證 API 呼叫。對 GCP 而言,相關的 provider 有兩個:hashicorp/google (GA) 與 hashicorp/google-beta (預覽功能)。同一個 root module 可以同時宣告兩者,並透過 provider = google-beta meta-argument 把特定資源導向 Beta provider。

google 與 google-beta Provider

HashiCorp registry 為 GCP 發佈了兩個獨立的 provider,PCA 考試你必須知道何時用哪個:

  • hashicorp/google (GA provider): 對應正式版的 GCP REST endpoint(例如 compute.googleapis.com/v1container.googleapis.com/v1),有 HashiCorp 標準 SLA,大約每週發佈一次。
  • hashicorp/google-beta 暴露屬於 GCP Beta API 的資源與引數(例如 container.googleapis.com/v1beta1)。GKE Autopilot 的 DNS-based endpoint、部分 Cloud Run 預覽 flagAlloyDB 預覽功能等都會先在這裡登場。

你可以在同一個 root module 宣告兩者,逐個資源指定:

terraform {
  required_providers {
    google      = { source = "hashicorp/google",      version = "~> 5.0" }
    google-beta = { source = "hashicorp/google-beta", version = "~> 5.0" }
  }
}

resource "google_container_cluster" "preview" {
  provider = google-beta   # 此 cluster 採用 Beta 功能
  name     = "edge-cluster"
  # ...
}

為什麼架構師要在意

  1. 升級時的資源漂移。 某個 Beta 引數升上 GA 後可能會改名;單純把 provider = google-beta 改成 provider = google 可能觸發 force replacement。請明確 pin 住版本。
  2. 同一專案內混用。 95% 的資源用 google、少數最前沿資源用 google-beta 是受支援且常見的做法。
  3. 驗證機制共用。 兩個 provider 都消耗同一份 Application Default Credentials,也共用 project / region 引數。

常見陷阱:把某個 Beta-only 的引數(例如 enable_l4_ilb_subsetting 還在 Beta 時)抄到 provider = google 的資源區塊。Terraform 在語法上會接受,但 apply 時 GA API 會拒絕該欄位。請務必檢查 registry 文件頁標頭是「Beta」還是 GA。


Resource Lifecycle Meta-Arguments

每個 Terraform 資源都接受一個 lifecycle 區塊,用來覆寫預設的 plan/apply 行為。PCA 中與零停機切換生產資源保護相關的情境,幾乎都靠這些參數解決。

create_before_destroy

預設順序是先 destroy 再 create。對於掛在 google_compute_instance_group_manager 上的 google_compute_instance_template,這會造成中斷。設定:

lifecycle {
  create_before_destroy = true
}

Terraform 會先建好新 template、把 MIG 指向新 template、再刪除舊 template,藉此保留 rolling update。

prevent_destroy

針對有狀態資源的安全閘門:

resource "google_sql_database_instance" "prod" {
  # ...
  lifecycle { prevent_destroy = true }
}

任何會刪除此 google_sql_database_instance 的計畫(包含 terraform destroy 或上游變更觸發的 replacement)會在 plan 階段就失敗。必須先用一個獨立 commit 移除這個 flag,資源才能被刪除 —— 非常適合生產 Cloud SQL 與存放法遵資料的 GCS bucket

ignore_changes

當外部系統會修改某個屬性、而你不希望 Terraform「糾正」它時使用:

resource "google_compute_instance" "vm" {
  lifecycle {
    ignore_changes = [metadata["ssh-keys"], labels["last-deployed-at"]]
  }
}

GCP 上常見例子:OS Login 金鑰輪替、MIG autoscaler 託管的 target_size、或被 Cloud Asset Inventory 自動化修補的 label。

replace_triggered_by (Terraform 1.2+)

當資源 B 改變時,強制重建資源 A —— 適合把 google_compute_instance 綁到 startup-script google_storage_bucket_object 的雜湊值上。


GCS 上的遠端 State 與 Locking

GCP Terraform 推薦的 backend 是 gcs

terraform {
  backend "gcs" {
    bucket  = "tf-state-prod-acme-co"
    prefix  = "platform/network"
  }
}

內建好處

  • 強一致性 —— Cloud Storage 提供寫後即讀一致性,plan/apply 總能讀到最新 state。
  • 原生 state locking —— 從 provider v4+ 起,gcs backend 用 Cloud Storage object generation condition 實作 locking;不需要額外的 Firestore/DynamoDB 元件(不像 S3 backend 需要 DynamoDB)。早期設計曾把 GCS 配 Firestore 文件儲存 lock metadata,但現代設定都改用內建機制。
  • 物件版本控制 (Object Versioning) —— 在 state bucket 啟用後,損壞的 state 可以用 gsutil cp gs://bucket/path#<generation> . 回滾到先前的 generation。
  • CMEK 加密 —— 在 bucket 設 kms_key_name,用 Cloud KMS 加密 state,滿足禁止 Google-managed key 的法遵要求。

強化檢查清單

  1. State 用獨立專案,跟工作負載專案分開。
  2. Uniform bucket-level access + 只把 roles/storage.objectAdmin 授予 CI/CD service account。
  3. VPC Service Controls perimeter 圍住 state bucket,防止 state(含 secrets)被外洩。
  4. 在 bucket 啟用 Audit Logs(Data Access)—— 每次 terraform plan 都會留下 objects.get 紀錄。

Terraform state 檔案會以明文儲存 secrets —— 來自 google_sql_user 的資料庫密碼、service account key、Secret Manager 版本。把 state bucket 當作 Tier-0 資產(CMEK + VPC SC + 嚴格 IAM)對受監管的工作負載是不容妥協的要求。


Cloud Foundation Toolkit (CFT) 模組

Cloud Foundation Toolkit 是 Google 發佈在 github.com/terraform-google-modules 的開源 Terraform 模組集合。用 CFT 與手刻 Landing Zone 的差距,就是「半年後仍維持一致」與「半年後 drift 到面目全非」的差距。

PCA 必懂的模組

  • terraform-google-modules/project-factory —— 一次呼叫就完成建立 google_project、連結 billing、啟用 API、加入 Shared VPC、建立預設 service account、設定預算告警。
  • terraform-google-modules/iam —— 在 org / folder / project / bucket / service-account 各層級管理 IAM 綁定,且採用安全的 additive 語意(避開 iam_binding 的 authoritative 陷阱)。
  • terraform-google-modules/network —— 含 Shared VPC、subnet、GKE secondary range、Cloud NAT、firewall rule。
  • terraform-google-modules/kubernetes-engine —— 預設安全的 GKE cluster(Workload Identity、Shielded Nodes、private cluster、release channel)。
  • terraform-google-modules/log-export —— 集中 log sink 到 logging 專案,支援 BigQuery / Pub/Sub / GCS 目的地。

組合範例

module "host_project" {
  source  = "terraform-google-modules/project-factory/google"
  version = "~> 14.0"
  name              = "vpc-host-prod"
  org_id            = var.org_id
  billing_account   = var.billing
  shared_vpc_host   = true
}

module "service_project_app1" {
  source  = "terraform-google-modules/project-factory/google"
  version = "~> 14.0"
  name              = "app1-prod"
  shared_vpc        = module.host_project.project_id
  shared_vpc_subnets = ["projects/${module.host_project.project_id}/regions/us-central1/subnetworks/app1-prod"]
}

CFT 與 Cloud Foundation Fabric(Google Cloud 主導的另一個藍圖 repo)方向接近但不相同:CFT 偏向細粒度的積木模組;Fabric 則直接提供完整的參考架構。


模組組合 (Module Composition) 模式

光是現成的 CFT 模組還不夠;架構師必須懂得組合模組,把爆炸半徑壓小、把程式碼維持 DRY。

1. Root → Stack → Module

  • Root:每個環境一個目錄(envs/prodenvs/staging)。放 backend 設定與 provider 區塊。
  • Stack:邏輯分組,例如 networkdata-platformgke-runtime。每個 stack 有自己的 state 檔案(不同 GCS prefix)。
  • Module:可重用抽象層,定義 input 變數與 output。放在 modules/ 目錄,或放獨立 Git repo 加 semver tag。

2. 薄包裝模組 (Thin wrapper)

把 CFT 模組包在自己組織內的薄薄一層 wrapper,注入組織預設值(label、log sink、必要的防火牆規則)。使用者呼叫 wrapper、而不是直接呼叫 CFT,這樣升級 CFT 版本可以集中處理。

3. 跨 stack 資料共享

避免用 terraform_remote_state data source 把 stack 緊密耦合。優先採用:

  • google_compute_network data source 用名稱查詢 —— 鬆耦合。
  • Output 發佈到 Secret Manager 或 GCS 上的設定物件 —— 消費端 stack 在 apply 時讀取。

4. for_each 優先於 count

從 list 中移除中間元素時,count 會造成破壞性的重排。for_each 用 map key 索引資源,移除某個 entry 只會 destroy 那一個。GCP 集合(例如 project IAM member)一律優先 for_each

多團隊的 monorepo,建議用 AtlantisHCP Terraformworkspace-per-stack 模式運作,並要求 PR 必須由 CODEOWNERS 名單上的 reviewer 核准才能 apply。如此可以在 PR 留言看到 terraform plan 輸出,又不用把 state bucket 憑證發給每位工程師。


匯入既有 GCP 資源 (terraform import)

ClickOps 在所難免。接手手刻環境時,terraform import 可以把這些資源納入管理而不重建。

基本流程

  1. 在 HCL 撰寫 resource 區塊,引數比照現存資源(可以用 gcloud ... describe 讀取現況)。
  2. 執行 terraform import <address> <gcp-id>。例如:
terraform import google_compute_instance.legacy \
  projects/my-proj/zones/us-central1-a/instances/legacy-vm
  1. 執行 terraform plan。如果計畫顯示有變更,代表 HCL 與現實不一致;修 HCL 直到 plan 顯示「no changes」為止。
  2. Commit。

import 區塊 (Terraform 1.5+)

較新的宣告式寫法,讓匯入動作可以在 PR 上被審查:

import {
  to = google_storage_bucket.legacy_data
  id = "legacy-data-bucket"
}

搭配 terraform plan -generate-config-out=generated.tf 可以自動生成 HCL 骨架 —— 在匯入幾十條手動管理的 google_project_iam_member 時非常實用。

必背的資源 ID 格式

資源 Import ID
google_compute_instance projects/{project}/zones/{zone}/instances/{name}
google_storage_bucket {bucket-name}
google_project {project-id}
google_project_iam_member "{project} {role} {member}"(以空白分隔)
google_sql_database_instance projects/{project}/instances/{name}

批次匯入工具

  • terraformer(Google Cloud 開源)—— 從現存 GCP state 反向產生 HCL。
  • gcloud beta resource-config bulk-export —— 為專案、folder 或 organisation 匯出 Terraform 相容 HCL。

HCP Terraform (Terraform Cloud) 與 GCP

當團隊規模超過約 5 位工程師,從筆電或單一 CI runner 跑 terraform apply 就會撐不住。HCP Terraform(前身為 Terraform Cloud)提供託管的 state、執行管線、policy-as-code(Sentinel / OPA)、與私有模組登錄。

整合輪廓

  • 每一組 stack-環境對應一個 HCP Terraform workspace(例如 network-proddata-platform-staging)。
  • VCS-driven runs:HCP Terraform 監聽 Git repo;開 PR 觸發 speculative plan、merge 觸發 apply
  • 遠端 state 放在 HCP —— 不再需要 GCS backend bucket,但很多團隊仍會留 GCS 做災難復原匯出。
  • Run task 可以呼叫外部系統(Wiz、Snyk、Bridgecrew)在 apply 前做政策檢查。

對 GCP 的驗證選項

選項 適用情境 缺點
長效 service account JSON key 存成敏感變數 快速 PoC 金鑰輪替負擔;金鑰外洩風險
Workload Identity Federation (WIF) —— 用 HCP Terraform OIDC token 換短效 GCP 憑證 生產環境 設定稍多;強烈建議
在你的 VPC 內部署 tfc-agent 氣隙或受 VPC-SC 保護的專案 你要自行管理 agent VM

Sentinel / OPA 政策範例

  • 禁止任何 uniform_bucket_level_access = falsegoogle_storage_bucket
  • 所有 google_compute_instance 必須帶 cost-center label。
  • 禁止 google_project_iam_binding(authoritative),改用 google_project_iam_member

PCA 考試提示:題目若提到「SaaS 託管的 Terraform 執行、policy-as-code、私有模組登錄」,答案是 HCP Terraform (Terraform Cloud)。若再加上「不能儲存長效 service account 金鑰」,請搭配 Workload Identity Federation


Workload Identity Federation (HCP Terraform → GCP)

WIF 讓 HCP Terraform 用自己的 OIDC token 去冒充 GCP service account —— 不必再把 JSON key 塞進 HCP Terraform 的變數庫。

GCP 端一次性設定

resource "google_iam_workload_identity_pool" "tfc" {
  workload_identity_pool_id = "hcp-terraform-pool"
}

resource "google_iam_workload_identity_pool_provider" "tfc" {
  workload_identity_pool_id          = google_iam_workload_identity_pool.tfc.workload_identity_pool_id
  workload_identity_pool_provider_id = "hcp-terraform-provider"
  oidc {
    issuer_uri = "https://app.terraform.io"
  }
  attribute_mapping = {
    "google.subject"                        = "assertion.sub"
    "attribute.terraform_organization_name" = "assertion.terraform_organization_name"
    "attribute.terraform_workspace_name"    = "assertion.terraform_workspace_name"
    "attribute.terraform_run_phase"         = "assertion.terraform_run_phase"
  }
  attribute_condition = "assertion.terraform_organization_name == \"acme-co\""
}

resource "google_service_account_iam_member" "tfc_impersonate" {
  service_account_id = google_service_account.tf_runner.name
  role               = "roles/iam.workloadIdentityUser"
  member             = "principalSet://iam.googleapis.com/projects/${var.project_number}/locations/global/workloadIdentityPools/hcp-terraform-pool/attribute.terraform_workspace_name/network-prod"
}

HCP Terraform workspace 環境變數

在 workspace 上設定下列環境變數:

TFC_GCP_PROVIDER_AUTH       = true
TFC_GCP_RUN_SERVICE_ACCOUNT_EMAIL = [email protected]
TFC_GCP_WORKLOAD_POOL_ID    = hcp-terraform-pool
TFC_GCP_WORKLOAD_PROVIDER_ID = hcp-terraform-provider
TFC_GCP_PROJECT_NUMBER      = 123456789012

HCP Terraform 的執行階段會自動呼叫 sts.googleapis.com,把自己的 OIDC token 交換成短效(≤1 小時)且綁定該 service account 的 access token。

為什麼這很重要

  • HCP 端不再有長效 secret —— 滿足 SOC 2 / ISO 27001 控制要求。
  • Workspace 層級的最小權限 —— attribute_conditionprincipalSet URI 可以限定哪個 workspace 才能冒充哪個 service account。
  • 執行階段感知政策 —— 用 attribute.terraform_run_phaseapply 階段綁到比 plan 階段更高權限的 SA。

常見問題 — Terraform 與 Google Provider

Q1. 我該如何驗證 Terraform 到 GCP 的身分?

最佳方法是使用應用程式預設憑證 (Application Default Credentials, ADC)。在你的機器上執行 gcloud auth application-default login,或者讓 Terraform 使用它正在執行的 VM/CI-CD 執行器的 Service Account。

Q2. 什麼是 terraform import

使用此功能將現有的 GCP 資源(在控制台中手動建立的)納入 Terraform 管理。你提供 GCP 資源 ID,Terraform 會為其建立狀態條目。

Q3. 我可以使用 Terraform 管理 IAM 嗎?

可以。強烈建議透過 Terraform 管理 IAM,以確保權限是可稽核的,並遵循「最小權限」原則。

Q4. google_project_iam_membergoogle_project_iam_binding 之間有什麼區別?

  • Member: 將單個使用者/Service Account 新增到角色中。使用起來很安全。
  • Binding: 管理角色的整個使用者列表。要小心——它會移除程式碼中未定義的任何人!

Q5. 什麼是 "Google Cloud Foundations" Fabric/Blueprint?

Google 提供預製的 Terraform 藍圖(如 "Cloud Foundation Fabric"),這些藍圖實作了 Landing Zones、網路和安全性的最佳實踐。使用這些藍圖可以快速啟動一個新組織。


最後的架構師小撇步

在 PCA 考試中,如果題目提到**「基礎設施一致性」「可稽核的更改」「管理複雜環境」,答案通常涉及 Terraform。重點在於狀態管理** (具有版本控制的 GCS 後端) 和模組化。始終優先選擇聲明式方法,而不是命令式腳本。

官方資料來源

更多 PCA 主題