To pull an image from a private registry, we can specify the imagePullSecrets
property in the pod template, or we can add it to a service account we'll add to the pod, which will automatically set the imagePullSecrets
property for us.
kubectl get sa
When your namespace is empty, you should only have the service account: default
You should have:
NAME SECRETS AGE
default 0 21d
kubectl get serviceaccount default -o yaml
You should have:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2023-11-18T16:04:11Z"
name: default
namespace: default
resourceVersion: "321"
uid: 5fb55f56-9b6b-4eb6-91fb-ae1f568975e2
The metadata.creationTimestamp
, metadata.resourceVersion
and metadata.uid
are generated by k8s
Creating a kubernetes.io/dockercfg
secret, to find out more, click here
kubectl apply -f pull-secret.yml
As you can see, it's a fake
Check that it has been created correctly
kubectl get secret
You should have:
NAME TYPE DATA AGE
pull-secret kubernetes.io/dockercfg 1 4s
As you can see, nothing fancy. You can decode the contents of .dockercfg
. with :
kubectl get secret pull-secret -o "jsonpath={.data.\.dockercfg}" | base64 -d
This is a copy of the service account default
to which we've added :
...
imagePullSecrets:
- name: pull-secret
kubectl apply -f service-account-with-secret.yml
Check that it has been created correctly
kubectl get sa
You should have:
NAME SECRETS AGE
default 0 21d
default-with-secret 0 12s
kubectl apply -f deployment_sa.yml
It's a simple deployment with the property spec.template.spec.serviceAccountName: default-with-secret
kubectl get deployments
You should have:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 1/1 1 1 12s
kubectl get deployments nginx-deployment -o yaml
You should have:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"nginx-deployment","namespace":"default"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"nginx"}},"template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"nginx","name":"nginx","ports":[{"containerPort":80}]}],"serviceAccountName":"default-with-secret"}}}}
creationTimestamp: "2023-12-10T14:34:31Z"
generation: 1
labels:
app: nginx
name: nginx-deployment
namespace: default
resourceVersion: "38060"
uid: 7f3efae2-d94f-4bcd-92e4-95362c8acee2
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default-with-secret
serviceAccountName: default-with-secret
terminationGracePeriodSeconds: 30
status:
availableReplicas: 1
conditions:
- lastTransitionTime: "2023-12-10T14:34:33Z"
lastUpdateTime: "2023-12-10T14:34:33Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2023-12-10T14:34:31Z"
lastUpdateTime: "2023-12-10T14:34:33Z"
message: ReplicaSet "nginx-deployment-545667cd6b" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 1
replicas: 1
updatedReplicas: 1
Now we'll list the pods
kubectl get pods
You should have:
NAME READY STATUS RESTARTS AGE
nginx-deployment-545667cd6b-2gwfj 1/1 Running 0 2m11s
Let's take a closer look at our pod
kubectl get pods nginx-deployment-545667cd6b-2gwfj -o yaml
You should have:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2023-12-10T14:34:31Z"
generateName: nginx-deployment-545667cd6b-
labels:
app: nginx
pod-template-hash: 545667cd6b
name: nginx-deployment-545667cd6b-2gwfj
namespace: default
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: nginx-deployment-545667cd6b
uid: c50733b9-6fa5-46fe-937b-dc73b15c62ba
resourceVersion: "38058"
uid: b6ebd8ae-ad76-4931-9584-a9d59f479113
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-slx9w
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
imagePullSecrets:
- name: pull-secret
nodeName: docker-desktop
preemptionPolicy: PreemptLowerPriority
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default-with-secret
serviceAccountName: default-with-secret
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: kube-api-access-slx9w
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2023-12-10T14:34:31Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2023-12-10T14:34:33Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2023-12-10T14:34:33Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2023-12-10T14:34:31Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://cd5fe9fb9dff6a1d717cf9ebddb9b44a4e5420c12f0fb6b7cd4122d0224fa364
image: nginx:latest
imageID: docker-pullable://nginx@sha256:10d1f5b58f74683ad34eb29287e07dab1e90f10af243f151bb50aa5dbb4d62ee
lastState: {}
name: nginx
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2023-12-10T14:34:33Z"
hostIP: 192.168.65.3
phase: Running
podIP: 10.1.2.79
podIPs:
- ip: 10.1.2.79
qosClass: BestEffort
startTime: "2023-12-10T14:34:31Z"
What's notable is what's in spec.imagePullSecrets[0].name
, we see the imagePullSecrets
we've put in the service account
Normally with this, you can pull images from a private registry.