本文档介绍如何使用适用于 GKE 的工作负载身份联合从 Google Kubernetes Engine (GKE) 集群中运行的工作负载更安全地访问 Google Cloud API。如需了解详情,请参阅适用于 GKE 的工作负载身份联合简介。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行
gcloud components update
以获取最新版本。
- 确保适用于 GKE 的工作负载身份联合支持您要访问的 Google Cloud API。如需查看支持的 API 列表,请参阅支持的产品和限制。如果 API 不受支持,或者您的使用场景被该服务的工作负载身份联合限制阻止,请参阅此文档中的“替代方案:将 Kubernetes ServiceAccount 关联到 IAM”。
确保您已启用 IAM Service Account Credentials API。
确保您拥有以下 IAM 角色:
roles/container.admin
roles/iam.serviceAccountAdmin
确保您了解适用于 GKE 的工作负载身份联合的限制。
在集群和节点池上启用适用于 GKE 的工作负载身份联合
在 Autopilot 中,适用于 GKE 的工作负载身份联合默认启用。跳到将应用配置为使用适用于 GKE 的工作负载身份联合部分。
在 Standard 中,您可以使用 Google Cloud CLI 或 Google Cloud 控制台在集群和节点池上启用适用于 GKE 的工作负载身份联合。必须先在集群级层启用适用于 GKE 的工作负载身份联合,然后才能在节点池上启用适用于 GKE 的工作负载身份联合。
创建新集群
您可以使用 gcloud CLI 或 Google Cloud 控制台在新的标准集群上启用适用于 GKE 的工作负载身份联合。
gcloud
-
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
如需在新集群上启用适用于 GKE 的工作负载身份联合,请运行以下命令:
gcloud container clusters create CLUSTER_NAME \ --location=LOCATION \ --workload-pool=PROJECT_ID.svc.id.goog
替换以下内容:
CLUSTER_NAME
:新集群的名称。LOCATION
:集群的 Compute Engine 位置。PROJECT_ID
:您的 Google Cloud 项目 ID。
控制台
如需在新集群上启用适用于 GKE 的工作负载身份联合,请执行以下操作:
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
点击 add_box 创建。
在创建集群对话框中,对于 GKE Standard,点击配置。
在导航菜单的集群部分中,点击安全。
选中启用 Workload Identity 复选框。
继续配置该集群,然后点击创建。
更新现有集群
您可以使用 gcloud CLI 或 Google Cloud 控制台在现有标准集群上启用适用于 GKE 的工作负载身份联合。现有节点池不受影响,但集群中的任何新节点池都使用适用于 GKE 的工作负载身份联合。
gcloud
-
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
如需在现有集群上启用适用于 GKE 的工作负载身份联合,请运行以下命令:
gcloud container clusters update CLUSTER_NAME \ --location=LOCATION \ --workload-pool=PROJECT_ID.svc.id.goog
替换以下内容:
CLUSTER_NAME
:现有集群的名称。LOCATION
:集群的 Compute Engine 位置。PROJECT_ID
:您的 Google Cloud 项目 ID。
控制台
如需在现有集群上启用适用于 GKE 的工作负载身份联合,请执行以下操作:
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
在集群列表中,点击您要修改的集群的名称。
在集群详情页面的安全部分中,点击
修改 Workload Identity。在修改 Workload Identity 对话框中,选中启用 Workload Identity 复选框。
点击保存更改。
将现有工作负载迁移到适用于 GKE 的工作负载身份联合
在现有集群上启用适用于 GKE 的工作负载身份联合后,您可能需要迁移正在运行的工作负载,以使用适用于 GKE 的工作负载身份联合。选择最适合您的环境的迁移策略。您可以创建新的节点池并启用适用于 GKE 的工作负载身份联合,也可以更新现有的节点池以启用适用于 GKE 的工作负载身份联合。
如果您还需要修改应用以与适用于 GKE 的工作负载身份联合兼容,我们建议您创建新的节点池。
创建新的节点池
如果集群启用了适用于 GKE 的工作负载身份联合,则您创建的所有新节点池默认使用适用于 GKE 的工作负载身份联合。如需创建启用了适用于 GKE 的工作负载身份联合的新节点池,请运行以下命令:
gcloud container node-pools create NODEPOOL_NAME \
--cluster=CLUSTER_NAME \
--region=COMPUTE_REGION \
--workload-metadata=GKE_METADATA
替换以下内容:
NODEPOOL_NAME
:新节点池的名称。CLUSTER_NAME
:启用了适用于 GKE 的工作负载身份联合的现有集群的名称。
--workload-metadata=GKE_METADATA
标志将节点池配置为使用 GKE 元数据服务器。我们建议您添加该标志,这样一来,未在集群上启用适用于 GKE 的工作负载身份联合时,节点池创建将会失败。
更新现有节点池
在集群上启用适用于 GKE 的工作负载身份联合后,您可以在现有节点池上手动启用适用于 GKE 的工作负载身份联合。
gcloud
-
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
如需修改现有节点池以使用适用于 GKE 的工作负载身份联合,请运行以下命令:
gcloud container node-pools update NODEPOOL_NAME \ --cluster=CLUSTER_NAME \ --region=COMPUTE_REGION \ --workload-metadata=GKE_METADATA
如果集群启用了适用于 GKE 的工作负载身份联合,您可以通过明确指定
--workload-metadata=GCE_METADATA
在特定节点池中选择性地停用它。如需了解详情,请参阅保护集群元数据。
控制台
如需修改现有节点池以使用适用于 GKE 的工作负载身份联合,请执行以下步骤:
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
在集群列表中,点击您要修改的集群的名称。
点击节点标签页。
在节点池部分中,点击要修改的节点池的名称。
在节点池详情页面中,点击
修改。在修改节点池页面的安全部分中,选中启用 GKE 元数据服务器复选框。
点击保存。
将应用配置为使用适用于 GKE 的工作负载身份联合
如需让您的 GKE 应用使用适用于 GKE 的工作负载身份联合向 Google Cloud API 进行身份验证,您可以为特定 API 创建 IAM 政策。这些政策中的主账号是与工作负载、命名空间或 ServiceAccount 相对应的 IAM 主账号标识符。
配置授权和主账号
获取集群的凭据:
gcloud container clusters get-credentials CLUSTER_NAME \ --location=LOCATION
替换以下内容:
CLUSTER_NAME
:启用了适用于 GKE 的工作负载身份联合的集群的名称。LOCATION
:您的集群的位置。
创建用于 Kubernetes 服务账号的命名空间。您还可以使用
default
命名空间或任何现有命名空间。kubectl create namespace NAMESPACE
为您的应用创建 Kubernetes 服务账号。您还可以在任何命名空间中使用任何现有的 Kubernetes ServiceAccount。如果您未为工作负载分配 ServiceAccount,则 Kubernetes 会在命名空间中分配
default
ServiceAccount。kubectl create serviceaccount KSA_NAME \ --namespace NAMESPACE
替换以下内容:
KSA_NAME
:新 Kubernetes ServiceAccount 的名称。NAMESPACE
:ServiceAccount 的 Kubernetes 命名空间的名称。
创建引用 Kubernetes ServiceAccount 的 IAM 允许政策。对于应用需要访问的特定 Google Cloud 资源,最好授予相应的权限。您必须拥有相关的 IAM 权限才能在项目中创建允许政策。
例如,以下命令会向您创建的 ServiceAccount 授予 Kubernetes Engine Cluster Viewer (
roles/container.clusterViewer
) 角色:gcloud projects add-iam-policy-binding projects/PROJECT_ID \ --role=roles/container.clusterViewer \ --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME \ --condition=None
替换以下内容:
PROJECT_ID
:您的 Google Cloud 项目 ID。PROJECT_NUMBER
:您的 Google Cloud 项目编号(数字)。
您可以针对支持 IAM 允许政策的任何 Google Cloud 资源授予角色。主账号标识符的语法取决于 Kubernetes 资源。如需查看支持的标识符列表,请参阅适用于 GKE 的工作负载身份联合的主账号标识符。
验证适用于 GKE 的工作负载身份联合设置
在本部分中,您将创建一个 Cloud Storage 存储桶,并向您在上一部分中创建的 Kubernetes ServiceAccount 授予对该存储桶的查看权限。然后,您可以部署工作负载并测试容器是否可以列出项目中的集群。
创建空的 Cloud Storage 存储桶:
gcloud storage buckets create gs://BUCKET
将
BUCKET
替换为新存储桶的名称。向您创建的 ServiceAccount 授予 Storage Object Viewer (
roles/storage.objectViewer
) 角色:gcloud storage buckets add-iam-policy-binding gs://BUCKET \ --role=roles/storage.objectViewer \ --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME \ --condition=None
替换以下内容:
PROJECT_ID
:您的 Google Cloud 项目 ID。PROJECT_NUMBER
:您的 Google Cloud 项目编号(数字)。NAMESPACE
:包含 ServiceAccount 的 Kubernetes 命名空间。KSA_NAME
:ServiceAccount 的名称。
将以下清单保存为
test-app.yaml
:apiVersion: v1 kind: Pod metadata: name: test-pod namespace: NAMESPACE spec: serviceAccountName: KSA_NAME containers: - name: test-pod image: google/cloud-sdk:slim command: ["sleep","infinity"] resources: requests: cpu: 500m memory: 512Mi ephemeral-storage: 10Mi
仅在 Standard 集群中,将以下内容添加到
template.spec
字段,以将 Pod 放置在使用适用于 GKE 的工作负载身份联合的节点池上。在 Autopilot 集群中跳过此步骤,这会拒绝此 nodeSelector,因为每个节点都使用适用于 GKE 的工作负载身份联合。
spec: nodeSelector: iam.gke.io/gke-metadata-server-enabled: "true"
将配置应用到您的集群:
kubectl apply -f test-app.yaml
等待 Pod 准备就绪。如需检查 Pod 的状态,请运行以下命令:
kubectl get pods --namespace=NAMESPACE
Pod 准备就绪后,输出类似于以下内容:
NAME READY STATUS RESTARTS AGE test-pod 1/1 Running 0 5m27s
在 Pod 中打开 shell 会话:
kubectl exec -it pods/test-pod --namespace=NAMESPACE -- /bin/bash
获取存储桶中的对象列表:
curl -X GET -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://storage.googleapis.com/storage/v1/b/BUCKET/o"
输出如下所示:
{ "kind": "storage#objects" }
此输出显示 Pod 可以访问存储桶中的对象。
替代方案:将 Kubernetes ServiceAccount 关联到 IAM
我们建议您使用 IAM 主账号标识符配置适用于 GKE 的工作负载身份联合。但是,此联合身份对每个受支持的 Google Cloud API 有特定限制。如需查看限制列表,请参阅支持的产品和限制。
如果您存在这些限制,请按照以下步骤配置从 GKE 工作负载对这些 API 的访问权限:
创建 Kubernetes 命名空间:
kubectl create namespace NAMESPACE
创建 Kubernetes ServiceAccount:
kubectl create serviceaccount KSA_NAME \ --namespace=NAMESPACE
创建 IAM 服务账号。 您还可以在组织的任何项目中使用任何现有的 IAM 服务账号。
gcloud iam service-accounts create IAM_SA_NAME \ --project=IAM_SA_PROJECT_ID
替换以下内容:
IAM_SA_NAME
:新 IAM 服务账号的名称。IAM_SA_PROJECT_ID
:您的 IAM 服务账号的项目 ID。
如需了解如何授权 IAM 服务账号访问 Google Cloud API,请参阅了解服务账号。
向您的 IAM 服务账号授予在特定 Google Cloud API 上所需的角色:
gcloud projects add-iam-policy-binding IAM_SA_PROJECT_ID \ --member "serviceAccount:IAM_SA_NAME@IAM_SA_PROJECT_ID.iam.gserviceaccount.com" \ --role "ROLE_NAME"
将
ROLE_NAME
替换为角色的名称,例如roles/spanner.viewer
。创建 IAM 允许政策,以向 Kubernetes ServiceAccount 授予模拟 IAM 服务账号的权限:
gcloud iam service-accounts add-iam-policy-binding IAM_SA_NAME@IAM_SA_PROJECT_ID.iam.gserviceaccount.com \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"
为 Kubernetes ServiceAccount 添加注解,以便 GKE 看到服务账号之间的关联:
kubectl annotate serviceaccount KSA_NAME \ --namespace NAMESPACE \ iam.gke.io/gcp-service-account=IAM_SA_NAME@IAM_SA_PROJECT_ID.iam.gserviceaccount.com
通过代码使用适用于 GKE 的工作负载身份联合
通过代码向 Google Cloud 服务进行身份验证的过程,与使用 Compute Engine 元数据服务器进行身份验证的过程相同。使用适用于 GKE 的工作负载身份联合时,您对实例元数据服务器发出的请求将路由到 GKE 元数据服务器。 使用实例元数据服务器进行身份验证的现有代码(如使用 Google Cloud 客户端库的代码)在运行时不应进行任何修改。
在适用于 GKE 的工作负载身份联合中使用其他项目的配额
在运行 GKE 1.24 版或更高版本的集群上,您可以在调用 IAM Service Account Credentials API 中的 GenerateAccessToken
和 GenerateIdToken
方法时,视需要将 Kubernetes 服务账号配置为使用其他 Google Cloud 项目中的配额。这样,您就无需完全使用主项目中的配额,而是可以为集群中的这些服务使用其他项目中的配额。
如需配置适用于 GKE 的工作负载身份联合的配额项目,请执行以下操作:
将配额项目的
serviceusage.services.use
权限授予 Kubernetes 服务账号。gcloud projects add-iam-policy-binding QUOTA_PROJECT_ID \ --role=roles/serviceusage.serviceUsageConsumer \ --member='principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/serviceaccount/NAMESPACE/KSA_NAME' \
将
QUOTA_PROJECT_ID
替换为配额项目的 ID。使用配额项目为 Kubernetes 服务账号添加注释:
kubectl annotate serviceaccount KSA_NAME \ --namespace NAMESPACE \ iam.gke.io/credential-quota-project=QUOTA_PROJECT_ID
如需验证配置是否生效,请执行以下操作:
创建一个 pod 并启动一个 shell 会话。请参阅 Kubernetes 文档以获取正在运行的容器的 Shell。
向元数据服务器发出请求:
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
在 Google Cloud 控制台中,进入配额项目的 IAM Service Accounts Credentials API 页面:
检查流量变化情况。
清理
如需停止使用适用于 GKE 的工作负载身份联合,请撤消对 IAM 服务账号的访问权限并在集群上停用适用于 GKE 的工作负载身份联合。
撤消访问权限
如需撤消对主账号的访问权限,请移除您在将应用配置为使用适用于 GKE 的工作负载身份联合部分中创建的 IAM 允许政策。
例如,如需撤消 Artifact Registry 仓库的访问权限,请运行以下命令:
gcloud artifacts repositories remove-iam-policy-binding REPOSITORY_NAME \
--location=REPOSITORY_LOCATION \
--member='principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/serviceaccount/NAMESPACE/KSA_NAME' \
--role='roles/artifactregistry.reader' \
--all
停用适用于 GKE 的工作负载身份联合
您只能在 Standard 集群上停用适用于 GKE 的工作负载身份联合。
gcloud
-
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
在每个节点池上停用适用于 GKE 的工作负载身份联合:
gcloud container node-pools update NODEPOOL_NAME \ --cluster=CLUSTER_NAME \ --workload-metadata=GCE_METADATA
对集群中的每个节点池重复此命令。
在集群中停用适用于 GKE 的工作负载身份联合:
gcloud container clusters update CLUSTER_NAME \ --disable-workload-identity
控制台
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
在集群列表中,点击您要修改的集群的名称。
点击节点标签页。
如需在每个节点池上停用适用于 GKE 的工作负载身份联合,请对节点池部分中的每个节点池执行以下操作:
- 点击要修改的节点池的名称。
- 在节点池详情页面中,点击 修改。
- 在修改节点池页面的安全部分中,清除启用 GKE 元数据服务器复选框。
- 点击保存。
如需为集群停用适用于 GKE 的工作负载身份联合,请执行以下操作:
- 点击详情标签页。
- 在安全部分中,点击 Workload Identity 旁边的 修改。
- 在修改 Workload Identity 对话框中,清除启用 Workload Identity 复选框。
- 点击保存更改。
在组织中停用适用于 GKE 的工作负载身份联合
从安全角度来看,适用于 GKE 的工作负载身份联合支持 GKE 声明可向 Google Cloud 资源进行身份验证并获得 Google Cloud 资源授权的 Kubernetes 服务账号身份。如果您是已采取措施(例如禁止创建服务账号或禁止创建服务账号密钥)将工作负载与 Google Cloud 资源隔离的管理员,可能还需要为组织停用适用于 GKE 的工作负载身份联合。
请参阅这些说明以了解如何为组织停用适用于 GKE 的工作负载身份联合。
问题排查
如需了解问题排查信息,请参阅排查适用于 GKE 的工作负载身份联合问题。
后续步骤
- 详细了解适用于 GKE 的工作负载身份联合。
- 阅读 GKE 安全概览。
- 了解如何保护集群元数据。
- 了解 IAM 服务账号。