Kubernetes
Mint a pull key
Create a project key scoped to pull only. A cluster never needs to push:
repositories:pull:acme/*Narrow it to a single repository if the cluster only runs one service.
Create the secret
kubectl create secret docker-registry lazer \
--namespace production \
--docker-server=lazer.sh \
--docker-username=k8s \
--docker-password="$LAZER_PULL_KEY"Pull secrets are namespaced. Create one per namespace that runs your images.
Reference it
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
spec:
template:
spec:
imagePullSecrets:
- name: lazer
containers:
- name: api
image: lazer.sh/acme/api:2.4.1
imagePullPolicy: IfNotPresentTo avoid repeating it on every workload, attach the secret to the namespace's default service account instead:
kubectl patch serviceaccount default \
--namespace production \
-p '{"imagePullSecrets":[{"name":"lazer"}]}'Deploy by digest
Tags move. Digests do not. Deploying by digest means the image running in production is exactly the one CI built, even if someone retags:
image: lazer.sh/acme/api@sha256:9f3c...a71eGet the digest in CI with crane digest lazer.sh/acme/api:$GIT_SHA and substitute it into
the manifest.
Rotating the key
Update the secret in place; running pods are unaffected because they have already pulled:
kubectl create secret docker-registry lazer \
--namespace production \
--docker-server=lazer.sh \
--docker-username=k8s \
--docker-password="$NEW_KEY" \
--dry-run=client -o yaml | kubectl apply -f -Then revoke the old key in the panel.
Troubleshooting
ImagePullBackOff with unauthorized usually means the secret is in the wrong namespace,
or the key expired. Check with:
kubectl get events --namespace production --field-selector reason=Failedinsufficient scope means the key is scoped to a different repository than the image
reference names.