<h2 id="background">Background:</h2>
<p>I have a GKE cluster which has suddenly stopped being able to pull my docker images from GCR; both are in the same GCP project. It has been working well for several months, no issues pulling images, and has now started throwing errors without having made any changes.</p>
<p>(NB: I'm generally the only one on my team who accesses Google Cloud, though it's entirely possible that someone else on my team may have made changes / inadvertently made changes without realising).</p>
<p>I've seen a few other posts on this topic, but the solutions offered in others haven't helped. Two of these posts stood out to me in particular, as they were both posted around the same day my issues started ~13/14 days ago. Whether this is coincidence or not who knows..</p>
<p><a href="https://stackoverflow.com/questions/68305918/troubleshooting-a-manifests-prod-403-error-from-kubernetes-in-gke">This post</a> has the same issue as me; unsure whether the posted comments helped them resolve, but it hasn't fixed for me. <a href="https://serverfault.com/questions/1069107/gke-node-from-new-node-pool-gets-403-on-artifact-registry-image">This post</a> seemed to also be the same issue, but the poster says it resolved by itself after waiting some time.</p>
<h2 id="the-issue">The Issue:</h2>
<p>I first noticed the issue on the cluster a few days ago. Went to deploy a new image by pushing image to GCR and then bouncing the pods <code>kubectl rollout restart deployment</code>.</p>
<p>The pods all then came back with <code>ImagePullBackOff</code>, saying that they couldn't get the image from GCR:</p>
<p><code>kubectl get pods</code>:</p>
<pre><code>XXX-XXX-XXX     0/1     ImagePullBackOff   0          13d
XXX-XXX-XXX     0/1     ImagePullBackOff   0          13d
XXX-XXX-XXX     0/1     ImagePullBackOff   0          13d
...
</code></pre>
<p><code>kubectl describe pod XXX-XXX-XXX</code>:</p>
<pre><code>Normal   BackOff           20s                kubelet                                Back-off pulling image &quot;gcr.io/&lt;GCP_PROJECT&gt;/XXX:dev-latest&quot;
Warning  Failed            20s                kubelet                                Error: ImagePullBackOff
Normal   Pulling           8s (x2 over 21s)   kubelet                                Pulling image &quot;gcr.io/&lt;GCP_PROJECT&gt;/XXX:dev-latest&quot;
Warning  Failed            7s (x2 over 20s)   kubelet                                Failed to pull image &quot;gcr.io/&lt;GCP_PROJECT&gt;/XXX:dev-latest&quot;: rpc error: code = Unknown desc = failed to pull and unpack image &quot;gcr.io/&lt;GCP_PROJECT&gt;/XXX:dev-latest&quot;: failed to resolve reference &quot;gcr.io/&lt;GCR_PROJECT&gt;/XXX:dev-latest&quot;: unexpected status code [manifests dev-latest]: 403 Forbidden
Warning  Failed            7s (x2 over 20s)   kubelet                                Error: ErrImagePull
</code></pre>
<h2 id="troubleshooting-steps-followed-from-other-posts">Troubleshooting steps followed from other posts:</h2>
<p>I know that the image definitely exists in GCR -</p>
<ul>
<li>I can pull the image to my own machine (also removed all docker images from my machine to confirm it was really pulling)</li>
<li>I can see the tagged image if I look on the GCR UI on chrome.</li>
</ul>
<p>I've SSH'd into one of the cluster nodes and tried to docker pull manually, with no success:</p>
<pre><code>docker pull gcr.io/&lt;GCP_PROJECT&gt;/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
</code></pre>
<p>(Also did a docker pull of a public mongodb image to confirm <em>that</em> was working, and it's specific to GCR).</p>
<p>So this leads me to believe it's an issue with the service account not having the correct permissions, as <a href="https://cloud.google.com/kubernetes-engine/docs/troubleshooting#gke_service_account_deleted" rel="noreferrer">in the cloud docs</a> under the 'Error 400/403' section. This seems to suggest that the service account has either been deleted, or edited manually.</p>
<p>During my troubleshooting, I tried to find out exactly <em>which</em> service account GKE was using to pull from GCR. In the steps outlined in the docs, it says that: <code>The name of your Google Kubernetes Engine service account is as follows, where PROJECT_NUMBER is your project number:</code></p>
<pre><code>service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
</code></pre>
<p>I found the service account and checked the polices - it did have one for <code>roles/container.serviceAgent</code>, but nothing specifically mentioning kubernetes as I would expect from the description in the docs.. '<em>the Kubernetes Engine Service Agent role</em>' (unless that is the one they're describing, in which case I'm no better off that before anyway..).</p>
<p>Must not have had the correct roles, so I then followed the steps to re-enable (disable then enable the Kubernetes API). Running <code>cloud projects get-iam-policy &lt;GCP_PROJECT&gt;</code> again and diffing the two outputs (before/after), the only difference is that a service account for '@cloud-filer...' has been deleted.</p>
<p>Thinking maybe the error was something else, I thought I would try spinning up a new cluster. Same error - can't pull images.</p>
<h2 id="send-help">Send help..</h2>
<p>I've been racking my brains to try to troubleshoot, but I'm now out of ideas! Any and all help much appreciated!</p>

localghost
<p>I don't know if it still helps, but I had the same issue and managed to fix it.</p>
<p>In my case I was deploying GKE trough terraform and did not specify <code>oauth_scope</code> property for node pool as show in <a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/container_cluster#example-usage---with-the-default-node-pool" rel="nofollow noreferrer">example</a>. As I understand you need to make gcp APIs available here to make nodes able to use them.</p>
