環境管理簡介
有效的環境管理是專業雲端架構師 (Professional Cloud Architect) 實現卓越營運的基石。在 Google Cloud 上,必須對環境(開發 Dev、測試 Test、暫存 Staging、生產 Prod)進行架構設計,以確保隔離性、可重現性和安全性。目標是透過保持高度的環境一致性 (Environment Parity),同時控制成本並保護敏感的生產資料,來盡量減少「在我的電腦上可以執行」的問題。
白話文解釋 Environment Management
比喻 1 — 米其林星級廚房
想像開發 (Development) 是主廚的家庭廚房,在那裡他們嘗試新的口味。測試 (Testing) 是私人品酒室,在那裡他們完善菜餚。暫存 (Staging) 是試營運 (Soft opening),在那裡一切都與真正的餐廳完全相同,但僅限受邀嘉賓。生產 (Production) 則是週六晚上的主餐廳。你絕不會在主餐廳第一次嘗試全新的食譜!
比喻 2 — 電影劇組
開發是排練室。測試是CGI 與混音工作室。暫存是為製作人準備的私人放映會。生產則是全球戲院上映。如果你在排練期間發現鏡頭中出現了收音麥克風,那沒關係;但如果它出現在戲院上映版中,那就是一場災難。
比喻 3 — 試驗工廠
在化學工程中,你不會立即建造一座巨大的工廠。你會先建造實驗室規模 (Dev),然後建造一個試驗工廠 (Pilot Plant) (Staging),看看製程是否可以按比例放大。只有當試驗工廠運作良好時,你才會建造全規模煉油廠 (Production)。
盡可能保持開發、暫存和生產環境相似的實踐,以確保程式碼在整個交付流水線中的行為保持一致。
設計環境的資源階層
在 GCP 上隔離環境最穩健的方法是在資料夾 (Folder) 結構內使用專案 (Project) 層級的隔離。
- 專案隔離: 每個環境都應該有自己的專案(例如:
app-dev、app-staging、app-prod)。這提供了最強的安全邊界。 - 共享 VPC (Shared VPC): 使用共享 VPC 來集中管理網路,同時允許各個環境專案使用專屬於它們的子網路。
- 資料夾層級政策: 在資料夾層級(例如「開發」資料夾)套用組織政策 (Organization Policies),以執行不同的規則(例如在開發環境允許外部 IP,但在生產環境不允許)。
環境發佈工作流程
將程式碼和基礎設施從一個環境移動到下一個環境應該透過 CI/CD 自動化完成。
- 製品發佈 (Artifact Promotion): 絕不要為不同的環境重新構建你的容器或二進位檔案。在開發/構建階段構建一次,存儲在 Artifact Registry 中,然後將同一個映像檔部署到暫存環境,接著再部署到生產環境。
- 設定即程式碼 (Configuration as Code): 使用特定環境的設定檔或 Secret Manager,將特定環境的數值(如資料庫連線字串)注入到不可變的製品中。
架構師洞察: 在 PCA 考試中,務必主張使用專案層級的隔離,而不是僅使用標籤或為不同環境共享專案。這可以確保開發環境中的錯誤配置(如寬鬆的防火牆規則)不會影響生產環境。 ::
管理測試資料與沙盒 (Sandboxes)
- 資料遮罩 (Data Masking): 當使用生產資料進行測試時,務必使用 Sensitive Data Protection (DLP) 來遮罩個人識別資訊 (PII)。
- 合成資料 (Synthetic Data): 優先考慮生成模擬生產規模和多樣性的合成資料,以避免安全風險。
- 沙盒 (Sandboxes): 為開發人員提供具有嚴格預算警報和自動清理腳本的「遊樂場」專案,以鼓勵創新而不會導致成本失控。
Dev/Staging/Prod 專案分離模式
PCA 考試始終偏好將每個環境對應到獨立 GCP 專案、並掛在以 Organization 節點為根的資料夾結構之下。標準階層為 Organization → Environments 資料夾 → {dev、nonprod、prod} 子資料夾 → 工作負載專案。每個環境資料夾擁有自己的計費子帳戶、自己在 Cloud Identity 的緊急破窗群組,以及自己一套的 Organization Policy 綁定。
為何採用專案層級(而非標籤層級)分離
- 配額以專案為單位。 dev 中失控的 Cloud Run 版本不會耗盡 prod 的 Compute Engine CPU 配額,前提是各自有獨立專案。
- IAM 影響範圍縮小。 在 dev 專案授予
roles/owner,永遠不會洩漏到 prod 的 BigQuery 或 Cloud SQL 資料。 - 記錄與稽核軌跡保持乾淨。 Cloud Audit Logs 以專案為單位彙整,因此
app-prod的安全審查不會被開發者實驗污染。
應套用的資料夾層級護欄
| 政策 | dev 資料夾 | prod 資料夾 |
|---|---|---|
compute.vmExternalIpAccess |
允許(子集) | 拒絕 |
iam.allowedPolicyMemberDomains |
允許外包 | 限公司網域 |
storage.uniformBucketLevelAccess |
強制 | 強制 |
compute.requireOsLogin |
強制 | 強制 |
sql.restrictPublicIp |
允許 | 強制 |
使用 Terraform 配合 google_folder 資源與 google_org_policy_policy 綁定,讓護欄納入版本控管。再搭配 Cloud Logging 中的資料夾範圍 sink,將 prod 稽核事件路由到獨立的 BigQuery sink 以符合合規保存期(通常 7 年),而 dev 記錄可在 30 天後到期以控制成本。
若 PCA 題目提到「開發者誤刪資料庫」或「非生產 IAM 被授予到生產環境」,正確答案幾乎都是在環境資料夾下建立獨立專案,並搭配 Organization Policy 護欄 — 絕不是在共享專案內以標籤、tag 或 namespace 區隔。
以 Shared VPC 進行環境網路隔離
常見架構是每個環境一個主機專案 (host project)(例如 net-host-prod、net-host-nonprod),並將工作負載專案以服務專案 (service project) 形式掛上。這讓網路團隊集中管理網路,同時讓應用團隊保留對運算與資料服務的 IAM。
參考佈局
net-host-prod(主機專案)擁有vpc-prodVPC,內含子網路subnet-prod-asia-east1、subnet-prod-us-central1。app-prod-*服務專案透過僅在特定子網路上授予roles/compute.networkUser來消費子網路 — 切勿授予整個 VPC。net-host-nonprod託管vpc-nonprodVPC;prod 與 nonprod 之間的 VPC Peering 故意不設定,這樣 nonprod 工作負載即使誤設也無法觸及 prod 資料層。
防火牆政策階層
- 資料夾層級的階層式防火牆政策 (Hierarchical Firewall Policies) 拒絕來自
0.0.0.0/0的所有流量,僅允許全域 Load Balancer 後方的tcp:443入向。 - VPC 層級的網路防火牆政策僅允許在標記服務帳戶之間的東西向流量(例如
[email protected]到[email protected])。 - 跨環境流量必須走文件化的出向路徑 — 通常透過 Cloud NAT 加上 Private Service Connect 端點,永不在 dev 與 prod 之間直接 VPC peering。
為何不採用單一 Shared VPC 涵蓋所有環境
單一 VPC 表示單一 CIDR 規劃、單一防火牆面、單一路由集合。dev 中一條誤設的路由就能使 prod 流量黑洞化。每個環境獨立 Shared VPC 多花 5 分鐘 Terraform,但移除整類跨環境事故。
各環境的 IAM 範圍限縮
身分擴散是環境洩漏的最常見來源。PCA 考試的標準答案模式:群組綁定在最低必要範圍、服務帳戶逐環境隔離、人類不持有任何常駐 prod 存取權限。
群組 + 範圍矩陣
gcp-app-developers@corp→ 僅綁定到 dev 資料夾的roles/editor。gcp-app-sre@corp→ 綁定到 prod 資料夾的roles/run.developer+roles/logging.viewer,需要roles/run.admin時透過 Privileged Access Manager (PAM) 走破窗流程。gcp-app-deployer@corp(僅 CI/CD,無人類)→ 在每個環境綁定部署專屬角色。
服務帳戶衛生
- 每個環境有自己的服務帳戶 namespace:
[email protected]與[email protected]是不同實體。 - 在 prod 資料夾上透過
iam.disableServiceAccountKeyCreation組織政策停用服務帳戶金鑰建立。 - CI/CD 改用 Workload Identity Federation 取代長期 JSON 金鑰 — GitHub Actions 或 GitLab CI 透過 OIDC 假冒部署 SA。
- 跨專案 SA 假冒必須顯式:dev SA 無法假冒 prod SA,因為
roles/iam.serviceAccountTokenCreator從未跨越環境邊界授予。
PCA 稽核清單
- 每季執行
gcloud asset search-all-iam-policies --scope=folders/PROD_FOLDER_ID --query="policy:user:"找出應該以群組綁定卻直接綁到個人使用者的情況。 - 啟用 IAM Recommender 的 Policy Analyzer 找出未使用的權限,先在 dev 採納建議驗證模式,再套用到 prod。
將 prod 服務帳戶的 roles/iam.serviceAccountUser 授予 dev-developers 群組是無聲的 prod 失守 — 開發者可以用該 prod SA 啟動 Compute Engine VM 並讀取 prod 資料。永遠將 roles/iam.serviceAccountUser 限縮在 SA 被允許掛載的特定專案。
沙盒資料夾用於實驗
沙盒是防止影子 IT 的安全閥。PCA 推薦的模式是 Organization → Sandbox 資料夾,與主要 Environments 資料夾隔離,並施加嚴格護欄。
沙盒資料夾設定
- 自動清理: 由 Cloud Scheduler 觸發的排程 Cloud Function 執行
gcloud projects list --filter="parent.id=SANDBOX_FOLDER AND createTime<-P30D"並刪除任何超過 30 天且未標記keep=true的專案。 - 預算上限: 每個沙盒專案由 Project Factory Terraform 模組建立,自動掛上每月 50 美元的 Cloud Billing 預算,並在達 100% 時透過 Pub/Sub 觸發停用計費。
- 不含 prod 資料: 組織政策
gcp.restrictServiceUsage在 Sandbox 資料夾拒絕bigquerydatatransfer.googleapis.com與datastream.googleapis.com,防止從 prod 意外建立管線。 - 允許外部 IP,但記錄: 與 prod 不同,沙盒可有外部 IP 以利快速展示,但 VPC Flow Logs 串流到安全 SIEM,讓安全團隊可發現外洩模式。
自助流程
開發者透過 Backstage 或內部入口請求沙盒,後者呼叫 Cloud Build 觸發器。建置執行 project-factory Terraform,將請求者指派為該單一專案的 roles/owner(絕不在資料夾層級),並將專案 ID 貼到 Slack。這把實驗從 dev 環境(會污染共用狀態)移到短暫、有上限的空間。
Terraform Workspaces 對比 Directory-per-Environment
Terraform 提供兩種多環境 IaC 模式,PCA 考試會測試各自的適用時機。
Workspaces(CLI workspaces 或 Terraform Cloud workspaces)
# main.tf - 共用
resource "google_compute_network" "vpc" {
name = "vpc-${terraform.workspace}"
project = var.project_ids[terraform.workspace]
}
- 單一程式碼庫,每個 workspace 一份 state。
- 優點:當環境形狀確實相同時,重複最少。
- 缺點:容易套用到錯誤 workspace —
terraform workspace select prod拼錯一個字就是災難。
Directory-per-environment(PCA 推薦)
infra/
modules/
network/
gke-cluster/
envs/
dev/main.tf (以 dev 變數呼叫模組)
staging/main.tf (以 staging 變數呼叫模組)
prod/main.tf (以 prod 變數呼叫模組,獨立 backend)
- 每個 env 有獨立 backend bucket:
gs://tf-state-prod、gs://tf-state-dev,並以 bucket 層級 IAM 阻止 dev pipeline SA 接觸 prod state。 - 發佈 = 一個 PR 在
envs/staging/main.tf提高模組版本 pin(source = "git::...//modules/gke-cluster?ref=v1.4.2"),再一個 PR 在envs/prod/main.tf。 - 此模式與 Cloud Build 依變更路徑過濾的觸發器吻合:只有
envs/prod/下的變更會觸發 prod plan/apply 管線,並掛人工核准。
對混合團隊,Terraform Cloud workspaces 結合 VCS 兼具兩者優點:Git 中以目錄分環境,workspace 層級加上執行核准與稽核記錄。
各環境專屬的 Secret Manager 配置
機密絕不可跨環境共用 — 洩漏的 dev 機密不該解鎖 prod。GCP 的 Secret Manager 透過每專案機密加上機密層級 IAM 來支援這一點。
命名與專案佈局
- 機密名稱跨環境保持穩定:
db-password、stripe-api-key、oauth-client-secret。 - 每個環境有專屬於它的專案來託管這些機密:
secrets-dev、secrets-staging、secrets-prod。 - 應用讀取
projects/secrets-${ENV}/secrets/db-password/versions/latest— 唯一改變的是部署時注入的專案前綴。
各環境的存取控制
[email protected]僅在projects/secrets-prod取得roles/secretmanager.secretAccessor。roles/secretmanager.admin永不授予人類於 prod 機密專案 — 輪替透過 Cloud Scheduler + Cloud Function 自動呼叫 Secret Manager 與上游供應商 API。- prod 機密啟用 CMEK 加密,金鑰位於獨立
kms-prod專案的 Cloud KMS,因此即使具備 Secret Manager admin 但不具roles/cloudkms.cryptoKeyDecrypter也無法取出明文。
輪替與版本管理
- 透過機密資源上的
rotation欄位設定自動輪替,並觸發 Pub/Sub 主題由 Cloud Function 監聽。 - 舊版本停用(而非銷毀)30 天以支援回滾。
- PCA 提示:當題目描述「dev 記錄中外洩機密、需確保 prod 不受影響」,答案就是利用逐環境的專案分離 — prod 不需輪替,因為 dev 機密原本就沒有 prod 存取權。
透過 Cloud Build 替換變數 (_SECRET_PROJECT=$_ENV-secrets) 在部署時注入環境特定的機密專案 ID。應用程式碼保持環境無感、從 projects/${SECRET_PROJECT}/secrets/... 讀取 — 少一條分支要維護。
Cloud Build 替換變數驅動逐環境管線
以替換變數參數化的單一 cloudbuild.yaml 讓你可以在 dev/staging/prod 之間維護一份管線定義,由觸發器供應各環境特定值。
替換變數驅動的管線
# cloudbuild.yaml
substitutions:
_ENV: dev
_PROJECT_ID: app-dev
_REGION: us-central1
_MIN_INSTANCES: '0'
_CMEK_KEY: ''
steps:
- id: build
name: gcr.io/cloud-builders/docker
args: ['build', '-t', 'us-central1-docker.pkg.dev/$_PROJECT_ID/app/web:$SHORT_SHA', '.']
- id: deploy
name: gcr.io/google.com/cloudsdktool/cloud-sdk
entrypoint: gcloud
args:
- run
- deploy
- web-$_ENV
- --image=us-central1-docker.pkg.dev/$_PROJECT_ID/app/web:$SHORT_SHA
- --region=$_REGION
- --min-instances=$_MIN_INSTANCES
- --project=$_PROJECT_ID
各環境的觸發器設定
- dev 觸發器: 推送到
main即觸發。替換變數:_ENV=dev, _PROJECT_ID=app-dev, _MIN_INSTANCES=0。 - staging 觸發器: 符合
staging-*的 tag 觸發。替換變數:_ENV=staging, _PROJECT_ID=app-staging, _MIN_INSTANCES=1。 - prod 觸發器: 符合
v[0-9]+.[0-9]+.[0-9]+的 tag 觸發。替換變數:_ENV=prod, _PROJECT_ID=app-prod, _MIN_INSTANCES=2, _CMEK_KEY=projects/kms-prod/...。需要人工核准(approval_config.approval_required: true)。
每個 Cloud Build 觸發器以自己的服務帳戶執行。prod 觸發器 SA 僅在 app-prod 取得 roles/run.admin;dev 觸發器 SA 同樣僅在 app-dev 取得。絕不要跨環境共用同一個 builder SA — 那個帳戶會立刻成為整個組織內最高價值的攻擊目標。
建置時對比執行時的替換
只有 image tag、區域、資源名稱應在建置時不同。應用設定(feature flag、log level)應來自執行時來源(Secret Manager、Firestore、以 Cloud Storage 等同 App Config 的機制),使設定變更不必重新部署。從 dev 發佈到 prod 的 image SHA 必須是逐位元組相同。
GKE Config Sync 處理各環境政策
對於跨環境執行 GKE 的組織,Config Sync(Anthos Config Management 的一部分)以 GitOps 提供各叢集的政策與設定交付。
儲存庫結構
config-sync/
base/ (共用 Kustomize base — namespace、network policy)
overlays/
dev/
patches/
deny-internet.yaml (限制較鬆)
resource-quotas.yaml (較小配額)
staging/
prod/
patches/
deny-internet.yaml (拒絕所有出向,僅允許 allowlist)
resource-quotas.yaml (生產規模)
pod-security.yaml (restricted PSS)
每個 GKE 叢集(gke-dev、gke-staging、gke-prod)有自己的 RootSync 資源,指向同一 Git repo 中不同的 overlay 路徑,確保所有叢集追蹤單一事實來源,同時套用各環境合適的限制。
各環境的 Policy Controller (Gatekeeper)
Policy Controller 透過 OPA Gatekeeper 範本強制限制:
- dev: 大多限制為
warn模式,讓開發者看到違規但不阻擋部署。 - staging: 關鍵限制為
deny模式(禁止 privileged container、hostNetwork),對 image registry 限制則為 warn-only。 - prod: 所有限制為
deny模式,包括K8sAllowedRepos將映像限制在*-docker.pkg.dev/PROD_PROJECT/*。
偏移偵測與修復
Config Sync 持續對 Git 調節叢集狀態。若開發者透過 kubectl edit 手動編輯 prod 的 NetworkPolicy,Config Sync 會在數秒內回復,並向 Cloud Monitoring 發出觸發 PagerDuty 警報的指標。這使 prod 在 Git 工作流之外實質上不可變 — 與你希望 IaC 層提供的特性相同,只是套用到 Kubernetes API 層。
透過 Cloud Run 提供短暫的預覽環境
每個 PR 一個預覽環境能大幅改善開發者回饋迴圈。Cloud Run 是 GCP 上的首選服務,因為它有亞秒級冷啟動、可縮容到零的計費,以及每個版本一個 URL。
實作模式
- 在
pull_request觸發的 GitHub Actions workflow 建置容器,標記pr-${PR_NUMBER}-${SHA}並推送到 Artifact Registry。 - Workflow 執行
gcloud run deploy preview-pr-${PR_NUMBER} --image=... --region=us-central1 --no-traffic,為每個 PR 建立新的 Cloud Run 服務。 - Cloud Run 回傳確定的 URL
https://preview-pr-123-xyz-uc.a.run.app,workflow 將其貼為 PR 留言。 - PR 關閉(合併或放棄)時,後續 workflow 執行
gcloud run services delete preview-pr-${PR_NUMBER}。
成本與安全護欄
- 所有預覽服務位於專屬
app-preview專案(非 dev、非 staging)。 --min-instances=0與--max-instances=3將閒置成本維持為零、活躍成本設上限。- 預覽 SA 對獨立 BigQuery 資料集中已淨化的 staging 資料副本具備唯讀存取 — 永不及於生產。
- 啟用 Cloud Run 認證(
--no-allow-unauthenticated),開發者透過gcloud auth print-identity-token或綁定公司網域的 Identity-Aware Proxy 認證。
為何不採用 GKE 預覽
每個 PR 一個 GKE namespace 雖可行,但增加排程延遲(拉映像、排程 Pod)與 namespace 清理成本。Cloud Run 30 秒內提供全新 URL、開發者互動之間可縮容到零,並省去叢集資源管理。GKE 預覽應保留給 Cloud Run 無法承載、具黏滯狀態(資料庫、StatefulSet)的工作負載。
暫存環境的資料匿名化
暫存必須真實鏡像生產,又不能成為合規負債。Sensitive Data Protection (DLP)、Dataflow 與 Cloud KMS 的組合提供可重複的匿名化管線。
管線架構
- 排程 BigQuery 匯出透過 BigQuery Data Transfer Service 以僅具 prod 唯讀的 SA 每晚把 prod 資料表快照到綁定 staging 的 Cloud Storage bucket。
- Dataflow 範本(Google 提供的
Cloud_DLP_GCS_Text_to_BigQuery範本)讀取快照、以DeidentifyConfig呼叫 DLP API,再寫入 staging BigQuery 資料集。 - DLP 設定使用:
- 對電子郵件與電話欄位使用 FFX 的格式保留加密 (FPE),使參考完整性得以保留(相同 prod 電子郵件永遠對應到相同 staging 電子郵件)。
- 對 SSN/國民身分證欄位使用密碼學雜湊,金鑰位於獨立
kms-deid專案的 Cloud KMS。 - 對薪資等數值欄位使用桶化 (Bucketing)(
< 50000、50000-100000、> 100000)以保留統計特性而不暴露精確值。 - 對時間戳記使用日期位移並以每筆記錄一致的位移量,讓時間序列分析仍可運作。
再識別控制
- FPE 使用的 KMS 金鑰包覆在僅去識別化 SA 可使用的 KMS key ring 之下。再識別需顯式 IAM 授予,並觸發 Cloud Audit Log 警報。
- Staging 存取由獨立群組
gcp-app-staging-readers@corp把關,預設不授予產品工程師 — 即使資料已匿名化,最小權限原則仍適用。
發佈前驗證
Staging 資料上線前,Cloud Run job 執行 k-匿名性與 l-多樣性檢查(使用 DLP 的 RiskAnalysisJob),確認匿名化資料集達到組織的隱私門檻(例如 k≥5)。若工作失敗,staging 重整中止並觸發警報 — 防止意外弱化的匿名化進入工程師視線。
PCA 測試資料情境的標準答案:DLP + Dataflow 是 GCP 原生的大規模匿名化方案,搭配需要參考完整性的欄位使用格式保留加密、單向假名化使用密碼學雜湊、統計欄位使用桶化/日期位移。把去識別化的 KMS 金鑰放在獨立專案以強制職責分離。
常見問題 — 環境管理
Q1. 我們如何確保開發環境和生產環境之間的一致性?
使用基礎設施即程式碼 (Terraform)。定義一次基礎設施並使用變數將其部署到多個專案。這可以確保網路、防火牆和服務配置完全相同。
Q2. 開發環境和生產環境應該在同一個 VPC 中嗎?
不應該。為了獲得高度安全性,請將它們放在分開的 VPC 中(可能是在共享 VPC 架構中,它們佔用不同的子網路並由防火牆規則隔離)。
Q3. 我們如何控制開發/測試環境的成本?
使用 Cloud Scheduler 在非工作時間關閉非生產用 VM,使用 Preemptible/Spot VM,並設置積極的 Cloud Billing 預算。
Q4. 暫存環境 (Staging) 的作用是什麼?
暫存環境是用於最終驗證。它應該是生產環境的 1:1 複製品,包括資料量(已遮罩)和流量模式,以便發現效能問題和整合錯誤。
Q5. 我們可以在不同環境中使用相同的 Service Accounts 嗎?
絕對不行。每個環境都必須擁有自己唯一的 Service Accounts,其權限範圍僅限於該環境的資源。