将Docker镜像从GCR拉入GKE时出错“无法拉入镜像.... 403禁止”

sirbozc5  于 2023-03-29  发布在  Docker
关注(0)|答案(6)|浏览(250)

背景:

我有一个GKE集群,它突然停止了从GCR中提取我的Docker镜像;两者都在同一个GCP项目中。它已经运行了几个月,没有问题拉取图像,现在已经开始抛出错误,没有做任何更改。
(NB:我通常是我的团队中唯一一个访问Google Cloud的人,尽管我的团队中的其他人完全有可能在没有意识到的情况下进行了更改。
我已经看到了关于这个主题的其他一些帖子,但其他人提供的解决方案并没有帮助。其中两个帖子对我来说特别突出,因为它们都是在我的问题开始的同一天发布的~13/14天前。这是否是巧合,谁知道呢。
This post有和我一样的问题;不确定是否张贴的评论帮助他们解决,但它还没有固定为我. This post似乎也是同样的问题,但海报说,它解决了自己等待一段时间后.

问题:

几天前我第一次注意到集群上的问题。通过将映像推送到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
...

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

其他帖子的故障排除步骤:

我知道这画面在大中华区绝对存在-

  • 我可以将镜像拉到我自己的机器上(也从我的机器上删除了所有的docker镜像,以确认它真的在拉)
  • 我可以看到标记的图像,如果我看的GCR用户界面上的 chrome 。

我已经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

(Also做了一个公共mongodb镜像的docker pull,以确认 that 正在工作,并且它是特定于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

我找到了服务帐户并检查了策略-它确实有一个针对roles/container.serviceAgent的策略,但没有特别提到kubernetes,因为我希望从文档中的描述中..“* Kubernetes Engine Service Agent role*”(除非这是他们描述的那个,在这种情况下,我之前也没有更好的..)。
必须没有正确的角色,所以我随后按照步骤重新启用(禁用然后启用Kubernetes API)。再次运行cloud projects get-iam-policy <GCP_PROJECT>并区分两个输出(之前/之后),唯一的区别是'@cloud-filer...'的服务帐户已被删除。
我想可能是别的什么错误,我想我会尝试旋转一个新的集群。同样的错误-不能拉图像。

发送帮助..

我一直在绞尽脑汁想办法解决问题,但我现在没有办法了!任何和所有的帮助非常感谢!

x6h2sr28

x6h2sr281#

我相信正确的解决方案是将“roles/artifactregistry.reader”角色添加到节点池配置使用的服务帐户中

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

pxiryf3j2#

我不知道它是否仍然有帮助,但我有同样的问题,并设法解决它。
在我的例子中,我是通过terraform部署GKE的,并且没有为节点池指定oauth_scope属性,如示例所示。据我所知,您需要在这里提供gcp API,以使节点能够使用它们。

vnjpjtjt

vnjpjtjt3#

现在已经解决了这个问题。
服务帐户具有正确的角色/权限,但由于某种原因停止工作。
我手动为该服务帐户创建了一个密钥,将该密钥添加到kube集群中,并设置服务帐户使用该密钥。
我仍然不知道为什么它还没有这样做,或者为什么它突然停止工作,但它正在工作。
修复来自this guide,从“创建和使用GCR凭证”开始的部分。

v8wbuo2f

v8wbuo2f4#

我也遇到过同样的问题,我们有两个案例:
1.如果在GKE(docs)中使用terraform定义节点池时,在node config中指定了服务帐户,请记下此服务帐户的名称
1.如果你不指定任何东西,Terraform使用默认服务帐户(最低权限)为你创建节点池,你可以看到这个服务帐户的名称,因为GKE只显示Service account: default-〉你必须去Compute Engine -> VM instances -> click to name of instance that belong to your nodepool和搜索Service account得到你想要的名称
最后一步,转到IAM并授予上述服务帐户的访问权限,至少您需要将Storage Object Viewer授予您的服务帐户以从注册表(文档)中提取图像
回到你的GKE,删除你的pod以重新触发拉动:从注册表图像,这对我来说是好的。

ttvkxqim

ttvkxqim5#

从docs compute engine默认的service account访问容器注册表来拉取镜像,而不是kubernetes engine service account。您可以转到node pool,在security部分检查service account名称。检查service account的访问日志,查看错误,然后为service account提供必要的权限。

u2nhd7ah

u2nhd7ah6#

在我的例子中,重新添加(即删除,然后添加)角色“工件注册表阅读器”,用于集群使用的serviceaccount。

相关问题