本頁面說明如何設定應用程式,以便從機群中驗證Google Cloud API (例如 Compute Engine API 或 AI Platform API),這些機群在整個機群中具有混合信任模型。如果車隊在整個車隊中採用共用信任模型,請參閱「從共用信任車隊工作負載向 Google Cloud API 進行驗證」。
本頁面適用於平台管理員和營運人員,以及想要透過程式從車隊工作負載向 Google CloudAPI 進行驗證的安全工程師。如要進一步瞭解說明文件中提及的使用者角色和範例工作,請參閱「常見的 GKE 使用者角色和工作」。 Google Cloud
閱讀本頁面之前,請務必先熟悉下列概念:
- 關於機群 Workload Identity 聯盟
- Kubernetes ConfigMap
- Identity and Access Management (IAM) 允許政策
- 團隊範圍和機群命名空間
關於混合信任環境的機群 Workload Identity 聯盟
透過 Fleet Workload Identity Federation,您可以將Google Cloud API 和資源的 IAM 角色授予 Fleet 中的實體,例如特定命名空間中的工作負載。根據預設,機群主機專案會使用 Google 管理的工作負載身分集區,為整個機群中的實體佈建身分。不過,在混合信任環境 (例如多租戶機群) 或執行獨立叢集的機群主機專案中,建議您為部分工作負載和叢集設定個別的自行管理工作負載身分集區。
使用自行管理工作負載身分集區的實體,在 IAM 政策中的 ID 與使用機群主機專案 Google 管理工作負載身分集區的實體不同。這樣一來,授予特定車隊命名空間中主體的存取權時,就不會意外授予與 ID 相符的任何其他主體存取權。
如要使用自行管理的工作負載身分集區,必須使用團隊範圍。團隊範圍可讓您針對個別團隊控管部分機群資源的存取權。將特定團隊範圍繫結至特定機群成員叢集,允許該團隊在這些叢集上部署工作負載。在團隊範圍內,團隊成員只能將工作負載部署至機群命名空間。
使用自行管理的工作負載身分集區為團隊範圍工作負載提供身分,有以下優點:
- 請確保授予艦隊命名空間中實體的存取權,不會無意中套用至其他命名空間或叢集中的實體。
- 將一組機群叢集繫結至團隊範圍,並在這些叢集中將自行管理的集區設為身分提供者,即可設定這些叢集從自行管理的集區取得身分。
- 設定團隊範圍的繫結叢集子集,只在特定叢集中將自行管理的集區設為身分識別提供者,即可從自行管理的集區取得身分。
混合信任環境中的身分相同性範例
請考量下列情境:
- 您有兩個機群成員叢集:
frontend-cluster和finance-cluster。 - 您尚未設定自行管理的工作負載身分集區。
- 您可以在團隊範圍中建立
finance-team團隊範圍和finance-ns機群命名空間。 - 將
finance-cluster叢集繫結至finance-team團隊範圍。 - 您要將 IAM 角色授予
finance-saKubernetesfinance-ns叢集命名空間中的 ServiceAccount。
符合下列條件的工作負載會共用相同身分:
- 在
finance-ns機群命名空間中執行。 - 使用
finance-saServiceAccount。
不過,如果 frontend-cluster 叢集中的使用者建立 Kubernetes 命名空間和 finance-sa ServiceAccount,他們會取得與 finance-cluster 叢集工作負載相同的身分。finance-ns這是因為整個機群使用機群主機專案的 Google 代管工作負載身分集區,且主體 ID 未指定主機叢集。
請考慮對上述情境進行下列變更:
- 在 Fleet 中設定自行管理的工作負載身分集區。
- 您會設定
finance-cluster叢集,從自行管理的集區取得身分,而不是從 Google 管理的集區取得。 - 您建立的 IAM 角色授權會指定主體 ID 中的自行管理集區,而非 Google 管理的集區。
在 finance-cluster 的 finance-ns Fleet 命名空間中執行的工作負載,現在會從自行管理的集區取得身分。不過,frontend-cluster 叢集中的 finance-ns Kubernetes 命名空間實體,仍會從機群主機專案的 Google 管理 workload identity pool 取得身分。
這些變更可帶來下列好處:
- 您可以明確將角色授予
finance-ns艦隊命名空間中的實體。 frontend-cluster叢集中的實體無法取得相同存取權,因為frontend-cluster叢集中的身分來自 Google 管理的 workload identity pool。
事前準備
確認您已安裝下列指令列工具:
- 最新版 Google Cloud CLI,內含
gcloud,可與 Google Cloud互動的指令列工具。 kubectl
如果您使用 Cloud Shell 做為與 Google Cloud互動的 Shell 環境,系統會為您安裝這些工具。
- 最新版 Google Cloud CLI,內含
確認您已初始化 gcloud CLI,以便搭配專案使用。
需求條件
您必須在機群中使用機群團隊管理功能,例如團隊範圍和機群命名空間。本頁面的操作說明會示範如何設定範例團隊範圍和機群命名空間。
準備您的叢集
機群中的應用程式必須先註冊至機群,並正確設定使用機群 Workload Identity Federation,才能接收聯合身分。以下各節說明如何為不同類型的叢集設定機群 Workload Identity Federation。
GKE
如果是 GKE 叢集,請按照下列步驟操作:
- 如果尚未啟用,請在 Google Kubernetes Engine 叢集上啟用 GKE 的 Workload Identity 聯盟。
- 向機群註冊叢集。
您也可以在建立叢集和註冊車隊的過程中,啟用 Workload Identity Federation for GKE。
外部叢集 Google Cloud
下列類型的叢集會自動啟用機群工作負載身分聯合驗證,並在建立叢集時註冊至機群:
- VMware 上的 Google Distributed Cloud (僅限軟體)
- 裸機上的 Google Distributed Cloud (僅限軟體)
- GKE on AWS
- GKE on Azure
附加的叢集
使用 GKE Multi-Cloud API 註冊的 EKS 和 AKS 附加叢集,預設會啟用機群 Workload Identity 聯盟。如果其他連結的叢集符合必要條件,即可註冊啟用機群 Workload Identity 聯盟。請按照「註冊叢集」一文中的叢集類型操作說明進行。
設定 IAM workload identity pool
在本節中,您會在機群主機專案中建立新的 IAM 工作負載身分集區,並授予機群服務代理程式新集區的存取權。
建立 workload identity pool:
gcloud iam workload-identity-pools create POOL_NAME \ --location=global \ --project=POOL_HOST_PROJECT_ID \ --mode=TRUST_DOMAIN更改下列內容:
POOL_NAME:新 workload identity pool 的名稱。POOL_HOST_PROJECT_ID:您要在其中建立自行管理的 Workload Identity Pool 的專案 ID。您可以使用任何 Google Cloud 專案,包括機群主專案。
在新的 workload identity pool 中,將 IAM Workload Identity Pool Admin 角色 (
roles/iam.workloadIdentityPoolAdmin) 授予機群服務代理:gcloud iam workload-identity-pools add-iam-policy-binding POOL_NAME \ --project=POOL_HOST_PROJECT_ID \ --location=global \ --member=serviceAccount:service-FLEET_HOST_PROJECT_NUMBER@gcp-sa-gkehub.iam.gserviceaccount.com \ --role=roles/iam.workloadIdentityPoolAdmin \ --condition=None將
FLEET_HOST_PROJECT_NUMBER替換為車隊主專案的專案編號。
將自行管理的集區新增至機群設定
在本節中,您將透過機群 Workload Identity 聯盟啟用自行管理的集區,並將建立的集區新增至機群設定。本節也提供建立新團隊範圍和機群命名空間的說明。如果機群已設定團隊範圍和機群命名空間,請略過這些步驟。
在 Fleet 層級啟用 Fleet Workload Identity Federation:
gcloud beta container fleet workload-identity enable \ --project=FLEET_HOST_PROJECT_ID將
FLEET_HOST_PROJECT_ID替換為車隊主機專案的專案 ID。將自行管理的工作負載身分集區新增至 Fleet 設定:
gcloud beta container fleet workload-identity scope-tenancy-pool set POOL_NAME將 POOL_NAME 替換為自行管理的 workload identity pool 名稱。這個值的語法如下:
POOL_NAME.global.POOL_HOST_PROJECT_NUMBER.workload.id.goog建立新的團隊範圍。如果您已有現有的團隊範圍和車隊命名空間,請跳至「驗證 workload identity pool 設定」一節。
gcloud container fleet scopes create SCOPE_NAME將
SCOPE_NAME替換為新團隊範圍的名稱。在團隊範圍中建立新的機群命名空間:
gcloud container fleet scopes namespaces create NAMESPACE_NAME \ --scope=SCOPE_NAME將
NAMESPACE_NAME替換為新車隊命名空間的名稱。將機群中的叢集繫結至團隊範圍:
gcloud container fleet memberships bindings create BINDING_NAME \ --membership=FLEET_CLUSTER_NAME \ --location=global \ --scope=SCOPE_NAME更改下列內容:
BINDING_NAME:新成員資格繫結的名稱。FLEET_CLUSTER_NAME:要繫結至團隊範圍的現有機群叢集名稱。
驗證工作負載身分集區設定
在本節中,您將確認自行管理的工作負載身分集區設定是否成功。
說明機群成員設定:
gcloud container fleet memberships describe FLEET_CLUSTER_NAME \ --location=global將
FLEET_CLUSTER_NAME替換為現有機群叢集的名稱,該叢集已繫結至機群中的任何團隊範圍。輸出結果會與下列內容相似:
authority: ... scopeTenancyIdentityProvider: https://gkehub.googleapis.com/projects/FLEET_HOST_PROJECT_ID/locations/global/memberships/FLEET_CLUSTER_NAME scopeTenancyWorkloadIdentityPool: POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog workloadIdentityPool: FLEET_HOST_PROJECT_ID.svc.id.goog ...這項輸出內容應包含下列欄位:
scopeTenancyIdentityProvider:在團隊範圍內的 Fleet 命名空間中執行的工作負載身分提供者。這個值是叢集的資源 ID。scopeTenancyWorkloadIdentityPool:團隊範圍內 Fleet 命名空間中的工作負載會從這個 workload identity pool 取得 ID。這個值是您自行管理的工作負載身分集區,格式為POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog。workloadIdentityPool:機群主機專案的 Google 管理 Workload Identity Pool 名稱,機群中的所有其他工作負載預設都會從這個 Pool 取得身分。
選用:檢查工作負載身分集區是否有名稱與機群命名空間相同的命名空間:
gcloud iam workload-identity-pools namespaces list \ --workload-identity-pool=POOL_NAME \ --location=global輸出結果會與下列內容相似:
--- description: Fleet namespace NAMESPACE_NAME name: projects/FLEET_HOST_PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME/namespaces/NAMESPACE_NAME state: ACTIVE
現在,機群可以使用自行管理的工作負載身分集區,為在機群命名空間中執行的工作負載取得身分。如要開始使用自行管理的集區,請設定特定叢集取得身分的方式,詳情請參閱下一節。
讓工作負載使用身分的自我管理集區
如要讓工作負載使用自行管理的集區,請使用 Kubernetes ConfigMap,在機群成員叢集中設定特定機群命名空間。這項以叢集和命名空間為單位的設定,可讓您進一步縮減授權範圍,從整個機群命名空間縮減至特定叢集中特定機群命名空間內執行的工作負載。
連線至機群成員叢集:
gcloud container clusters get-credentials FLEET_CLUSTER_NAME \ --project=CLUSTER_PROJECT_ID \ --location=CLUSTER_LOCATION更改下列內容:
FLEET_CLUSTER_NAME:已繫結至團隊範圍的 Fleet 成員叢集名稱。CLUSTER_PROJECT_ID:叢集專案的專案 ID。CLUSTER_LOCATION:叢集位置。
取得自行管理的工作負載身分集區完整名稱。稍後會用到。
kubectl get membership membership -o json | jq -r ".spec.scope_tenancy_workload_identity_pool"輸出結果會與下列內容相似:
POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog取得團隊範圍的識別資訊提供者名稱。稍後會需要用到。
kubectl get membership membership -o json | jq -r ".spec.scope_tenancy_identity_provider"輸出結果會與下列內容相似:
https://gkehub.googleapis.com/projects/FLEET_HOST_PROJECT_ID/locations/global/memberships/FLEET_CLUSTER_NAME在文字編輯器中,將下列 ConfigMap 的 YAML 資訊清單儲存為
self-managed-pool.yaml:kind: ConfigMap apiVersion: v1 metadata: namespace: NAMESPACE_NAME name: google-application-credentials data: config: | { "type": "external_account", "audience": "identitynamespace:SELF_MANAGED_POOL_FULL_NAME:IDENTITY_PROVIDER", "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", "token_url": "https://sts.googleapis.com/v1/token", "credential_source": { "file": "/var/run/secrets/tokens/gcp-ksa/token" } }更改下列內容:
NAMESPACE_NAME:車隊命名空間的名稱。SELF_MANAGED_POOL_FULL_NAME:這個部分中,上一個步驟輸出內容的自管 workload identity pool 完整名稱。例如:example-pool.global.1234567890.workload.id.goog。IDENTITY_PROVIDER:這個部分中上一個步驟的輸出內容所提供的身分識別提供者名稱。例如:https://gkehub.googleapis.com/projects/1234567890/locations/global/memberships/example-cluster.
在叢集中部署 ConfigMap:
kubectl create -f self-managed-pool.yaml
部署 ConfigMap 會向 GKE 指出,該命名空間中的工作負載應使用自行管理的工作負載身分集區來取得身分。
將 IAM 角色授予主體
在本節中,您將在車隊命名空間中建立 Kubernetes ServiceAccount,並將 IAM 角色授予該 ServiceAccount。使用這個 ServiceAccount 的 Pod 隨後就能存取您授予角色的 Google Cloud 資源。
在艦隊命名空間中建立 Kubernetes ServiceAccount:
kubectl create serviceaccount SERVICEACCOUNT_NAME \ --namespace=NAMESPACE_NAME更改下列內容:
SERVICEACCOUNT_NAME:新 ServiceAccount 的名稱。NAMESPACE_NAME:車隊命名空間的名稱。
將 IAM 角色授予 ServiceAccount。下列範例指令會將 bucket 的「Storage 物件檢視者」角色 (
roles/storage.objectViewer) 授予 ServiceAccount:gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \ --member=principal://iam.googleapis.com/projects/FLEET_HOST_PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog/subject/ns/NAMESPACE_NAME/sa/SERVICEACCOUNT_NAME \ --role=roles/storage.objectViewer \ --condition=None
member 旗標包含您建立的新 ServiceAccount 的主體 ID。工作負載傳送至 Google CloudAPI 的要求會使用同盟存取權杖。這個同盟存取權杖包含傳送要求實體的主體 ID。如果允許政策中授予目標資源角色的主體,與同盟存取權權杖中的主體相符,即可繼續進行驗證和授權。
部署使用自行管理集區的工作負載
您在機群命名空間中套用的 Kubernetes 資訊清單必須經過設定,才能從自行管理的集區取得身分。您部署的工作負載需要呼叫 Google Cloud API,因此應包含下列欄位:
metadata.namespace:車隊命名空間的名稱。spec.serviceAccountName:艦隊命名空間中 Kubernetes ServiceAccount 的名稱。spec.containers.env:名為GOOGLE_APPLICATION_CREDENTIALS的環境變數,指出應用程式預設憑證 (ADC) 檔案的路徑。spec.containers.volumeMounts:唯讀磁碟區,可讓容器使用 ServiceAccount 的不記名權杖。spec.volumes:投影磁碟區,可將 ServiceAccount 權杖掛接到 Pod 中。權杖的對象是自行管理的工作負載身分集區。包含 Fleet Workload Identity 聯盟設定的 ConfigMap 是磁碟區的來源。
如要查看設定正確的資訊清單檔案範例,請參閱「從工作負載驗證驗證」一節。
驗證工作負載的驗證
本節提供選用操作說明,可列出範例 Cloud Storage bucket 的內容,確認您是否正確設定自行管理的工作負載身分集區。您要建立值區、將值區的角色授予機群命名空間中的 ServiceAccount,並部署 Pod 來嘗試存取值區。
建立 Cloud Storage bucket:
gcloud storage buckets create gs://FLEET_HOST_PROJECT_ID-workload-id-bucket \ --location=LOCATION \ --project=FLEET_HOST_PROJECT_ID將 bucket 的
roles/storage.objectViewer角色授予叢集命名空間中的 ServiceAccount:gcloud storage buckets add-iam-policy-binding gs://FLEET_HOST_PROJECT_ID-workload-id-bucket \ --condition=None \ --role=roles/storage.objectViewer \ --member=principal://iam.googleapis.com/projects/FLEET_PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog/subject/ns/NAMESPACE_NAME/sa/SERVICEACCOUNT_NAME更改下列內容:
FLEET_HOST_PROJECT_NUMBER:車隊主機專案的專案編號。POOL_NAME:自行管理的 Workload Identity Pool 名稱。NAMESPACE_NAME:要在其中執行 Pod 的 Fleet 命名空間名稱。SERVICEACCOUNT_NAME:Pod 應使用的 Kubernetes ServiceAccount 名稱。
將下列資訊清單儲存為
pod-bucket-access.yaml:apiVersion: v1 kind: Pod metadata: name: bucket-access-pod namespace: NAMESPACE_NAME spec: serviceAccountName: SERVICEACCOUNT_NAME containers: - name: sample-container image: google/cloud-sdk:slim command: ["sleep","infinity"] env: - name: GOOGLE_APPLICATION_CREDENTIALS value: /var/run/secrets/tokens/gcp-ksa/google-application-credentials.json volumeMounts: - name: gcp-ksa mountPath: /var/run/secrets/tokens/gcp-ksa readOnly: true volumes: - name: gcp-ksa projected: defaultMode: 420 sources: - serviceAccountToken: path: token audience: POOL_NAME.global.FLEET_HOST_PROJECT_NUMBER.workload.id.goog expirationSeconds: 172800 - configMap: name: my-cloudsdk-config optional: false items: - key: "config" path: "google-application-credentials.json"更改下列內容:
NAMESPACE_NAME:要在其中執行 Pod 的 Fleet 命名空間名稱。SERVICEACCOUNT_NAME:Pod 應使用的 Kubernetes ServiceAccount 名稱。POOL_NAME:自行管理的 Workload Identity Pool 名稱。FLEET_HOST_PROJECT_NUMBER:車隊主機專案的專案編號。
在叢集中部署 Pod:
kubectl apply -f pod-bucket-access.yaml在 Pod 中開啟殼層工作階段:
kubectl exec -it bucket-access-pod -n NAMESPACE_NAME -- /bin/bash嘗試列出值區中的物件:
curl -X GET -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ "https://storage.googleapis.com/storage/v1/b/FLEET_HOST_PROJECT_ID-workload-id-bucket/o"輸出內容如下:
{ "kind": "storage#objects" }
您可以選擇驗證不同機群成員叢集中類似的命名空間和 ServiceAccount,是否無法聲明相同身分。在採用機群 Workload Identity 聯盟,但沒有機群命名空間或自我管理集區設定的叢集中,請完成下列步驟:
- 建立新的 Kubernetes 命名空間,名稱與您設定自管工作負載身分集區的機群命名空間相同。
- 建立新的 Kubernetes ServiceAccount,並將其命名為您在先前章節中授予 IAM 角色的 ServiceAccount。
部署使用相同 ServiceAccount 和命名空間的 Pod,但
spec.volumes.projected.sources.serviceAccountToken欄位指定 Google 管理的工作負載身分識別集區。這個集區的語法如下:FLEET_HOST_PROJECT_ID.svc.id.goog嘗試從 Pod 的殼層工作階段存取 Cloud Storage bucket。
輸出內容應為 401: Unauthorized 錯誤,因為使用 Google 代管工作負載身分集區的 Pod 主體 ID,與使用自行管理集區的 Pod 主體 ID 不同。