Kubernetes patching
Chatting to a developer with a question on Stack Overflow, showed an interesting use of imagePullSecrets that I’d not seen before. The container registry secret can be added to the default service account. This then enables e.g. kubectl run ... (which runs as the default service account) to access the private registry. Previously, I’ve resorted to creating Deployments that include imagePullSecrets to circumvent this challenge.
So, I have a secret:
kubectl get secret/ghcr --output=yaml
Yields:
apiVersion: v1
data:
.dockerconfigjson: [[REDACTED]]
kind: Secret
metadata:
creationTimestamp: "2020-10-00T00:00:00Z"
name: ghcr
namespace: default
selfLink: /api/v1/namespaces/default/secrets/ghcr
type: kubernetes.io/dockerconfigjson
And, customarily, I’d always do something like this to pull images in repositories that require the secret:
apiVersion: apps/v1
kind: Deployment
metadata:
name: something
spec:
replicas: 1
selector:
matchLabels:
project: x
function: y
template:
metadata:
labels:
project: x
function: y
name: something
spec:
imagePullSecrets:
- name: SECRET
containers:
- name: something
image: IMAGE
imagePullPolicy: Always
Because:
kubectl run test --image=${IMAGE}
Yields:
kubectl get pod/test \
--output=jsonpath="{.status.containerStatuses[?(@.image==\"${IMAGE}\")].state.waiting.reason}"
ImagePullBackOff
Because kubectl (correctly) does not have permissions to access the private repository
But, it turns out you can add the imagePullSecrets to a service account (using default in this case):
Using a vanilla service account:
kubectl get serviceaccount/default --output=yaml
Yields:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2020-00-00T00:00:00Z"
name: default
namespace: default
selfLink: /api/v1/namespaces/default/serviceaccounts/default
secrets:
- name: default-token-7nfwh
It can be patched with the imagePullSecrets:
kubectl patch serviceaccount/default \
--patch='{"imagePullSecrets":[{"name":"ghcr"}]}'
serviceaccount/default patched
So that:
kubectl get serviceaccount/default --output=yaml
Yields:
apiVersion: v1
imagePullSecrets:
- name: ghcr
kind: ServiceAccount
metadata:
creationTimestamp: "2020-10-26T17:03:40Z"
name: default
namespace: default
resourceVersion: "313759"
selfLink: /api/v1/namespaces/default/serviceaccounts/default
uid: a8408316-aed7-49d9-9ebf-dab8f3578e2d
secrets:
- name: default-token-7nfwh
And now the kubectl run ... will succeed.
And, if you want subsequently to remove the secret:
kubectl patch serviceaccount/default \
--patch='{"imagePullSecrets":[]}'
serviceaccount/default patched
kubectl get serviceaccount/default --output=yaml
Yields:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2020-00-00T00:00:00Z"
name: default
namespace: default
selfLink: /api/v1/namespaces/default/serviceaccounts/default
secrets:
- name: default-token-7nfwh