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

資源標記與標籤 (Tagging and Labeling)

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

了解如何在 Google Cloud 中使用標籤 (Labels) 和標記 (Tags) 進行成本分配、治理和網路安全編排。

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

資源元資料 (Resource Metadata) 簡介

在大規模的雲端環境中,可視化和控制至關重要。Google Cloud 提供了兩種主要機制來組織和識別資源:Labels (標籤)Tags (標記)。雖然它們聽起來很相似,但用途卻大不相同。專業雲端架構師 (Professional Cloud Architect) 必須設計一致的元資料分類體系 (Taxonomy),以支援帳單、自動化、安全性和合規性。

白話文解釋 Labels and Tags

比喻 1 — 便利貼 vs. 識別證

想像 Label 是你貼在筆電上的便利貼。上面寫著「行銷部財產」或「專案 X 使用」。它非常適合用來盤點庫存和了解誰該付帳。然而,Tag 就像是識別證 (Security Badge)。它不只是描述這個人,實際上還授予了他們進入建築物中某些門(防火牆規則)的權限。

比喻 2 — 超市庫存

Labels 就像超市裡的價格標籤和部門標牌(農產品、乳製品)。它們幫助經理了解哪個部門賺的錢最多。Tags 則像條碼,自動化系統利用條碼來決定某個物品是否被允許通過「快速通道」(網路安全政策)。

比喻 3 — 圖書館系統

Labels 是書脊上的主題類別(歷史、科學),用於組織書架。Tags 則是 RFID 晶片,如果你在未借閱的情況下試圖將書帶走,它就會觸發警報(政策執行)。

附加在資源上的鍵值對 (Key-value pairs),用於組織資源和成本分配。它們在帳單導出中是可見的。

具有命名空間的鍵和值,提供了一種條件式允許或拒絕政策的方法,並在網路安全中被大量使用。


Labels vs. Tags:主要差異

功能 Labels Tags
主要案例 帳單、組織、庫存 IAM 政策、網路防火牆、安全性
可視化 帳單導出、控制台、SDK Resource Manager、IAM、防火牆
範圍 資源層級 組織/專案層級 (具命名空間)
繼承性 是 (具階層性)
格式 key: value (小寫,特定字元) tagKeys/tagValues (具命名空間)

設計分類體系 (Taxonomy)

成功的標記和標籤策略需要一致的分類體系 (Taxonomy)。常見類別包括:

  • 所有權 (Ownership): owner: marketingteam: data-eng
  • 環境 (Environment): env: prodenv: sandbox
  • 成本中心 (Cost Center): cost-center: 12345
  • 應用程式 (Application): app: checkout-service
  • 合規性 (Compliance): compliance: hipaa

大規模執行政策

你不能依賴手動輸入元資料。

  1. Terraform: 在 IaC 模組中定義 Labels 和 Tags。在 Google Provider 中使用 default_labels 將全域標籤套用於所有資源。
  2. 組織政策 (Organization Policy): 使用「必要標籤 (Required labels)」約束(在可用之處)來防止建立缺少強制性元資料的資源。
  3. Cloud Asset Inventory: 定期查詢你的資源庫,找出「孤兒」資源或那些標籤不合規的資源。
::promoted

架構師洞察: 在 PCA 考試中,請記住 Tags(最近推出作為 Network Tags 的繼任者)現在是跨專案管理防火牆政策的首選方式,因為它們受 IAM 管理,並可以沿著資源階層繼承。 ::


Resource Manager Tags:TagKey 與 TagValue 架構

Resource Manager 的 Tags 是一級資源 (first-class resource),存活於 tagKeys/{numeric_id}tagValues/{numeric_id} 命名空間之下,並掛在被建立時所屬的 Organization、Folder 或 Project 節點上。每個 TagKey 在其父節點下是唯一的(例如 123456789012/environment),每個 TagValue 代表一個被允許的值(例如 productionstaging)。資源與 tag 的綁定透過 TagBinding 資源完成,後者以完整資源名稱指向目標(//compute.googleapis.com/projects/p/zones/z/instances/i)。

生命週期與 IAM 分離

  • 建立 tag keys/values 需要在父節點(Org 或 Folder)擁有 roles/resourcemanager.tagAdmin
  • 將既有 tag 綁定到資源上,則需要對該 tag value 擁有 roles/resourcemanager.tagUser,並對目標資源也擁有 tagUser。這種權限切分讓中央平台團隊負責維護分類體系,而應用團隊可以自助綁定。
  • Tag bindings 會沿著資源階層向下繼承。掛在 Folder 上的 tag 會套用到底下每一個 Project(以及大多數子資源),除非被覆寫。

gcloud 操作流程

gcloud resource-manager tags keys create environment \
  --parent=organizations/123456789012
gcloud resource-manager tags values create production \
  --parent=123456789012/environment
gcloud resource-manager tags bindings create \
  --tag-value=123456789012/environment/production \
  --parent=//cloudresourcemanager.googleapis.com/projects/my-prod-proj

與 labels 不同,你無法透過底層資源的 gcloud ... update 批次修改 tag bindings — tags 是由自己獨立的 API 介面管理。這正是讓它們能安全用於 IAM Conditions 的關鍵:政策可以信任這個 tag 是由具備明確 tagUser 權限的主體所設定,而非任何擁有工作負載編輯權限的人。


由 Tags 驅動的 IAM Conditions

當 Tags 與 IAM Conditions 結合時威力大增。你可以只在目標資源帶有特定 tagValue 時才授予角色,藉此打造屬性式存取控制 (ABAC),而不需要大量增生服務帳號或專案。

範例:只能讀取 production buckets

bindings:
- role: roles/storage.objectViewer
  members:
  - group:[email protected]
  condition:
    title: only-prod-buckets
    expression: |
      resource.matchTag('123456789012/environment', 'production')

resource.matchTag() 這個 CEL 函式會評估繼承下來的 tag bindings,所以 Folder 層級設定的 tag,其下每一個 bucket 都會生效。如果你想釘住一個能在改名後仍然存在的數字 tag id,可以搭配 resource.matchTagId()

IAM Conditions 對 tags 的判斷是在請求發生時即時進行,所以一旦移除 tag binding,存取權的移除可說是立即生效(仍需扣除幾分鐘的憑證快取 TTL)。這讓 tags 成為時限性存取的絕佳「kill switch」 — 比跨數百個專案輪換 IAM bindings 快得多。

GCP 上常見的 ABAC 模式

  • 環境隔離: env=prod → 禁止 CI 服務帳號執行 storage.objects.delete
  • 資料分級: data-class=restricted → 要求主體必須是特權群組,且需從 VPC-SC perimeter 內部存取。
  • 成本回收: cost-center=12345 → 只有該成本中心的成員可以開新執行個體。

Labels 完全做不到這些事。它們不在 IAM Conditions 暴露給 resource CEL 物件的範圍裡。


帳單導出與基於 Labels 的成本分配

GCP 帳單透過標準帳單導出寫入 BigQuery。其 schema 包含一個重複欄位 labels,型別為 STRUCT<key STRING, value STRING>;另外還有一個 system_labels 欄位由 GCP 自動為 GKE clusters、Cloud SQL instances、Compute Engine VMs 等資源填入。

範例:每個應用程式每月成本

SELECT
  (SELECT value FROM UNNEST(labels) WHERE key = 'app') AS app,
  FORMAT_DATE('%Y-%m', usage_start_time) AS month,
  ROUND(SUM(cost), 2) AS cost_usd
FROM `billing.gcp_billing_export_v1_0123ABC`
WHERE _PARTITIONTIME >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY)
GROUP BY app, month
ORDER BY month DESC, cost_usd DESC;

注意事項

  • Labels 是在用量發生當下被記錄的 — 今天替 VM 重新打 label 不會回溯改寫昨天的帳單列。請在建立資源時就把分類體系搞對。
  • labels 陣列只會包含真正套上去的 labels。沒打 label 的資源會以 app IS NULL 出現;把這個量值放上 FinOps 儀表板當作「漏洞 (leakage)」指標。
  • 對於 BigQuery 本身,掛在 query job 上的 labels 也會傳遞到帳單導出,這讓你能把 on-demand 查詢成本歸屬到特定儀表板、dbt model 或臨時分析師。

BigQuery 帳單導出的 labels 欄位是不可變的歷史元資料。如果你的 chargeback 模型事後需要修正某個錯誤的 label,必須在上層疊一張對應表 (old_app -> new_app) 並在報表中 join,而不是試圖去 mutate 導出。這是反覆出現的財務爭議來源,PCA 等級的架構師必須事先預判。


GKE 工作負載 Labels 與 System Labels

在 Google Kubernetes Engine 上,cluster 層級的 GCP labels 與 Kubernetes pod labels 是兩個不同的層次,但會彼此配合,讓你能以 namespace、workload 或團隊為單位分配成本。

兩層 labels

  1. GCP 資源層 labels:掛在 cluster、node pool 以及底層 Compute Engine VMs 上。它們會以 compute SKUs 出現在帳單導出中。
  2. GKE 成本分配 labels — 在 cluster 上以 --enable-cost-allocation 啟用後,GKE 會在帳單列上補上 system_labels,例如 goog-k8s-cluster-namegoog-k8s-cluster-namespacegoog-k8s-workload-name,即使你從未在 GCP 端設定過這些。

實務設定

gcloud container clusters update prod-cluster \
  --enable-cost-allocation \
  --region=asia-east1

啟用後,你就可以把單一 bin-packed node pool 的帳單拆給共享它的多個工作負載:

SELECT
  (SELECT value FROM UNNEST(system_labels) WHERE key = 'goog-k8s-cluster-namespace') AS ns,
  (SELECT value FROM UNNEST(system_labels) WHERE key = 'goog-k8s-workload-name') AS workload,
  SUM(cost) AS cost_usd
FROM `billing.gcp_billing_export_v1_0123ABC`
WHERE service.description = 'Kubernetes Engine'
GROUP BY ns, workload;

至於 Kubernetes 那一側的 label 衛生,可以用 Policy Controller (Gatekeeper) 的 constraint 強制要求 pod 必須帶有 teamapp.kubernetes.io/name 等指定 labels。這能讓 Kubernetes 端與 GCP 端的分類體系維持對齊,讓儀表板數字保持一致。


Cloud Asset Inventory:以元資料進行篩選與稽核

Cloud Asset Inventory (CAI) 是橫跨整個 Organization 中所有資源與 IAM 政策的權威資源庫,並對每一項資產的 labelstagKeys 都建立索引。CAI 是「找出所有缺少 cost-center label 的資源」或「列出所有帶 env=prod 但沒有 data-class tag 的 VM」這類查詢的正確工具。

搜尋與導出

# 找出整個組織內缺少 cost-center label 的資源
gcloud asset search-all-resources \
  --scope=organizations/123456789012 \
  --query="NOT labels.cost-center:*"

# 找出帶有 prod environment tag 的資源
gcloud asset search-all-resources \
  --scope=organizations/123456789012 \
  --query="tagKeys:123456789012/environment AND tagValues:production"

持續合規

  • Feeds: 設定 CAI feed 寫入 Pub/Sub topic,使資源的 labels 或 tag bindings 一旦變更便即時發出事件。把它接到 Cloud Function 以重新打 label 或發出警示。
  • 導出到 BigQuery: 每日匯出完整資產清單,能讓你把資源庫與帳單做 join,找出有花錢但缺少必要元資料的資源。
  • Saved queries: 為每條合規規則(缺少 label、錯誤 tag、孤兒服務帳號)建立 --query=... 片段函式庫,並在排程的 GitHub Actions 中執行。

CAI 是唯一能跨服務一致地查詢元資料的 API — gcloud compute instances list --filter 只能看到 Compute Engine。


Label 與 Tag 的配額與格式限制

Labels 與 tags 都有硬性限制,常讓第一次設計分類體系的團隊吃驚。在 PCA 考試裡熟記這些數字,可以避免你設計出在規模化後悄悄崩潰的策略。

Labels

  • 大多數服務 每個資源最多 64 個 labels
  • Key:1–63 字元,小寫字母、數字、底線或破折號;必須以小寫字母開頭。
  • Value:0–63 字元,字元集相同。
  • 不允許大寫與國際字元 — Owner: Alice 是無效的;改用 owner: alice

Tags

  • 每個 organization 最多 1,000 個 tag keys
  • 每個 tag key 最多 1,000 個 tag values
  • 每個資源最多 50 個 tag bindings(若繼承下來也算進這個上限;請以最新文件為準)。
  • Tag key 短名:1–63 字元;允許大寫、底線、句點、破折號 — 字元集比 labels 寬鬆許多。

常見考題陷阱:考生以為 labels 可以裝下豐富的值,例如電子郵件位址或像 v1.2.3 這樣的版本字串。在 label value 裡 v1.2.3 的句點是無效字元,電子郵件裡的 @ 也是。請改用底線 (v1_2_3),或把這類資訊改放到 annotation 或 description 欄位。Tags 在短名中是允許句點的,但 tag values 一樣有受限的字元集。


一套能撐過稽核的成本分配策略

可被辯護的成本分配模型,建立在一組小而強制的 labels 上,並一致地套用於每一個會產生費用的資源。

最小可行 label 集合

Label key 基數 真值來源
cost-center ~50 個值 財務 ERP
business-unit ~10 個值 人資/組織圖
app ~500 個值 服務目錄 / CMDB
env 4–5 個值 部署管線
data-class 3–4 個值 資料治理團隊

數字如何流動

  1. 每個資源都由 Terraform 在建立時依模組預設打上 label。
  2. 帳單導出每小時串流到 BigQuery。
  3. 排程查詢把 costcost-center 拆分,並與財務 ERP 對表取得 chargeback 代碼。
  4. Looker Studio(或 Looker)依事業單位呈現 chargeback 儀表板。
  5. 未打 label 的花費獨立成「漏洞 (leakage)」項目,目標控制在總花費的 < 2%。

為何不直接用專案?

專案本身已經會隔離帳單,但你的應用程式與成本中心通常遠多於可以舒適建模為專案的數量。Labels 讓你能在專案內部切片(同一個專案多個 microservices、多個團隊共用一個 GKE cluster),同時讓專案維持為 IAM 與配額的單位。兩者是互補關係。


Label 衛生政策:讓必要欄位真的被執行

Label 策略的好壞,取決於必要欄位的執行強度。你應該疊加多層執行手段,而不是只挑一種。

多層執行

  1. IaC 預設值: 在 Terraform 的 google provider 上設定 default_labels,讓 Terraform 建立的每個資源都繼承 cost-centerenvapp。把這些變數設為必填(type = string,不給 default)。
  2. 模組驗證: 在共用 Terraform 模組裡用 validation 區塊,在 plan 階段就拒絕空 label。
  3. Pre-commit hook:tflint 加自訂規則,若 PR 內任一 google_* 資源缺少必要欄位就讓 PR 失敗。
  4. 組織政策 (Organization Policy): 在可用之處,用 gcp.resourceLocations 與 label 相關約束從一開始就防止未打 label 的資源被建立。
  5. CAI feed + Cloud Function: 作為非 Terraform 路徑(主控台手動點選、第三方 agent)的最後防線;由 Pub/Sub 觸發的函式把資源加入或移出「不合規」的 labels 群組並通知擁有者。
  6. 排程稽核: BigQuery 排程查詢把帳單導出與必要欄位清單 join,每週在 Slack 發出 label 覆蓋率最差的團隊報告。

PCA 考試請記住經典執行金字塔:預防 (Org Policy) → 在 IaC 內強制 (Terraform 預設值 + 模組驗證) → 偵測 (CAI feeds + BigQuery 排程查詢) → 補救 (Cloud Function 或 Workflows)。多層防護永遠勝過任何單一控制。


用 Cloud Functions 與 CAI Feeds 自動補救

你可以用事件驅動的補救管線把 label 漂移問題收口。無論缺的是哪一個必要 label,模式都一樣。

參考架構

  1. 在 Organization 層級建立 Cloud Asset Inventory feed,按你關心的 asset types (compute.googleapis.com/Instancestorage.googleapis.com/Bucketbigquery.googleapis.com/Dataset) 過濾,並把每次變更發布到 Pub/Sub topic。
  2. Cloud Function (2nd gen) 訂閱該 topic。對每則訊息:
    • 解析 asset payload。
    • 檢查必要欄位 (cost-centerenvapp) 是否存在且非空。
    • 若缺漏且父專案帶有 default-cost-center label,把該值複製到子資源上。
    • 否則透過 Slack/電子郵件通知擁有團隊,並把資源打上 compliance=non-compliant tag。
  3. Dead-letter topic 收容函式無法處理的訊息;由 on-call 工程師每週清空。

程式骨架 (Python)

def remediate(event, context):
    asset = json.loads(base64.b64decode(event["data"]))["asset"]
    labels = asset["resource"]["data"].get("labels", {})
    missing = [k for k in ("cost-center", "env", "app") if k not in labels]
    if not missing:
        return
    project = asset["ancestors"][0]
    default = lookup_project_default(project)
    if default:
        apply_labels(asset["name"], default)
    else:
        notify_owner(asset, missing)

運維要點

  • 函式必須是 idempotent:套上 label 後它會再看到該 asset,所以寫入前要先檢查目前狀態。
  • 流量控制:吵雜資源(例如 Dataflow job 大量產生暫存資源)可能淹沒函式。請使用 Pub/Sub flow control,並對函式設定 max-instance 上限。
  • 把每一次 label 變更連同函式的主體一起記錄到稽核 log。

BigQuery 視圖:統一的 Label 目錄

一張 BigQuery 視圖暴露「每個資源及其 labels,並與帳單與資源庫 join 起來」,會成為 FinOps、安全與平台團隊的主力工作面。建一次,到處查。

把那一段「按 key 取出 label」的 unnest 子查詢包成 SQL UDF,例如 fn.label(labels, 'app')。每位分析師之後只要寫 fn.label(labels, 'team') 而不必到處複製貼上子查詢 — 這會大幅提升 FinOps 報表之間的一致性。

視圖設計

CREATE OR REPLACE VIEW finops.resource_catalog AS
SELECT
  r.name AS resource_name,
  r.asset_type,
  r.ancestors[OFFSET(0)] AS project,
  r.labels,
  (SELECT value FROM UNNEST(r.labels) WHERE key = 'cost-center') AS cost_center,
  (SELECT value FROM UNNEST(r.labels) WHERE key = 'env')        AS env,
  (SELECT value FROM UNNEST(r.labels) WHERE key = 'app')        AS app,
  b.last_30d_cost_usd
FROM `cai_export.assets` r
LEFT JOIN (
  SELECT
    project.id AS project,
    (SELECT value FROM UNNEST(labels) WHERE key = 'app') AS app,
    ROUND(SUM(cost), 2) AS last_30d_cost_usd
  FROM `billing.gcp_billing_export_v1_0123ABC`
  WHERE _PARTITIONTIME >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
  GROUP BY project, app
) b
ON r.ancestors[OFFSET(0)] = CONCAT('projects/', b.project)
  AND (SELECT value FROM UNNEST(r.labels) WHERE key = 'app') = b.app;

為何重要

  • 一個 join 取代散落各團隊的十個臨時查詢。
  • 新增欄位(例如 data_class)不會破壞下游儀表板,因為底層 labels 陣列仍保留。
  • 視圖層級的 row-level security(使用 BigQuery row access policies)可以把每個事業單位限縮到自己 cost_center 的範圍內。
  • 同一個視圖被 Looker Studio(成本儀表板)、Looker(chargeback 報表)以及臨時分析共用,確保所有人看到的數字一致。

這個模式 — CAI 導出 + 帳單導出 + 視圖 — 就是 GCP 上資源治理的標準「單一玻璃面板」,非常值得在 PCA 考試前牢記。


常見問題 — 資源元資料

Q1. 我可以使用 Labels 進行安全控管嗎?

不行。Labels 用於組織和帳單。它們沒有與 IAM 鏈接的執行機制。請使用 TagsIAM 條件 (IAM Conditions) 來處理安全性相關的邏輯。

Q2. Labels 會顯示在 BigQuery 帳單導出中嗎?

會。這是它們的強大之處。你可以執行 SQL 查詢,確切了解 app: legacy-portal 每個月花費你多少錢。

Q3. Labels 的限制是多少?

大多數 GCP 資源允許每個資源最多有 64 個 Labels。

Q4. 什麼是 "Network Tags"?

Network Tags 是專門針對 Compute Engine VM 和 VPC 防火牆的舊版本標記。雖然仍被廣泛使用,但較新的 Resource Manager Tags 功能更強大,因為它們可以跨不同的資源類型和資料夾運作。

Q5. 我該如何更新 1000 台 VM 上的 Labels?

使用 gcloud compute instances add-labels 命令配合腳本,或者最好是更新你的 Terraform 程式碼並執行 plan/apply,使環境達到理想狀態。

官方資料來源

更多 PCA 主題