将 docker 映像从 GCR 拉入 GKE "Failed to pull image .... 403 Forbidden" 时出错

Error pulling docker image from GCR into GKE "Failed to pull image .... 403 Forbidden"

背景:

我有一个 GKE 集群突然无法从 GCR 中提取我的 docker 图像;两者都在同一个 GCP 项目中。它几个月来一直运行良好,拉取图像没有问题,现在开始抛出错误而没有进行任何更改。

(注意:我通常是我团队中唯一访问 Google Cloud 的人,尽管我团队中的其他人完全有可能在没有意识到的情况下进行了更改/无意中进行了更改)。 =25=]

我看过一些关于此主题的其他帖子,但其他帖子中提供的解决方案没有帮助。其中两个帖子对我来说特别突出,因为它们都是在我的问题开始的同一天发布的~13/14 天前。是不是巧合谁知道..

This post has the same issue as me; unsure whether the posted comments helped them resolve, but it hasn't fixed for me. This post好像也是同样的问题,不过发帖者说等了一段时间自己解决了

问题:

几天前我第一次注意到集群上的问题。通过将映像推送到 GCR 然后弹回 pods kubectl rollout restart deployment.

来部署新映像

然后 pods 都返回 ImagePullBackOff,说他们无法从 GCR 获取图像:

kubectl get pods:

XXX-XXX-XXX     0/1     ImagePullBackOff   0          13d
XXX-XXX-XXX     0/1     ImagePullBackOff   0          13d
XXX-XXX-XXX     0/1     ImagePullBackOff   0          13d
...

kubectl describe pod XXX-XXX-XXX:

Normal   BackOff           20s                kubelet                                Back-off pulling image "gcr.io/<GCP_PROJECT>/XXX:dev-latest"
Warning  Failed            20s                kubelet                                Error: ImagePullBackOff
Normal   Pulling           8s (x2 over 21s)   kubelet                                Pulling image "gcr.io/<GCP_PROJECT>/XXX:dev-latest"
Warning  Failed            7s (x2 over 20s)   kubelet                                Failed to pull image "gcr.io/<GCP_PROJECT>/XXX:dev-latest": rpc error: code = Unknown desc = failed to pull and unpack image "gcr.io/<GCP_PROJECT>/XXX:dev-latest": failed to resolve reference "gcr.io/<GCR_PROJECT>/XXX:dev-latest": unexpected status code [manifests dev-latest]: 403 Forbidden
Warning  Failed            7s (x2 over 20s)   kubelet                                Error: ErrImagePull

我知道GCR里面肯定有这张图-

我已经通过 SSH 连接到其中一个集群节点并尝试 docker 手动拉取,但没有成功:

docker pull gcr.io/<GCP_PROJECT>/XXX:dev-latest
Error response from daemon: unauthorized: You don't have the needed permissions to perform this operation, and you may have invalid credentials. To authenticate your request, follow the steps in: https://cloud.google.com/container-registry/docs/advanced-authentication

(还对 public mongodb 图像进行了 docker 拉取,以确认 正在工作,并且它特定于 GCR) .

所以这让我相信这是服务帐户没有正确权限的问题,如 'Error 400/403' 部分下的 in the cloud docs。这似乎表明服务帐户已被删除或手动编辑。

在我的故障排除过程中,我试图找出确切的GKE 正在使用哪个 服务帐户从 GCR 中提取数据。在文档中概述的步骤中,它说:The name of your Google Kubernetes Engine service account is as follows, where PROJECT_NUMBER is your project number:

service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com

我找到了服务帐户并检查了政策 - 它确实有一个用于 roles/container.serviceAgent,但没有像我从文档中的描述中期望的那样具体提及 kubernetes..'the Kubernetes Engine Service Agent 角色'(除非那是他们所描述的角色,在这种情况下,无论如何我之前都不会更好......)。

一定没有正确的角色,所以我按照步骤重新启用(禁用然后启用 Kubernetes API)。再次 运行 cloud projects get-iam-policy <GCP_PROJECT> 并比较两个输出 (before/after),唯一的区别是“@cloud-filer...”的服务帐户已被删除。

考虑到错误可能是其他原因,我想我会尝试启动一个新集群。同样的错误 - 无法拉取图像。

发送帮助..

我绞尽脑汁想排查问题,现在没思路了!非常感谢任何帮助!

docs 计算引擎默认服务帐户访问容器注册表以拉取图像而不是 kubernetes 引擎服务 account.You 可以转到节点池并检查安全性中的服务帐户名称 section.Check 服务帐号的访问日志,查看错误,然后向服务帐号提供必要的权限。

现在已经解决了。

服务帐户具有正确的 roles/permissions,但由于某种原因停止工作。

我为该服务帐户手动创建了一个密钥,将该密钥添加到 kube 集群中,并将服务帐户设置为使用该密钥。

仍然不知道为什么它还没有这样做,或者为什么它一开始就突然停止工作,但它正在工作...

修复来自 this guide,从 'Create & use GCR credentials'.

开始的部分

我认为正确的解决方案是将“roles/artifactregistry.reader”角色添加到节点池配置使用的服务帐户。 在 terraform 中可以通过

完成
resource "google_project_iam_member" "allow_image_pull" {
  project = var.project_id
  role   = "roles/artifactregistry.reader"
  member = "serviceAccount:${var.service_account_email}"
}

在我的案例中,为集群使用的服务帐户工作了 re-add(即删除然后添加)角色“Artifact registry reader”。

我不知道它是否仍然有帮助,但我遇到了同样的问题并设法解决了它。

在我的例子中,我正在通过 terraform 部署 GKE,并且没有为节点池指定 oauth_scope 属性,如 example 中所示。据我了解,您需要在此处提供 gcp API 以使节点能够使用它们。