将 docker 映像从 GCR 拉入 GKE 时出错“无法拉取映像 .... 403 Forbidden”

con*_*l_c 12 docker google-cloud-platform kubernetes google-kubernetes-engine google-container-registry

背景:

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

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

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

这篇文章和我有同样的问题;不确定发布的评论是否帮助他们解决了问题,但对我来说还没有解决。这个帖子好像也是同样的问题,但是发帖人说等了一段时间后自己解决了。

问题:

几天前我第一次注意到集群上的问题。通过将映像推送到 GCR 然后弹跳 Pod 来部署新映像kubectl rollout restart deployment

然后所有 Pod 都返回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
...
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

我知道这个图像肯定存在于GCR中——

  • 我可以将映像拉到我自己的机器上(还从我的机器中删除了所有 docker 映像以确认它确实在拉动)
  • 如果我在 chrome 上查看 GCR UI,我可以看到标记的图像。

我已经通过 SSH 连接到集群节点之一,并尝试手动 docker pull,但没有成功:

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
Run Code Online (Sandbox Code Playgroud)

(还对公共 mongodb 映像进行了 docker pull 以确认正常工作,并且它特定于 GCR)。

因此,这让我相信这是服务帐户没有正确权限的问题,如云文档中的“错误 400/403”部分所示。这似乎表明服务帐户已被删除或手动编辑。

在故障排除过程中,我尝试准确找出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
Run Code Online (Sandbox Code Playgroud)

我找到了服务帐户并检查了策略 - 它确实有一个roles/container.serviceAgent,但没有特别提到 kubernetes,正如我从文档中的描述中所期望的那样......“ Kubernetes Engine 服务代理角色”(除非那是他们的角色)描述,在这种情况下我也没有比之前更好..)。

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

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

发送帮助..

我绞尽脑汁想解决问题,但现在却没有主意!非常感谢任何和所有帮助!

小智 5

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

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


con*_*l_c 2

现在已经解决了这个问题。

服务帐户具有正确的角色/权限,但由于某种原因停止工作。

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

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

修复来自本指南,从“创建和使用 GCR 凭据”开始的部分。