Kubernetes
ImagePullSecrets
Google Container Registry
GCR
Container Security

ImagePullSecrets GCR

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If your Kubernetes cluster needs to pull private images from Google Container Registry, the cluster must present valid registry credentials. In Kubernetes, the usual mechanism is an imagePullSecret referenced by a Pod or ServiceAccount. For GCR, that secret is typically created from a Google service account key or from Docker credentials that can authenticate to gcr.io.

What imagePullSecrets Does

When Kubernetes starts a Pod, the kubelet may need to authenticate to the registry before it can download the image. An imagePullSecret stores those registry credentials in a Kubernetes Secret of type kubernetes.io/dockerconfigjson.

Without it, private GCR images often fail with image-pull errors such as ImagePullBackOff.

Create a Secret for GCR

A common pattern uses a Google service account JSON key. The Docker username for this case is _json_key, and the password is the JSON key content.

bash
kubectl create secret docker-registry gcr-json-key   --docker-server=https://gcr.io   --docker-username=_json_key   --docker-password="$(cat key.json)"   --docker-email=[email protected]

Create the secret in the namespace where the Pod will run.

Use the Secret in a Pod

Reference it in the Pod spec.

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: demo
5spec:
6  containers:
7    - name: app
8      image: gcr.io/my-project/my-image:latest
9  imagePullSecrets:
10    - name: gcr-json-key

Now the Pod can use that secret when pulling the image.

Attach It to a ServiceAccount Instead

If many Pods in the same namespace need the same registry credentials, attaching the secret to a ServiceAccount is cleaner than repeating imagePullSecrets in every manifest.

yaml
1apiVersion: v1
2kind: ServiceAccount
3metadata:
4  name: app-sa
5imagePullSecrets:
6  - name: gcr-json-key

Then reference the ServiceAccount from your workload.

yaml
spec:
  serviceAccountName: app-sa

Namespace Scope Matters

Secrets are namespace-scoped. A secret created in default is not visible in production.

That is a common reason the configuration "looks right" but image pulls still fail. Make sure the secret exists in the same namespace as the Pod.

Troubleshooting Pull Failures

If the Pod still cannot pull the image, inspect it:

bash
kubectl describe pod demo

Look for messages such as:

  • 'ErrImagePull'
  • 'ImagePullBackOff'
  • unauthorized or forbidden registry responses

Also verify that:

  • the image path is correct
  • the service account key has permission to access the registry
  • the secret name is spelled correctly
  • the Pod and secret are in the same namespace

GCR Versus Artifact Registry

Some teams still use GCR, while others have moved to Google Artifact Registry. The Kubernetes secret pattern is similar, but the registry host changes. So always match the --docker-server value to the actual registry domain you are pulling from.

Verify the Secret Object Type

A quick sanity check is to confirm that Kubernetes created the secret as a Docker config secret and not as a generic opaque secret.

bash
kubectl get secret gcr-json-key -o yaml

You should see the type kubernetes.io/dockerconfigjson. If the type is wrong, the kubelet cannot use it for registry authentication even if the secret data exists.

Common Pitfalls

A common mistake is creating the secret in the wrong namespace.

Another mistake is referencing imagePullSecrets correctly but using credentials that do not actually have permission to the target image.

Developers also often copy GCR examples to Artifact Registry without changing the registry host, which results in authentication failures that look mysterious at first.

Summary

  • Private GCR images need registry credentials in Kubernetes.
  • Create a docker-registry secret and reference it with imagePullSecrets.
  • ServiceAccount attachment is cleaner when multiple Pods need the same secret.
  • The secret must exist in the same namespace as the Pod.
  • If pulls fail, inspect the Pod events and verify both registry path and permissions.

Course illustration
Course illustration

All Rights Reserved.