關於 Workload Identity Federation for GKE

本文說明 GKE 的 Workload Identity 聯盟,包括運作方式、啟用後對 GKE 叢集的影響,以及如何在 Identity and Access Management 政策中,將角色授予 Kubernetes 實體。在多數情況下,建議使用 Workload Identity Federation for GKE,協助保護及管理在 GKE 上執行的工作負載如何存取 Google Cloud 服務。

本文適用於安全專家和作業人員,他們負責管理 GKE 上的工作負載,且這些工作負載需要存取其他 Google Cloud服務。如要進一步瞭解 Google Cloud 內容中提及的常見角色和工作範例,請參閱「常見的 GKE 使用者角色和工作」。

術語

本頁面會區分 Kubernetes 服務帳戶和 Identity and Access Management (IAM) 服務帳戶。

Kubernetes 服務帳戶
Kubernetes 資源,可為 GKE Pod 中執行的程序提供身分。
IAM 服務帳戶
Google Cloud 資源,可讓應用程式對Google Cloud API 發出授權呼叫。

什麼是 Workload Identity Federation for GKE?

在 GKE 上執行的應用程式可能需要存取 Google Cloud API,例如 Compute Engine API、BigQuery Storage API 或機器學習 API。

透過 GKE 適用的工作負載身分聯盟,您可以使用 IAM 政策,授予 GKE 叢集中的 Kubernetes 工作負載特定Google Cloud API 的存取權,不必手動設定,也不必使用服務帳戶金鑰檔案等安全性較低的方法。使用 Workload Identity Federation for GKE,即可為叢集內的每個應用程式指派不重複的精細身分與授權。

Workload Identity Federation for GKE 可取代中繼資料隱藏功能。Workload Identity Federation for GKE 也會保護受中繼資料遮蔽功能保護的機密中繼資料。

您可以使用 IAM Workload Identity Federation for GKE,為在 Google Cloud內外環境中執行的工作負載提供身分。您可以使用 IAM Workload Identity Federation,從 AWS、Azure 和自行管理的 Kubernetes 等平台上執行的工作負載,安全地向支援的 Google Cloud API 進行驗證。在 GKE 中,Google Cloud 會為您管理 workload identity pool 和提供者,不需要外部身分提供者。

Workload Identity Federation for GKE 的運作方式

在叢集上啟用 Workload Identity Federation for GKE 時,GKE 會執行下列操作:

  • 為叢集的 Google Cloud專案建立固定的 workload identity pool,格式如下:

    PROJECT_ID.svc.id.goog
    

    workload identity pool 提供命名格式,讓 IAM 能夠理解及信任 Kubernetes 憑證。即使您刪除專案中的所有叢集,GKE 也不會刪除這個 workload identity pool。

  • 在 workload identity pool 中,將 GKE 叢集註冊為身分提供者。

  • 在每個節點上部署 GKE 中繼資料伺服器,攔截工作負載的憑證要求。

為 Google Cloud 資源建立 IAM 允許政策

如要透過 Workload Identity Federation for GKE 提供存取權,請建立 IAM 允許政策,將特定 Google Cloud 資源的存取權授予與應用程式身分對應的主體。舉例來說,您可以將 Cloud Storage bucket 的讀取權限,授予所有使用 database-reader Kubernetes ServiceAccount 的 Pod。

如需支援允許政策的資源清單,請參閱「接受允許政策的資源類型」。

在 IAM 政策中使用條件

您也可以在允許政策中設定條件,限制存取權範圍。條件是一種可擴充的方法,用於指定何時應套用允許政策。舉例來說,您可以使用條件,暫時授予特定 Google Cloud 資源的工作負載存取權,不必手動管理。

如果您是在專案、資料夾或組織層級設定允許政策,而非針對 Secret Manager 密鑰或 Cloud Storage bucket 等特定資源設定,條件也可能很有用。

如要在允許政策中新增條件,請參閱下列資源:

以下範例運算式適用於您可能會使用條件的常見情境。如需運算式中可用的屬性清單,請參閱「IAM 條件的屬性參考資料」。

條件運算式範例
允許在指定時間前存取
request.time < timestamp('TIMESTAMP')

將 TIMESTAMP 替換為世界標準時間的時間戳記,例如 2024-08-30T00:00:00.000Z。

如果要求中的資源具有指定標記,則允許存取
resource.matchTag('TAG_KEY', 'TAG_VALUE')

更改下列內容:

  • TAG_KEY:要比對的標記鍵,例如 env
  • TAG_VALUE:標記的值,例如 dev

在 IAM 政策中參照 Kubernetes 資源

在 IAM 政策中,您可以使用 IAM 主體 ID 選取 Kubernetes 資源。這個 ID 的語法如下:

PREFIX://iam.googleapis.com/projects/1234567890/locations/global/workloadIdentityPools/example-project.svc.id.goog/SELECTOR

在這個例子中,請考慮下列欄位:

  • PREFIX:必須是 principal 或 principalSet,視您選取的資源而定。principal 是指特定資源,例如單一 ServiceAccount。principalSet 適用於屬於指定資源的多項資源,例如特定叢集中的所有 Pod。
  • SELECTOR:選取主體類型的字串。例如,kubernetes.serviceaccount.uid/SERVICEACCOUNT_UID 會依據 UID 選取 ServiceAccount。

下表列出 GKE 支援的主體類型:

主體 ID 類型 語法
使用特定 Kubernetes ServiceAccount 的所有 Pod 依名稱選取 ServiceAccount:
principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/SERVICEACCOUNT

更改下列內容:

  • PROJECT_NUMBER:專案編號。如要取得專案編號,請參閱「識別專案」。
  • PROJECT_ID:您的 Google Cloud 專案 ID。
  • NAMESPACE:Kubernetes 命名空間。
  • SERVICEACCOUNT:Kubernetes ServiceAccount 名稱。

依 UID 選取 ServiceAccount:
principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/kubernetes.serviceaccount.uid/SERVICEACCOUNT_UID

更改下列內容:

  • PROJECT_NUMBER:您的專案編號 (數字)。如要取得專案編號,請參閱「識別專案」。
  • PROJECT_ID:您的 Google Cloud 專案 ID。
  • SERVICEACCOUNT_UID:API 伺服器中 ServiceAccount 物件的 UID。
命名空間中的所有 Pod,無論服務帳戶或叢集為何
principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/namespace/NAMESPACE

更改下列內容:

  • PROJECT_NUMBER:專案編號。如要取得專案編號,請參閱「識別專案」。
  • PROJECT_ID:您的 Google Cloud 專案 ID。
  • NAMESPACE:Kubernetes 命名空間。
特定叢集中的所有 Pod
principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/kubernetes.cluster/https://container.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/clusters/CLUSTER_NAME

更改下列內容:

  • PROJECT_NUMBER:專案編號。如要取得專案編號,請參閱「識別專案」。
  • PROJECT_ID:您的 Google Cloud 專案 ID。
  • CLUSTER_NAME:GKE 叢集名稱。
  • LOCATION:叢集位置。

憑證流程

工作負載傳送要求來存取 Google Cloud API 時 (例如使用 Google Cloud 用戶端程式庫時),會發生下列驗證步驟:

工作負載如何透過 Workload Identity 取得 IAM 服務帳戶權杖。
圖 1:工作負載如何透過 Workload Identity Federation for GKE 取得聯合存取權杖。
  1. 應用程式預設憑證 (ADC) 會向在 VM 上執行的 Compute Engine 中繼資料伺服器要求 Google Cloud 存取權杖。
  2. GKE 中繼資料伺服器會攔截權杖要求,並向 Kubernetes API 伺服器要求 Kubernetes ServiceAccount 權杖,以識別要求的工作負載。這項憑證是由 API 伺服器簽署的 JSON Web Token (JWT)。
  3. GKE 中繼資料伺服器會使用安全權杖服務,將 JWT 換成參照 Kubernetes 工作負載身分的短期聯盟存取權杖。

如支援的產品和限制所述,Security Token Service 傳回的聯合存取權杖在嘗試存取部分 Google Cloud 服務時,可能會受到限制。如果所選 Google Cloud 服務有限制,您可以視需要設定服務帳戶模擬。這個方法會產生 IAM 服務帳戶的存取權杖,工作負載可使用該權杖存取目標服務。詳情請參閱「將 Kubernetes 服務帳戶連結至 IAM」。

接著,工作負載就能存取其 IAM 主體 ID 可存取的任何 Google Cloud API。

Security Token Service 中 Exchange Token API 的配額

Security Token Service 中的 Exchange Token API 配額限制為每分鐘 6,000 個要求。如果看到 QUOTA_EXCEEDED 錯誤,可以透過「配額與系統限制」頁面,要求提高 Token exchange requests per minute 配額。

身分相同

如果多個叢集中的工作負載共用 workload identity pool,且主體 ID 中的中繼資料相同 (因為這些工作負載屬於同一個 Google Cloud 專案),IAM 會將這些工作負載視為相同。舉例來說,如果您在兩個叢集中有相同的命名空間,並在 IAM 中授予該命名空間的存取權,則兩個叢集中該命名空間的工作負載都會取得該存取權。您可以使用條件式 IAM 政策,將這項存取權限制在特定叢集。

舉例來說,請看下圖。叢集 A 和 B 屬於相同的工作負載身分集區。 Google Cloud 會將使用叢集 A 和叢集 B 的 backend 命名空間中 back-ksa ServiceAccount 的應用程式視為相同身分。IAM 不會區分發出呼叫的叢集。

圖表:說明 workload identity pool 內的相同身分
圖 2: 透過 Workload Identity Federation for GKE,使用相同身分存取 Google Cloud API。

這種身分相同性也意味著,您必須能夠信任特定 workload identity pool 中的每個叢集。舉例來說,如果上例中的新叢集 C 由不受信任的團隊擁有,他們可以建立 backend 命名空間,並使用 back-ksa ServiceAccount 存取 Google Cloud API,就像叢集 A 和叢集 B 一樣。

為避免不受信任的存取,請將叢集放在不同的專案中,確保叢集取得不同的 workload identity pool,或確保命名空間名稱彼此不同,避免使用共同的主體 ID。

GKE 中繼資料伺服器

為叢集啟用 Workload Identity Federation for GKE 時,叢集中的每個節點都會將中繼資料儲存在 GKE 中繼資料伺服器。GKE 中繼資料伺服器是 Kubernetes 工作負載所需 Compute Engine 中繼資料伺服器端點的子集。

GKE 中繼資料伺服器會以 DaemonSet 的形式運作,叢集中的每個 Linux 節點都有一個 Pod,或每個 Windows 節點都有一個原生 Windows 服務。中繼資料伺服器會攔截對 http://metadata.google.internal (169.254.169.254:80) 的 HTTP 要求。舉例來說,GET /computeMetadata/v1/instance/service-accounts/default/token 要求會擷取 Pod 設定模擬的 IAM 服務帳戶權杖。前往 GKE 中繼資料伺服器的流量絕不會離開代管 Pod 的 VM 執行個體。

權杖有效期限

根據預設,傳回的存取權杖效期為 1 小時 (3,600 秒)。為縮短用戶端延遲時間,GKE 中繼資料伺服器會快取存取權杖。在某些情況下,中繼資料伺服器傳回的快取權杖可能即將到期。

Cloud 用戶端程式庫內建邏輯,預設會檢查存取權杖是否會在接下來 3 分 45 秒內到期。如果權杖在到期期限內,GKE 會重新整理權杖。後續的 API 呼叫可以使用更新後的權杖。

如果您使用自己的程式碼直接存取 Google Cloud API,請導入類似的邏輯來處理權杖到期。程式碼應執行下列操作:

  1. 確認存取權杖是否會在 3 分 45 秒後過期。權杖酬載中的 exp 參數表示權杖到期時間戳記。
  2. 如果權杖將在 3 分 45 秒內到期,請提出權杖要求。

下表說明 GKE 中繼資料伺服器提供的 Compute Engine 中繼資料伺服器端點子集。如需 Compute Engine 中繼資料伺服器提供的端點完整清單,請參閱「預設 VM 中繼資料值」。

執行個體中繼資料

執行個體中繼資料會儲存在下列目錄中。

http://metadata.google.internal/computeMetadata/v1/instance/

項目 說明
hostname

節點的主機名稱。

id

節點的專屬 ID。

service-accounts/

與節點相關聯的服務帳戶目錄。每個服務帳戶都會提供下列資訊:

  • aliases
  • email:服務帳戶電子郵件地址。
  • identity:節點專屬的 JSON Web Token (JWT)。您必須在要求中加入 audience 參數。 例如:?audience=http://www.example.com。
  • scopes:指派給服務帳戶的存取權範圍。
  • token:用於驗證工作負載的 OAuth 2.0 存取權杖。
zone

GKE 節點的 Compute Engine 可用區。

執行個體屬性

執行個體屬性會儲存在下列目錄中。

http://metadata.google.internal/computeMetadata/v1/instance/attributes/

項目 說明
cluster-location

叢集的 Compute Engine 可用區或區域。

cluster-name

GKE 叢集的名稱。

cluster-uid

GKE 叢集的 UID。

系統僅支援表格中列出的屬性。如果您嘗試存取任何不支援的屬性,kube-system 命名空間中的 gke-metadata-server Pod 會產生並記錄 404 錯誤。錯誤訊息大致如下:

HTTP/404: generic::not_found: no child "", Reason: "NOT_FOUND", UserMessage: "Not Found"

如果您使用的是 istio-proxy,會看到類似下方的錯誤訊息:

Error fetching GCP Metadata property gcp_gce_instance_template: metadata: GCE metadata "instance/attributes/UNSUPPORTED_ATTRIBUTE" not defined

專案中繼資料

叢集專案中繼資料會儲存在下列目錄中。

http://metadata.google.internal/computeMetadata/v1/project/

項目 說明
project-id

您的 Google Cloud 專案 ID。

numeric-project-id

您的 Google Cloud 專案編號。

Workload Identity Federation for GKE 的限制

  • GKE 為專案建立的工作負載身分集區名稱無法變更。 Google Cloud

  • 如果您將 Kubernetes 服務帳戶連結至 IAM 服務帳戶,以設定 GKE 適用的工作負載身分聯盟,GKE 中繼資料伺服器會傳回 SERVICEACCOUNT_NAME.svc.id.goog 值做為服務帳戶 ID。這個 ID 未使用標準 IAM 主體 ID 語法,可能會導致部分程式輔助作業發生錯誤。如要取得服務帳戶 ID 做為 IAM 主體 ID,請將 iam.gke.io/return-principal-id-as-email: "true" 註解新增至 Kubernetes ServiceAccount。

  • 當 GKE 在節點集區上啟用 GKE 中繼資料伺服器時,Pod 就無法再存取 Compute Engine 中繼資料伺服器。相反地,GKE 中繼資料伺服器會攔截這些 Pod 向中繼資料端點提出的要求,但在主機網路上執行的 Pod 除外。

  • 如果 Cloud Storage FUSE CSI 驅動程式搭配 1.33.3-gke.1226000 以上版本的 Standard GKE 叢集使用,在主機網路 (hostNetwork: true) 上執行的 Pod 就能使用自己的 Kubernetes 服務帳戶進行驗證。詳情請參閱「為使用主機網路的 Pod 設定存取權」。

  • GKE 中繼資料伺服器需要幾秒鐘的時間,才會開始接受新建立 Pod 的要求。因此,在 Pod 建立後的最初幾秒內,嘗試使用 Workload Identity Federation for GKE 進行驗證可能會失敗。重新嘗試呼叫即可解決問題。詳情請參閱「疑難排解」。

  • GKE 內建的記錄和監控代理程式會繼續使用節點的服務帳戶。

  • Workload Identity Federation for GKE 需要手動設定 Knative serving,才能繼續發布要求指標。

  • Workload Identity Federation for GKE 限制每個節點最多可同時連線至 GKE 中繼資料伺服器 500 次。超過這項限制的其他並行呼叫會排入等待佇列,稍後再處理。如果 GKE 中繼資料伺服器在處理要求前達到用戶端逾時,這個佇列機制可能會導致 HTTP/499 錯誤。

  • GKE 中繼資料伺服器使用的記憶體資源,與叢集中的 Kubernetes 服務帳戶總數成正比。如果叢集有超過 3, 000 個 Kubernetes 服務帳戶,kubelet 可能會終止中繼資料伺服器 Pod。如需緩解措施,請參閱「疑難排解」。

  • Workload Identity Federation for GKE 在 VPC Service Controls perimeter 內運作,可存取 perimeter 內的資源。您也可以在 VPC Service Controls 輸入和輸出規則 (預先發布版) 中,為 GKE 主體設定 Workload Identity Federation,允許跨 perimeter 存取,而不必模擬中繼 IAM 服務帳戶。

Workload Identity Federation for GKE 的替代方案

您可以採用下列其中一種 Workload Identity Federation for GKE 替代方案,從 GKE 存取Google Cloud API。建議您使用 Workload Identity Federation for GKE,因為這些替代方案需要您做出某些安全性妥協。

後續步驟