从 GKE 工作负载向 Google Cloud API 进行身份验证


本文档介绍如何使用适用于 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 的工作负载身份联合

在 Autopilot 中,适用于 GKE 的工作负载身份联合默认启用。跳到将应用配置为使用适用于 GKE 的工作负载身份联合部分。

在 Standard 中,您可以使用 Google Cloud CLI 或 Google Cloud 控制台在集群和节点池上启用适用于 GKE 的工作负载身份联合。必须先在集群级层启用适用于 GKE 的工作负载身份联合,然后才能在节点池上启用适用于 GKE 的工作负载身份联合。

创建新集群

您可以使用 gcloud CLI 或 Google Cloud 控制台在新的标准集群上启用适用于 GKE 的工作负载身份联合。

gcloud

  1. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

    Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。

  2. 如需在新集群上启用适用于 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 的工作负载身份联合,请执行以下操作:

  1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 点击 创建

  3. 创建集群对话框中,对于 GKE Standard,点击配置

  4. 在导航菜单的集群部分中,点击安全

  5. 选中启用 Workload Identity 复选框。

  6. 继续配置该集群,然后点击创建

更新现有集群

您可以使用 gcloud CLI 或 Google Cloud 控制台在现有标准集群上启用适用于 GKE 的工作负载身份联合。现有节点池不受影响,但集群中的任何新节点池都使用适用于 GKE 的工作负载身份联合。

gcloud

  1. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

    Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。

  2. 如需在现有集群上启用适用于 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 的工作负载身份联合,请执行以下操作:

  1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 在集群列表中,点击您要修改的集群的名称。

  3. 在集群详情页面的安全部分中,点击 修改 Workload Identity

  4. 修改 Workload Identity 对话框中,选中启用 Workload Identity 复选框。

  5. 点击保存更改

将现有工作负载迁移到适用于 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

  1. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

    Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。

  2. 如需修改现有节点池以使用适用于 GKE 的工作负载身份联合,请运行以下命令:

    gcloud container node-pools update NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --region=COMPUTE_REGION \
        --workload-metadata=GKE_METADATA
    

    如果集群启用了适用于 GKE 的工作负载身份联合,您可以通过明确指定 --workload-metadata=GCE_METADATA 在特定节点池中选择性地停用它。如需了解详情,请参阅保护集群元数据

控制台

如需修改现有节点池以使用适用于 GKE 的工作负载身份联合,请执行以下步骤:

  1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 在集群列表中,点击您要修改的集群的名称。

  3. 点击节点标签页。

  4. 节点池部分中,点击要修改的节点池的名称。

  5. 节点池详情页面中,点击 修改

  6. 修改节点池页面的安全部分中,选中启用 GKE 元数据服务器复选框。

  7. 点击保存

将应用配置为使用适用于 GKE 的工作负载身份联合

如需让您的 GKE 应用使用适用于 GKE 的工作负载身份联合向 Google Cloud API 进行身份验证,您可以为特定 API 创建 IAM 政策。这些政策中的主账号是与工作负载、命名空间或 ServiceAccount 相对应的 IAM 主账号标识符

配置授权和主账号

  1. 获取集群的凭据:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=LOCATION
    

    替换以下内容:

    • CLUSTER_NAME:启用了适用于 GKE 的工作负载身份联合的集群的名称。
    • LOCATION:您的集群的位置。
  2. 创建用于 Kubernetes 服务账号的命名空间。您还可以使用 default 命名空间或任何现有命名空间。

    kubectl create namespace NAMESPACE
    
  3. 为您的应用创建 Kubernetes 服务账号。您还可以在任何命名空间中使用任何现有的 Kubernetes ServiceAccount。如果您未为工作负载分配 ServiceAccount,则 Kubernetes 会在命名空间中分配 default ServiceAccount。

    kubectl create serviceaccount KSA_NAME \
        --namespace NAMESPACE
    

    替换以下内容:

    • KSA_NAME:新 Kubernetes ServiceAccount 的名称。
    • NAMESPACE:ServiceAccount 的 Kubernetes 命名空间的名称。
  4. 创建引用 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 授予对该存储桶的查看权限。然后,您可以部署工作负载并测试容器是否可以列出项目中的集群。

  1. 创建空的 Cloud Storage 存储桶:

    gcloud storage buckets create gs://BUCKET
    

    BUCKET 替换为新存储桶的名称。

  2. 向您创建的 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 的名称。
  3. 将以下清单保存为 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
    
  4. 仅在 Standard 集群中,将以下内容添加到 template.spec 字段,以将 Pod 放置在使用适用于 GKE 的工作负载身份联合的节点池上。

    在 Autopilot 集群中跳过此步骤,这会拒绝此 nodeSelector,因为每个节点都使用适用于 GKE 的工作负载身份联合。

    spec:
      nodeSelector:
        iam.gke.io/gke-metadata-server-enabled: "true"
    
  5. 将配置应用到您的集群:

    kubectl apply -f test-app.yaml
    
  6. 等待 Pod 准备就绪。如需检查 Pod 的状态,请运行以下命令:

    kubectl get pods --namespace=NAMESPACE
    

    Pod 准备就绪后,输出类似于以下内容:

    NAME       READY   STATUS    RESTARTS   AGE
    test-pod   1/1     Running   0          5m27s
    
  7. 在 Pod 中打开 shell 会话:

    kubectl exec -it pods/test-pod --namespace=NAMESPACE -- /bin/bash
    
  8. 获取存储桶中的对象列表:

    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 的访问权限:

  1. 创建 Kubernetes 命名空间:

    kubectl create namespace NAMESPACE
    
  2. 创建 Kubernetes ServiceAccount:

    kubectl create serviceaccount KSA_NAME \
        --namespace=NAMESPACE
    
  3. 创建 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,请参阅了解服务账号

  4. 向您的 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

  5. 创建一个 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]"
    
  6. 为 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 中的 GenerateAccessTokenGenerateIdToken 方法时,视需要将 Kubernetes 服务账号配置为使用其他 Google Cloud 项目中的配额。这样,您就无需完全使用主项目中的配额,而是可以为集群中的这些服务使用其他项目中的配额。

如需配置适用于 GKE 的工作负载身份联合的配额项目,请执行以下操作:

  1. 将配额项目的 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。

  2. 使用配额项目为 Kubernetes 服务账号添加注释:

    kubectl annotate serviceaccount KSA_NAME \
        --namespace NAMESPACE \
        iam.gke.io/credential-quota-project=QUOTA_PROJECT_ID
    

如需验证配置是否生效,请执行以下操作:

  1. 创建一个 pod 并启动一个 shell 会话。请参阅 Kubernetes 文档以获取正在运行的容器的 Shell

  2. 向元数据服务器发出请求:

    curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
    
  3. 在 Google Cloud 控制台中,进入配额项目的 IAM Service Accounts Credentials API 页面:

    进入“API”

  4. 检查流量变化情况。

清理

如需停止使用适用于 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

  1. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

    Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。

  2. 在每个节点池上停用适用于 GKE 的工作负载身份联合:

    gcloud container node-pools update NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --workload-metadata=GCE_METADATA
    

    对集群中的每个节点池重复此命令。

  3. 在集群中停用适用于 GKE 的工作负载身份联合:

    gcloud container clusters update CLUSTER_NAME \
        --disable-workload-identity
    

控制台

  1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 在集群列表中,点击您要修改的集群的名称。

  3. 点击节点标签页。

  4. 如需在每个节点池上停用适用于 GKE 的工作负载身份联合,请对节点池部分中的每个节点池执行以下操作:

    1. 点击要修改的节点池的名称。
    2. 节点池详情页面中,点击 修改
    3. 修改节点池页面的安全部分中,清除启用 GKE 元数据服务器复选框。
    4. 点击保存
  5. 如需为集群停用适用于 GKE 的工作负载身份联合,请执行以下操作:

    1. 点击详情标签页。
    2. 安全部分中,点击 Workload Identity 旁边的 修改
    3. 修改 Workload Identity 对话框中,清除启用 Workload Identity 复选框。
    4. 点击保存更改

在组织中停用适用于 GKE 的工作负载身份联合

从安全角度来看,适用于 GKE 的工作负载身份联合支持 GKE 声明可向 Google Cloud 资源进行身份验证并获得 Google Cloud 资源授权的 Kubernetes 服务账号身份。如果您是已采取措施(例如禁止创建服务账号禁止创建服务账号密钥)将工作负载与 Google Cloud 资源隔离的管理员,可能还需要为组织停用适用于 GKE 的工作负载身份联合。

请参阅这些说明以了解如何为组织停用适用于 GKE 的工作负载身份联合

问题排查

如需了解问题排查信息,请参阅排查适用于 GKE 的工作负载身份联合问题

后续步骤