问题描述
我正在尝试在启用了工作负载身份的 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 Namespace
和 GCP SA
之间的绑定解决了问题,我将添加一个响应以添加更多我认为可以帮助澄清这一点的上下文。
是的,您说得对,工作负载身份是一项 GKE 集群功能,可让您将来自 K8s(Kubernetes 服务帐户 (KSA))的身份与 GCP 身份(Google 服务帐户 (GSA))绑定,以便对您的工作负载进行身份验证具有特定的 GCP 身份和足够的权限来访问某些 API(取决于您的 GCP 服务帐户拥有的权限)。 k8s namespaces
和 KSA
在这里起着关键作用,因为 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 策略绑定。