Skip to main content

Pull private images from the Cloider registry

To run an image from a private registry, Kubernetes needs credentials to pull it. For the Cloider container registry at registry.cloider.com, you create a pull-only registry token, store it in the cluster as a Secret of type kubernetes.io/dockerconfigjson, and reference that Secret as an imagePullSecret in your pods. This page shows the whole flow, from pushing an image to running it.

Before you begin​

How it works​

  • A registry token is a username and secret that can log in to the registry. Give the cluster its own token with the Pull only permission, limited to the projects it needs, so a leaked cluster secret can't push or delete images.
  • A Kubernetes Secret of type kubernetes.io/dockerconfigjson holds that login. Secrets are namespaced, so create it in every namespace whose pods pull private images.
  • imagePullSecrets in a pod spec (or on the namespace's ServiceAccount) tells Kubernetes to use the Secret when it pulls.

Step 1: Create a pull-only registry token​

  1. Open Registry in the sidebar and go to the Tokens tab.
  2. Click Create Token.
  3. In Name, type staging-cluster.
  4. In Projects, choose Only specific projects and pick acme.
  5. In Permission, choose Pull only.
  6. Choose when it Expires (the expiry can't be changed later).
  7. Click Create token.

The Token created dialog shows the Registry host, Username, Secret, a Docker login command and a ready Kubernetes pull secret command. Copy the pull secret command now: the secret isn't shown again. Then click I've saved the secret.

Step 2: Create the image pull secret in the cluster​

Run the pull secret command from step 1, adding the namespace your pods run in with -n. Without -n, the Secret is created in the default namespace only.

Open the cluster's terminal (Kubernetes, then the cluster's name) and paste the command, with -n shop added:

kubectl create namespace shop --dry-run=client -o yaml | kubectl apply -f -
kubectl create secret docker-registry cloider-registry -n shop \
--docker-server=registry.cloider.com \
--docker-username='acme' \
--docker-password='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
Output
secret/cloider-registry created

Check it:

kubectl get secret cloider-registry -n shop
Output
NAME TYPE DATA AGE
cloider-registry kubernetes.io/dockerconfigjson 1 10s

Step 3: Use the secret in your pods​

Reference the Secret in the pod template with imagePullSecrets:

api.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: shop
spec:
replicas: 2
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
imagePullSecrets:
- name: cloider-registry
containers:
- name: api
image: registry.cloider.com/acme/api:1.0
ports:
- containerPort: 8080
resources:
requests:
cpu: 100m
memory: 128Mi
kubectl apply -f api.yaml
kubectl rollout status deployment/api -n shop

Use the secret for every pod in a namespace​

Instead of adding imagePullSecrets to each Deployment, attach the Secret to the namespace's default ServiceAccount. Every pod that uses that ServiceAccount then pulls with it:

kubectl patch serviceaccount default -n shop \
-p '{"imagePullSecrets": [{"name": "cloider-registry"}]}'

Pods created after the patch pick it up; restart existing Deployments with kubectl rollout restart if they failed to pull before.

Helm charts​

Most charts take pull secrets as a value, often imagePullSecrets:

values.yaml
image:
repository: registry.cloider.com/acme/api
tag: "1.0"
imagePullSecrets:
- name: cloider-registry

Check the exact key with helm show values <chart>.

Verify​

kubectl get pods -n shop -l app=api
kubectl describe pod -n shop -l app=api | grep -A3 "Events"

A successful pull shows Successfully pulled image "registry.cloider.com/acme/api:1.0" in the pod's events, and the pods are Running.

Rotate or revoke the token​

Registry tokens can't be extended once created. To rotate, create a new token, update the Secret, and delete the old token:

kubectl create secret docker-registry cloider-registry -n shop \
--docker-server=registry.cloider.com \
--docker-username='acme' \
--docker-password="$NEW_REGISTRY_SECRET" \
--dry-run=client -o yaml | kubectl apply -f -

Running pods keep their already pulled images; the new Secret is used for the next pull. See Registry tokens for listing and deleting tokens.

Troubleshooting​

ImagePullBackOff or ErrImagePull: run kubectl describe pod <pod> -n shop and read the events:

Event message containsCause and fix
unauthorized or authentication requiredThe Secret is missing, in another namespace, not referenced in imagePullSecrets, or the token expired or was deleted. Check kubectl get secret cloider-registry -n shop and the pod spec
not found or manifest unknownThe repository or tag doesn't exist. Check cloider registry images acme api
denied or forbiddenThe token isn't allowed on that project. Edit the token's projects in Registry, Tokens, or with cloider registry token update

The secret was created in default: the pull secret command from the dashboard and CLI doesn't include a namespace. Recreate it with -n <namespace>.

A tag was overwritten but pods run the old image: Kubernetes reuses an image already on the node when the tag is unchanged. Use a new tag for every release (recommended, see Immutable tags), or set imagePullPolicy: Always.

More cases are in Kubernetes troubleshooting and Registry troubleshooting.

Next steps​

Frequently asked questions

How do I pull private images from the Cloider registry in Kubernetes?

Create a pull-only registry token, store it in the cluster with kubectl create secret docker-registry cloider-registry -n <namespace> --docker-server=registry.cloider.com and the token's username and secret, then add imagePullSecrets with the name cloider-registry to your pod spec.

Why does my pod show ImagePullBackOff for a registry.cloider.com image?

Usually the pull secret is missing, in another namespace, not referenced in imagePullSecrets, or its token expired or cannot access the project. kubectl describe pod shows the exact reason in the pod events.

Should the cluster use a pull-only token?

Yes. Give each cluster its own token with the Pull only permission, limited to the projects it needs. A leaked cluster credential then cannot push or delete images.

Do I need a pull secret in every namespace?

Yes. Kubernetes Secrets are namespaced, so create the pull secret in each namespace whose pods pull private images, or attach it to each namespace's default ServiceAccount.