1. Introduction

At the moment, there’s no flag to directly pass image pull secrets to kubectl run. However, we can still pull it off by configuring the default service account or a custom service account to use our image pull secret. Alternatively, we can update the pod definition created by kubectl run with the image pull secret.

In this tutorial, we illustrate how to pass an image pull secret when using kubectl run.

2. Using a Default Service Account

We’ll start by creating our image pull secret using kubectl create secret docker-registry:

$ kubectl create secret docker-registry baeldung-secret --docker-server=https://index.docker.io/v1/ --docker-username=[our-docker-username] --docker-password=[our-docker-password/token] --docker-email=[our-docker-email-address]
secret/baeldung-secret created

In the command above, we specified our –docker-server as https://index.docker.io/v1/ because our image is on Docker Hub. If we had the image on a different registry server, we would’ve provided the URL of that server. Of course, we’d also need to adjust other values accordingly.

Next, we’ll add the secret to our default service account using kubectl edit serviceaccount:

$ kubectl edit serviceaccount default
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2024-01-25T22:31:58Z"
name: default
namespace: default
resourceVersion: "6838"
uid: e53039ea-2fc1-4029-a128-ae36c0857a83
imagePullSecrets:
- name: baeldung-secret

We could’ve also added the secret to the default service account using kubectl patch serviceaccount:

$ kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "baeldung-secret"}]}'

With the secret attached to our default service account, we can now pull images from our private repository using kubectl run:

$ kubectl run test --image=baeldung/image
pod/test created

To confirm that we successfully pulled the image, we’ll run kubectl describe pod test:

$ kubectl describe pod test
Name:             test
Namespace:        default
Priority:         0
Service Account:  default
...truncated...
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  8s    default-scheduler  Successfully assigned default/test to minikube
  Normal  Pulling    8s    kubelet            Pulling image "baeldung/image"
  Normal  Pulled     7s    kubelet            Successfully pulled image "baeldung/image" in 802ms (802ms including waiting)
...truncated...

As shown in the Message column of the third row of the Events section, the image was successfully pulled.

The image pull secret remains attached to our default service account. So, we can use the same service account in other instances where we need to pull images from the same source.

In production, where we might need granular control, custom service accounts might be better. Also, if we use the default service account for every request to the Kubernetes API, auditing may become tedious. But if we have different service accounts for different types of requests, such is less likely.

With the workload distributed, we can readily read through the configuration of each service account, review, and update them.

3. Using a Custom Service Account

Since we already created our image pull secret in the previous section, we’ll start by creating a custom service account using kubectl create serviceaccount:

$ kubectl create serviceaccount baeldung
serviceaccount/baeldung created

After that, we’ll update our service account, baeldung, with the image pull secret using kubectl patch serviceaccount:

$ kubectl patch serviceaccount baeldung -p '{"imagePullSecrets": [{"name": "baeldung-secret"}]}'
serviceaccount/baeldung patched

We could’ve also updated it using kubectl edit serviceaccount.

Since our custom service account is now patched with the image pull secret, we can use it to pull images from our private repository with kubectl run:

$ kubectl run test --image=baeldung/image --overrides='{ "spec": { "serviceAccount": "baeldung" }  }'
pod/test created

The command creates a pod named test from an image baeldung/image. Then, instead of using the default service account, we altered that behavior by specifying our custom service account with the –overrides flag.

Let’s confirm the image was pulled successfully:

$ kubectl describe pod test
Name:             test
Namespace:        default
Priority:         0
Service Account:  baeldung
...truncated...
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  2s    default-scheduler  Successfully assigned default/test to minikube
  Normal  Pulling    2s    kubelet            Pulling image "baeldung/image"
  Normal  Pulled     1s    kubelet            Successfully pulled image "baeldung/image" in 799ms (799ms including waiting)
...truncated...

The third Message row confirms the success. Then, we can also see that kubectl run used baeldung as the Service Account.

As with the default service account, the image pull secret remains attached to the custom service account. So, we can reuse the service account for a similar purpose.

4. Overriding the Pod Definition

We already created our image pull secret. So, we’ll head to the next step where we add the image pull secret to the pod definition generated by kubectl run.

Using the –overrides flag of kubectl run, we’ll add the image pull secret to the generated pod definition:

$ kubectl run test --image=baeldung/image --overrides='{"spec": {"imagePullSecrets":[{"name": "baeldung-secret"}]}}'
pod/test created

We’ll confirm success using kubectl describe:

$ kubectl describe pod test
Name:             test
Namespace:        default
Priority:         0
Service Account:  default
...truncated...
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  8s    default-scheduler  Successfully assigned default/test to minikube
  Normal  Pulling    8s    kubelet            Pulling image "baeldung/image"
  Normal  Pulled     7s    kubelet            Successfully pulled image "baeldung/image" in 802ms (802ms including waiting)
...truncated...

One upside to this method is that it takes fewer steps, is quicker, and the image pull secret is not permanently attached to a service account. So, it’s a great option when we’re running tests or doing quick fixes.

4. Conclusion

In this article, we discussed how to pass an image pull secret to kubectl run using a default service account and a custom service account. We also talked about how to add an image pull secret to a kubectl run pod definition.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.