<p>I cannot pull artifact registry images to a newly created GKE cluster with Terraform and a user-defined service account.</p>
<p>The terraform used to stand up the cluster is below.</p>
<pre><code>locals {
  service         = &quot;example&quot;
  resource_prefix = format(&quot;%s-%s&quot;, local.service, var.env)
  location        = format(&quot;%s-b&quot;, var.gcp_region)
}

resource &quot;google_service_account&quot; &quot;main&quot; {
  account_id   = format(&quot;%s-sa&quot;, local.resource_prefix)
  display_name = format(&quot;%s-sa&quot;, local.resource_prefix)
  project      = var.gcp_project
}

resource &quot;google_container_cluster&quot; &quot;main&quot; {
  name                     = local.resource_prefix
  description              = format(&quot;Cluster primarily servicing the service %s&quot;, local.service)
  location                 = local.location
  remove_default_node_pool = true
  initial_node_count       = 1
}

resource &quot;google_container_node_pool&quot; &quot;main&quot; {
  name       = format(&quot;%s-node-pool&quot;, local.resource_prefix)
  location   = local.location
  cluster    = google_container_cluster.main.name
  node_count = var.gke_cluster_node_count

  node_config {
    preemptible  = true
    machine_type = var.gke_node_machine_type
    # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles.
    service_account = google_service_account.main.email
    oauth_scopes = [
      &quot;https://www.googleapis.com/auth/logging.write&quot;,
      &quot;https://www.googleapis.com/auth/monitoring&quot;,
      &quot;https://www.googleapis.com/auth/cloud-platform&quot;,
      &quot;https://www.googleapis.com/auth/devstorage.read_only&quot;,
      &quot;https://www.googleapis.com/auth/servicecontrol&quot;,
      &quot;https://www.googleapis.com/auth/service.management.readonly&quot;,
      &quot;https://www.googleapis.com/auth/trace.append&quot;
    ]
  }

  autoscaling {
    min_node_count = var.gke_cluster_autoscaling_min_node_count
    max_node_count = var.gke_cluster_autoscaling_max_node_count
  }
}
</code></pre>
<p>I run a helm deployment to deploy an application and get the following issue.</p>
<pre><code>default       php-5996c7fbfd-d6xf5                                             0/1     ImagePullBackOff             0          37m
</code></pre>
<pre><code>Normal   Pulling    36m (x4 over 37m)      kubelet            Pulling image &quot;europe-docker.pkg.dev/example-999999/eu.gcr.io/example-php-fpm:latest&quot;
  Warning  Failed     36m (x4 over 37m)      kubelet            Failed to pull image &quot;europe-docker.pkg.dev/example-999999/eu.gcr.io/example-php-fpm:latest&quot;: rpc error: code = Unknown desc = failed to pull and unpack image &quot;europe-docker.pkg.dev/example-999999/eu.gcr.io/example-php-fpm:latest&quot;: failed to resolve reference &quot;europe-docker.pkg.dev/example-999999/eu.gcr.io/example-php-fpm:latest&quot;: failed to authorize: failed to fetch oauth token: unexpected status: 403 Forbidden
  Warning  Failed     36m (x4 over 37m)      kubelet            Error: ErrImagePull
  Warning  Failed     35m (x6 over 37m)      kubelet            Error: ImagePullBackOff
</code></pre>
<p>Seems to me that I've missed something to do with the service account. Although using cloud ssh I am able to generate an oauth token, but that also does not work using <code>crictl</code></p>
<p><strong>UPDATE: issue resolved</strong></p>
<p>I have been able to resolve my problem with the following additional terraform code.</p>
<pre><code>resource &quot;google_project_iam_member&quot; &quot;artifact_role&quot; {
  role = &quot;roles/artifactregistry.reader&quot;
  member  = &quot;serviceAccount:${google_service_account.main.email}&quot;
  project = var.gcp_project
}
</code></pre>

<p>Turning comment to answer as it resolved @David's issue.</p>
<p>Because the user defined service account is being used for the node_pool the appropriate roles need to be bound to this service account.</p>
<p>In this case: <code>roles/artifactregistry.reader</code></p>
<p><a href="https://cloud.google.com/artifact-registry/docs/access-control#permissions" rel="nofollow noreferrer">Configuring artifact registry permissions</a></p>
<p>Best practice is to grant the minimum required roles.</p>
