如何在启用了工作负载身份的 GKE 上将 Cloud Trace 与 Nodejs 结合使用?

问题描述

我正在尝试在启用了工作负载身份的 GKE 集群上设置 Cloud Trace。我的 pod 使用具有 Cloud Trace Agent 角色的服务帐户。 (我还尝试赋予它 Owner 角色,以排除权限问题,但这并没有改变错误。)

我遵循了 Node.js quickstart,它表示将以下代码添加到我的代码中:

require('@google-cloud/trace-agent').start();

当我尝试添加跟踪时,出现以下错误

@google-cloud/trace-agent DEBUG TraceWriter#publish:将跟踪发布到 cloudtrace.googleapis.com 时收到错误错误:无法刷新访问令牌:尝试检索访问令牌时返回禁止错误Compute Engine 内置服务帐号。这可能是因为 Compute Engine 实例没有指定正确的权限范围:Could not refresh access token: Unsuccessful response status code。请求失败,状态码为 403

(如何)我如何配置库以在这种情况下工作?

解决方法

为了回答您对上述评论的问题:如果我错了,请纠正我 - 工作负载身份是一个集群功能,未连接到命名空间?

看到您通过配置 KSA/K8s NamespaceGCP SA 之间的绑定解决了问题,我将添加一个响应以添加更多我认为可以帮助澄清这一点的上下文。

是的,您说得对,工作负载身份是一项 GKE 集群功能,可让您将来自 K8s(Kubernetes 服务帐户 (KSA))的身份与 GCP 身份(Google 服务帐户 (GSA))绑定,以便对您的工作负载进行身份验证具有特定的 GCP 身份和足够的权限来访问某些 API(取决于您的 GCP 服务帐户拥有的权限)。 k8s namespacesKSA 在这里起着关键作用,因为 KSA 是命名空间资源。

因此,为了正确验证您的工作负载(容器)和 GCP 服务帐户,您需要在配置的 k8s Namespace 和配置的 KSA 中创建它们,如本 doc

如果您在不同的 k8s Namespace(意味着使用不同的 KSA)上创建您的工作负载,您将无法为您的工作负载获得经过身份验证的身份,相反,您的工作负载将使用 { {1}},即:Workload Identity Pool/Workload Identity Namespace。这意味着当您创建安装了 GCP SDK 的容器并运行 PROJECT_ID.svc.id.goog 时,您将获得 glcoud auth list 作为经过身份验证的身份,这是一个 IAM 对象,但不是在 IAM 中具有权限的身份。因此,您的工作负载将缺乏权限。

然后,您需要在配置的命名空间和配置的服务帐户中创建容器,以便能够在容器中拥有正确的身份并拥有 IAM 权限。

我假设上述(缺乏许可和缺乏实际 IAM 身份的身份验证)就是这里发生的事情,正如您在回复中提到的,您只是在 PROJECT_ID.svc.id.goog 和 { 之间添加了所需的绑定{1}},表示您的容器缺少具有实际 IAM 权限的身份。

为了明确这一点,Workload Identity 允许您使用不同于 GKE 节点上的服务帐号对您的工作负载进行身份验证。如果您的应用在具有默认服务帐号的 GCP 环境中运行,则您的应用可以检索服务帐号凭据以调用 GCP API。此类环境包括 Compute Engine、Google Kubernetes Engine、App Engine、Cloud Run 和 Cloud Functions,here

上面的评论我想说的是,即使您不使用 Workload Identity,您的容器也会在它们在 GKE 上运行时进行身份验证,默认情况下使用服务帐户,并且该服务帐户是从节点继承的您的容器、默认服务帐户(计算服务帐户)及其范围足以从容器写入 GSA,这就是为什么您能够在禁用 Workload Identity 的 GKE 集群的情况下看到跟踪,因为默认服务帐户已在您的容器和节点上使用。

如果您在两种环境中都进行测试:
具有工作负载标识的 GKE 集群:您将能够使用正确的配置看到一个不同于默认服务帐户的服务帐户,用于对您的工作负载/容器进行身份验证。

禁用工作负载身份的 GKE 集群:您将能够看到您的节点使用的相同服务帐户(默认情况下,使用默认服务帐户)在您的容器上。

这些测试可以通过旋转您在响应中使用的相同容器来执行,即:

KSA

并运行 `glcoud auth list 以查看您在容器上进行身份验证的身份。

希望这能以某种方式有所帮助!

,

结果是我错误地配置了 IAM 服务帐户。

通过在我的命名空间中运行一个安装了 gcloud cli 的新 pod,我设法获得了一条更有意义的错误消息:

kubectl run -it \
  --image gcr.io/google.com/cloudsdktool/cloud-sdk \
  --serviceaccount $GKE_SERVICE_ACCOUNT test \
  -- bash

之后,只要运行任何 gcloud 命令都会给出一条错误消息,其中包含(强调我的):

无法生成访问令牌; IAM 返回 403 Forbidden:调用方没有权限 此错误可能是由于目标 IAM 服务帐户上缺少 IAM 策略绑定所致。

运行

gcloud iam service-accounts get-iam-policy $SERVICE_ACCOUNT

确实表明缺少与 Kubernetes 服务帐户的绑定。

手动添加修复了问题:

gcloud iam service-accounts add-iam-policy-binding \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:$PROJECT.svc.id.goog[$NAMESPACE/$GKE_SERVICE_ACCOUNT]" \
  $SERVICE_ACCOUNT

经过更多研究,根本问题是我使用 Config Connector 创建了我的服务帐户,但没有正确地 annotated the Kubernetes namespace 使用 Google Cloud 项目来部署资源:

kubectl annotate namespace "$NAMESPACE" cnrm.cloud.google.com/project-id="$PROJECT"

因此,Cloud Connector 无法添加 IAM 策略绑定。