使用舰队 Workload Identity

应用通常会在连接到其他服务时进行身份验证(提供可验证的身份)。例如,您的应用必须进行身份验证才能使用 Google Cloud API(例如,Compute Engine 或 AI Platform API)。本页面介绍如何使用舰队 Workload Identity 这一系统推荐的最简单的方法,来对队列中托管的应用工作负载进行身份验证,以便使其能够使用 Google Cloud API 和服务。

什么是舰队 Workload Identity?

舰队 Workload Identity 扩展了 GKE Workload Identity 中提供的功能,可让您集群中的工作负载向 Google 进行身份验证,而无需下载、手动轮替和笼统管理 Google Cloud 服务账号密钥。相反,工作负载会使用集群生成的短期令牌进行身份验证。所有已启用 GKE Workload Identity 的集群在发出 ID 时均使用其项目的 Workload Identity 池,这可让 Identity and Access Management 信任和了解 Kubernetes 服务账号凭据。您可以在使用 Workload Identity 中详细了解 GKE Workload Identity。

借助队列,已注册的集群可以获得使用队列 Workload Identity 的额外优势。如果已注册的集群启用了舰队成员资格中的 Workload Identity,则可以使用舰队范围的舰队工作负载身份池,从而更轻松地在整个舰队和多个项目中设置 Google API 和其他服务的身份验证。Connect Agent 还可以在某些集群类型上使用舰队 Workload Identity 作为舰队成员资格的一部分向 Google 进行身份验证,并且需要使用某些能够跨项目运行的 GKE Enterprise 功能,例如 Anthos Service Mesh。

运作方式

队列使用工作负载身份联合为各应用提供不同的联合身份来进行身份验证,以便使其能够使用 Google Cloud 和您开发的其他服务。队列中运行的应用将按以下格式来接收联合工作负载身份

serviceAccount:FLEET_PROJECT_ID.svc.id.goog[K8S_NAMESPACE/KSA_NAME]

其中:

  • FLEET_PROJECT_ID.svc.id.goog 是队列的工作负载身份池的简写形式。每个队列都只有一个固定的工作负载身份池,它是由系统自动为您创建的。
  • K8S_NAMESPACE 是在其中定义了 Kubernetes 服务账号的 Kubernetes 命名空间。
  • KSA_NAME 是与应用关联的 Kubernetes 服务账号的名称。

一个队列中托管的所有应用都将共享同一工作负载身份池,从而为所有应用提供一个联合身份,而无需单独管理每个应用的托管位置。这样,即使是在不同的 Google Cloud 项目之间或在不同的云环境之间部署应用,也可以一次性地为队列中的应用提供对某项资源(例如,Google Cloud API)的访问权限,而无需逐个集群单独提供。与其他支持队列的功能一样,此项功能依赖于队列的相同性原则,即不同集群中的同名 Kubernetes 对象将被视为同一项。比如,如果您有一个应用,其后端部署在同一队列中的多个集群上,并且需要向 Google API 进行身份验证,那么您便可以轻松地配置该应用,使“backend”命名空间内的所有服务均可以访问该 API。如需详细了解舰队如何使用相同性(包括身份相同性),请参阅舰队的工作原理

Google Cloud 外部的集群还可以使用 Workload Identity 来为 Connect Agent 提供身份以向 Google 进行身份验证。如需详细了解哪些集群类型使用舰队 Workload Identity,请参阅下面的集群设置部分。

前期准备

  • 确保您已安装以下命令行工具:

    如果您使用 Cloud Shell 作为与 Google Cloud 交互的 Shell 环境,则系统会为您安装这些工具。

  • 确保您已初始化用于您项目的 gcloud CLI。

集群设置

在队列中的应用能够接收工作负载身份之前,必须先将运行这些应用的集群注册到队列并将其正确配置为使用队列 Workload Identity。如何执行此操作取决于集群类型。在您创建 Google Cloud 外部的大多数 GKE 集群时,其会自动注册到项目舰队。Google Cloud 上的 GKE 集群和关联的集群必须手动注册。

如需详细了解集群配置,请参阅每种集群类型的文档。

GKE

  1. 在 Google Kubernetes Engine 集群上启用 GKE Workload Identity(如果尚未启用)。
  2. 按照说明使用 Workload Identity 注册集群

Google Cloud 外部的 GKE 集群

GKE on VMwareGKE on Bare Metal多云 GKE 集群(在 AWS 和 Azure 上)会在创建集群时自动注册到项目舰队。自 GKE Enterprise 1.8 起,所有这些集群类型都会在注册时自动启用舰队 Workload Identity。现有的已注册集群在升级到 GKE Enterprise 1.8 或更高版本后会更新为使用 Workload Identity。

关联集群

使用 GKE Multi-Cloud API 注册的 EKS 和 AKS 关联集群默认会在启用了舰队 Workload Identity 的情况下注册。其他关联集群如果满足必要的要求,则可以在启用了舰队 Workload Identity 的情况下注册。按照注册集群中针对您的集群类型的说明进行操作。

使用舰队 Workload Identity

注册集群后,部署在集群上的工作负载便可以使用队列工作负载身份池中的工作负载身份。本部分介绍如何使用工作负载身份来模拟 Google Cloud 服务账号,以便您的工作负载可以访问 Google Cloud API。充当服务账号是联合身份的一种常见用例,因为这样便可让您的工作负载向该服务账号有权访问的任何 Google Cloud API 进行身份验证,并且无需单独管理每个工作负载的服务账号密钥,从而消除了这些额外的维护和安全负担。

模拟服务账号

本部分介绍如何通过在 ConfigMap 中提供应用默认凭据文件来配置应用的联合工作负载身份以使其模拟服务账号,包括创建和配置具有相关权限的服务账号。

该示例使用以下占位值:

  • WORKLOAD_IDENTITY_POOL 是与您的队列关联的工作负载身份池。如上所示,WORKLOAD_IDENTITY_POOL 的值为 FLEET_PROJECT_ID.svc.id.goog
  • IDENTITY_PROVIDER 是与您的 Kubernetes 集群关联的身份提供商的名称。
  • K8S_NAMESPACE 是在其中定义了 Kubernetes 服务账号的 Kubernetes 命名空间。
  • KSA_NAME 是与应用关联的 Kubernetes 服务账号的名称。
  • GSA_NAME 是您的应用将充当的 Google 服务账号的名称。
  • GSA_PROJECT_ID 是在其中定义了 Google 服务账号的项目 ID。

如需配置队列工作负载身份来模拟服务账号,请执行以下操作:

  1. 按照上文集群设置部分中的步骤操作,确保您的集群已注册到队列中。

  2. 使用以下命令检索集群的队列成员资格详情,以获取已注册集群的 WORKLOAD_IDENTITY_POOLIDENTITY_PROVIDER 值。将 MEMBERSHIP 替换为集群在队列中的唯一成员资格名称:

    gcloud container fleet memberships describe MEMBERSHIP
    

    描述成员资格的输出如下所示(为清楚起见,省略了某些字段):

    authority:
     identityProvider: IDENTITY_PROVIDER
     workloadIdentityPool: WORKLOAD_IDENTITY_POOL
    name: projects/FLEET_PROJECT_ID/locations/global/memberships/MEMBERSHIP
    
  3. 创建一个 Google Cloud 服务账号,以便您的应用在向 Google 进行身份验证时可以模拟该账号(如果您还没有该账号):

    gcloud iam service-accounts create GSA_NAME --project=GSA_PROJECT_ID
    

    该服务账号不需要在队列宿主项目中。您可以在组织中使用任何 Google Cloud 服务账号。如需详细了解服务账号及其工作原理,请参阅服务账号

  4. 通过添加必要的 IAM 政策绑定,确保您已向该服务账号授予访问 Google Cloud API 所需的所有权限。您可以使用 gcloud iam service-accounts add-iam-policy-binding 或您想要使用的其他方法来执行此操作。如需在每项服务的文档中查找使用 Google Cloud API 所需的权限,请参阅了解角色中预定义角色及其必要权限的完整列表。

  5. 通过创建 IAM 政策绑定,授权应用的工作负载身份模拟服务账号,如下所示。此绑定允许应用的联合工作负载身份充当 Google Cloud 服务账号。

    gcloud iam service-accounts add-iam-policy-binding \
      GSA_NAME@GSA_PROJECT_ID.iam.gserviceaccount.com \
      --role=roles/iam.workloadIdentityUser \
      --member="serviceAccount:WORKLOAD_IDENTITY_POOL[K8S_NAMESPACE/KSA_NAME]"
    

    --member 字段是应用的联合工作负载身份的 IAM 表示。

  6. 创建包含工作负载的应用默认凭据文件的 ConfigMap。此文件将指示编译到工作负载中的客户端库如何向 Google 进行身份验证。应用默认凭据文件包含相关工作负载身份池和服务账号信息,以及将在下一步中装载到容器的文件系统中的投影令牌的路径。GSA_NAME@GSA_PROJECT_ID.iam.gserviceaccount.com 是要模拟的服务账号的电子邮件地址。

    此配置本身不会授予模拟服务账号的权限。如果 IAM 绑定也不存在,则 Pod 将无法使用服务账号。

    kind: ConfigMap
    apiVersion: v1
    metadata:
      namespace: K8S_NAMESPACE
      name: my-cloudsdk-config
    data:
      config: |
        {
          "type": "external_account",
          "audience": "identitynamespace:WORKLOAD_IDENTITY_POOL:IDENTITY_PROVIDER",
          "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/GSA_NAME@GSA_PROJECT_ID.iam.gserviceaccount.com:generateAccessToken",
          "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"
          }
        }
    
  7. 请按照以下示例配置工作负载。请注意,上一步中的 ConfigMap 将作为 google-application-credentials.json/var/run/secrets/tokens/gcp-ksa 中的投影的服务账号令牌文件一起装载到容器的文件系统中。投影令牌由 Kubernetes 颁发,用来表示集群内部的工作负载身份。Cloud 客户端库会自动与 Google 交换这些令牌,以获取可向 Google API 进行身份验证的令牌。投影令牌的 audience 字段必须设置为 WORKLOAD_IDENTITY_POOL 的值。

    kind: Namespace
    apiVersion: v1
    metadata:
      name:  K8S_NAMESPACE
    ---
    kind: ServiceAccount
    apiVersion: v1
    metadata:
      namespace:  K8S_NAMESPACE
      name: KSA_NAME
    automountServiceAccountToken: false
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
      namespace:  K8S_NAMESPACE
    spec:
      serviceAccountName: KSA_NAME
      containers:
      - name: my-container
        image: my-image
        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: WORKLOAD_IDENTITY_POOL
              expirationSeconds: 172800
          - configMap:
              name: my-cloudsdk-config
              optional: false
              items:
                - key: "config"
                  path: "google-application-credentials.json"
    
    

通过代码进行身份验证

当您使用 Cloud 客户端库通过代码访问 Google 服务时,它们将自动向 Google Cloud 进行身份验证。如需在应用中使用上述设置,您必须使用支持工作负载身份联合的 Cloud 客户端库。下面列出了要求的最低 Cloud 客户端库版本,以及有关如何检查当前版本的说明:

C++

大多数 C++ 版 Google Cloud 客户端库 通过使用 ChannelCredentials 对象支持身份联合,该对象是通过调用 grpc::GoogleDefaultCredentials() 创建的。如要初始化此凭据,必须使用 gRPC 的 1.36.0 版本或更高版本构建客户端库。

C++ 版 Cloud Storage 客户端库使用的是 REST API,而不是 gRPC,因此不支持身份联合。

Go

如果 Go 客户端库使用 golang.org/x/oauth2 模块的 v0.0.0-20210218202405-ba52d332ba99 版本或更高版本,则客户端库支持身份联合。

如要查看客户端库使用的模块版本,请运行以下命令:

cd $GOPATH/src/cloud.google.com/go
go list -m golang.org/x/oauth2

Java

如果 Java 客户端库使用 com.google.auth:google-auth-library-oauth2-http 工件的 0.24.0 版或更高版本,则客户端支持身份联合。

如需查看该客户端库使用的工件版本,请在应用目录中运行以下 Maven 命令:

mvn dependency:list -DincludeArtifactIds=google-auth-library-oauth2-http

Node.js

如果 Node.js 客户端库使用 google-auth-library 软件包的 7.0.2 版本或更高版本,则客户端支持身份联合。

如要查看客户端库使用的软件包版本,请在应用目录中运行以下命令:

npm list google-auth-library

创建 GoogleAuth 对象时,您可以指定项目 ID,也可以允许 GoogleAuth 自动查找项目 ID。如要自动查找项目 ID,配置文件中的服务账号必须具有项目的 Browser 角色 (roles/browser) 或具有同等权限的角色。如需了解详情,请参阅 google-auth-library 软件包的 README

Python

如果 Python 客户端库使用 google-auth 软件包的 1.27.0 版本或更高版本,则客户端支持身份联合。

如要检查客户端库使用的软件包版本,请在已安装该软件包的环境中运行以下命令:

pip show google-auth

如要为身份验证客户端指定项目 ID,您可以设置 GOOGLE_CLOUD_PROJECT 环境变量,也可以允许客户端自动查找项目 ID。如要自动查找项目 ID,配置文件中的服务账号必须具有项目的 Browser 角色 (roles/browser) 或具有同等权限的角色。如需了解详情,请参阅 google-auth 软件包用户指南