本指南介绍了如何使用工作负载身份联合,让 Azure Azure Service (AKS)、Amazon Elastic Kubernetes Service 或自托管的 Kubernetes 集群上运行的工作负载可以向 Google Cloud 进行身份验证。
Kubernetes 可让您配置集群,以便工作负载可以从预计卷获取 Kubernetes 服务账号令牌。通过设置工作负载身份联合,您可以让工作负载使用这些 Kubernetes 服务账号令牌向 Google Cloud 进行身份验证。
如果您使用的是 GKE,请使用 Workload Identity,而不是配置工作负载身份联合。
须知事项
在配置工作负载身份联合之前,请确保您的 Kubernetes 集群符合以下条件:
AKS
请确保您的集群符合以下要求:
您已启用 OIDC 颁发者功能。
您必须启用此功能,以便工作负载身份联合可以访问集群的 OpenID Connect 元数据和 JSON Web 密钥集 (JWKS)。
EKS
您无需对 EKS 配置进行任何更改。
Kubernetes
请确保您的集群符合以下要求:
您正在运行 Kubernetes 1.20 或更高版本。
以前版本的 Kubernetes 使用与本文档中的说明不兼容的其他服务账号令牌格式。
您配置了
kube-apiserver
,使其支持ServiceAccount
令牌卷投影。
集群无需通过互联网访问。
配置工作负载身份联合
您只需为每个 Kubernetes 集群执行一次这些步骤。然后,您可以为多个工作负载以及多个 Google Cloud 项目使用相同的工作负载身份池和提供方。
如需开始配置工作负载身份联合,请执行以下操作:
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
我们建议您
使用专用项目管理工作负载身份池,并且提供商。
-
Make sure that billing is enabled for your Google Cloud project.
Enable the IAM, Resource Manager, Service Account Credentials, and Security Token Service APIs.
定义特性映射和条件
Kubernetes 服务账号令牌包含多个声明,包括:
sub
:包含服务账号的命名空间和名称,例如system:serviceaccount:NAMESPACE:KSA_NAME
,其中NAMESPACE
是服务账号的命名空间,KSA_NAME
是服务账号的名称。"kubernetes.io".namespace
:包含服务账号的命名空间。"kubernetes.io".serviceaccount.name
:服务账号的名称"kubernetes.io".pod.name
:包含 Pod 的名称。
如需在 Google Cloud 中使用 sub
作为主题标识符 (google.subject
),请使用以下映射:
google.subject=assertion.sub
您也可以视需要映射其他特性。然后,您可以在授予对资源的访问权限时引用这些特性。 例如:
google.subject=assertion.sub, attribute.namespace=assertion['kubernetes.io']['namespace'], attribute.service_account_name=assertion['kubernetes.io']['serviceaccount']['name'], attribute.pod=assertion['kubernetes.io']['pod']['name']
您可以视需要定义特性条件。特性条件是可以检查断言特性和目标特性的 CEL 表达式。如果给定凭据的特性条件评估结果为 true
,则接受凭据。否则,凭据会被拒绝。
您可以使用特性条件来限制哪些 Kubernetes 服务账号可以使用工作负载身份联合来获取短期 Google Cloud 令牌。例如,以下条件限制从 backend
和 monitoring
命名空间访问 Kubernetes 服务账号:
assertion['kubernetes.io']['namespace'] in ['backend', 'monitoring']
创建工作负载身份池和提供方
所需的角色
如需获得配置工作负载身份联合所需的权限,请让管理员向您授予项目的以下 IAM 角色:
-
Workload Identity Pool Admin (
roles/iam.workloadIdentityPoolAdmin
) -
Service Account Admin (
roles/iam.serviceAccountAdmin
)
如需详细了解如何授予角色,请参阅管理访问权限。
此外,IAM Owner (roles/owner
) 基本角色还具有配置身份联合的权限。您不应在生产环境中授予基本角色,但可以在开发或测试环境中授予这些角色。
如需创建工作负载身份池和提供商,请执行以下操作:
AKS
确定 AKS 集群的颁发者网址:
az aks show -n NAME -g RESOURCE_GROUP --query "oidcIssuerProfile.issuerUrl" -otsv
替换以下内容:
NAME
:集群的名称。RESOURCE_GROUP
:集群的资源组
该命令会输出颁发者网址。执行以下步骤之一时需要颁发者网址。
如果该命令未返回颁发者网址,请验证您是否已启用 OIDC 颁发者功能。
创建新的工作负载身份池:
gcloud iam workload-identity-pools create POOL_ID \ --location="global" \ --description="DESCRIPTION" \ --display-name="DISPLAY_NAME"
替换以下内容:
POOL_ID
:池的唯一 ID。DISPLAY_NAME
:池的名称。DESCRIPTION
:您选择的池的说明。当您授予对池身份的访问权限时,系统会显示此说明。
将 AKS 集群添加为工作负载身份池提供商:
gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \ --location="global" \ --workload-identity-pool="POOL_ID" \ --issuer-uri="ISSUER" \ --attribute-mapping="MAPPINGS" \ --attribute-condition="CONDITIONS"
替换以下内容:
EKS
确定 EKS 集群的颁发者网址:
aws eks describe-cluster --name NAME --query "cluster.identity.oidc.issuer" --output text
将
NAME
替换为您的集群的名称。该命令会输出颁发者网址。执行以下步骤之一时需要颁发者网址。
创建新的工作负载身份池:
gcloud iam workload-identity-pools create POOL_ID \ --location="global" \ --description="DESCRIPTION" \ --display-name="DISPLAY_NAME"
替换以下内容:
POOL_ID
:池的唯一 ID。DISPLAY_NAME
:池的名称。DESCRIPTION
:您选择的池的说明。当您授予对池身份的访问权限时,系统会显示此说明。
将 EKS 集群添加为工作负载身份池提供方:
gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \ --location="global" \ --workload-identity-pool="POOL_ID" \ --issuer-uri="ISSUER" \ --attribute-mapping="MAPPINGS" \ --attribute-condition="CONDITIONS"
替换以下内容:
Kubernetes
连接到您的 Kubernetes 集群并使用
kubectl
确定您集群的颁发者网址:kubectl get --raw /.well-known/openid-configuration | jq -r .issuer
执行以下步骤之一时需要颁发者网址。
下载集群的 JSON Web 密钥集 (JWKS):
kubectl get --raw /openid/v1/jwks > cluster-jwks.json
在以下某个步骤中,您需要上传 JWKS,以便工作负载身份联合能够验证集群颁发的 Kubernetes 服务账号令牌的真实性。
创建新的工作负载身份池:
gcloud iam workload-identity-pools create POOL_ID \ --location="global" \ --description="DESCRIPTION" \ --display-name="DISPLAY_NAME"
替换以下内容:
POOL_ID
:池的唯一 ID。DISPLAY_NAME
:池的名称。DESCRIPTION
:您选择的池的说明。当您授予对池身份的访问权限时,系统会显示此说明。
将 Kubernetes 集群添加为工作负载身份池提供商,并上传集群的 JWKS:
gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \ --location="global" \ --workload-identity-pool="POOL_ID" \ --issuer-uri="ISSUER" \ --attribute-mapping="MAPPINGS" \ --attribute-condition="CONDITIONS" \ --jwk-json-path="cluster-jwks.json"
替换以下内容:
对 Kubernetes 工作负载进行身份验证
本部分介绍如何配置 Kubernetes 工作负载以使用工作负载身份联合。
您必须对需要访问 Google Cloud 的每个 Kubernetes 工作负载执行一次这些步骤。
创建一对服务账号
要让 Kubernetes 工作负载向 Google Cloud 进行身份验证,您需要一对服务账号:
- 您附加到 Kubernetes Pod 的 Kubernetes 服务账号。
- Kubernetes 工作负载可以使用其关联的 Kubernetes 服务账号来模拟的 IAM 服务账号。
如需创建服务账号,请执行以下操作:
创建一个表示工作负载的 IAM 服务账号。
该服务账号不需要与工作负载身份池位于同一项目中。
gcloud iam service-accounts create SA_NAME
替换以下内容:
SA_NAME
:服务账号的名称。
创建 Kubernetes 服务账号:
kubectl create serviceaccount KSA_NAME --namespace NAMESPACE
替换以下内容:
KSA_NAME
:服务账号的名称。NAMESPACE
:要在其中创建服务账号的命名空间。
将 Workload Identity User 角色 (
roles/iam.workloadIdentityUser
) 授予 Kubernetes 服务账号的外部身份:gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \ --role=roles/iam.workloadIdentityUser \ --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT"
替换以下内容:
部署 Kubernetes 工作负载
现在,您可以部署一个 Kubernetes 工作负载,并让它使用服务账号对:
创建凭据配置文件:
gcloud iam workload-identity-pools create-cred-config \ projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \ --service-account=SERVICE_ACCOUNT_EMAIL \ --credential-source-file=/var/run/service-account/token \ --credential-source-type=text \ --output-file=credential-configuration.json
替换以下内容:
PROJECT_NUMBER
:包含工作负载身份池的项目的项目编号POOL_ID
:工作负载身份池的 IDPROVIDER_ID
:工作负载身份池提供方的 IDSERVICE_ACCOUNT_EMAIL
:服务账号的电子邮件地址
凭据配置文件允许 Cloud 客户端库、gcloud CLI 和 Terraform 确定以下内容:
- 从何处获取外部凭据
- 要使用的工作负载身份池和提供商
- 需要模拟的服务账号
将凭据配置文件作为 ConfigMap 导入:
kubectl create configmap CONFIGMAP_NAME \ --from-file credential-configuration.json \ --namespace NAMESPACE
替换以下内容:
CONFIGMAP_NAME
:ConfigMap 的名称。NAMESPACE
:要在其中创建 ConfigMap 的命名空间。
部署工作负载并使其使用 Kubernetes 服务账号和 ConfigMap。
创建清单并按如下方式配置:
- 装载投影的令牌卷,以便工作负载可以从本地文件获取 Kubernetes 服务账号令牌。配置卷,以便 Kubernetes 服务账号令牌使用工作负载身份联合池提供方所需的目标设备。
- 装载包含凭据配置文件的 ConfigMap,以便工作负载可以访问使用工作负载身份联合的必要配置。
- 添加包含凭据配置文件的路径的环境变量
GOOGLE_APPLICATION_CREDENTIALS
,以便工作负载可以找到该文件。
以下是一个示例清单,它使用 Kubernetes 服务账号和 ConfigMap 让 Google Cloud CLI 向 Google Cloud 进行身份验证:
apiVersion: v1 kind: Pod metadata: name: example namespace: NAMESPACE spec: containers: - name: example image: google/cloud-sdk:alpine command: ["/bin/sh", "-c", "gcloud auth login --cred-file $GOOGLE_APPLICATION_CREDENTIALS && gcloud auth list && sleep 600"] volumeMounts: - name: token mountPath: "/var/run/service-account" readOnly: true - name: workload-identity-credential-configuration mountPath: "/etc/workload-identity" readOnly: true env: - name: GOOGLE_APPLICATION_CREDENTIALS value: "/etc/workload-identity/credential-configuration.json" serviceAccountName: KSA_NAME volumes: - name: token projected: sources: - serviceAccountToken: audience: https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID expirationSeconds: 3600 path: token - name: workload-identity-credential-configuration configMap: name: CONFIGMAP_NAME
您可以按照相同的方法,让使用以下客户端库之一的工具和工作负载自动查找凭据:
C++
从 v2.6.0 版开始,C++ 版 Google Cloud 客户端库支持工作负载身份联合。如需使用工作负载身份联合,您必须使用 gRPC 1.36.0 版或更高版本构建客户端库。
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 版客户端库使用 7.0.2 版或更高版本的
google-auth-library
软件包,则该客户端库支持工作负载身份联合。如要查看客户端库使用的软件包版本,请在应用目录中运行以下命令:
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
软件包用户指南。gcloud
如需使用工作负载身份联合进行身份验证,请使用
gcloud auth login
命令:gcloud auth login --cred-file=FILEPATH.json
将
FILEPATH
替换为凭据配置文件的文件路径。版本 363.0.0 及更高版本的 gcloud CLI 支持 gcloud CLI 中的工作负载身份联合。
Terraform
如果您使用 3.61.0 版或更高版本,则 Google Cloud 提供方支持工作负载身份联合:
terraform { required_providers { google = { source = "hashicorp/google" version = "~> 3.61.0" } } }
gsutil
如需使用工作负载身份联合进行身份验证,请使用以下方法之一:
将 gsutil 与 gcloud 结合使用时,请按正常方式登录:
gcloud auth login --cred-file=FILEPATH.json
将 gsutil 用作独立的命令行应用时,请修改 .boto 文件以包含以下部分:
[Credentials] gs_external_account_file = FILEPATH
在这两种情况下,请将
FILEPATH
替换为凭据配置文件的文件路径。379.0.0 版及更高版本的 gcloud CLI 支持 gsutil 中的工作负载身份联合。
bq
如需使用工作负载身份联合进行身份验证,请使用
gcloud auth login
命令,如下所示:gcloud auth login --cred-file=FILEPATH.json
将
FILEPATH
替换为凭据配置文件的文件路径。390.0.0 版及更高版本的 gcloud CLI 支持 bq 中的工作负载身份联合。
(可选)通过运行以下命令验证身份验证是否正常运行:
kubectl exec example --namespace NAMESPACE -- gcloud auth print-access-token
后续步骤
- 详细了解工作负载身份联合。
- 了解使用工作负载身份联合的最佳实践。
- 了解如何管理工作负载身份池和提供方。