How can I update a secret on Kubernetes when it is generated from a file?
KubernetesKubectlKubernetes SecretsKubernetes Problem Overview
I've created a secret using
kubectl create secret generic production-tls \
--from-file=./tls.key \
--from-file=./tls.crt
If I'd like to update the values - how can I do this?
Kubernetes Solutions
Solution 1 - Kubernetes
This should work:
kubectl create secret generic production-tls \
--save-config \
--dry-run=client \
--from-file=./tls.key --from-file=./tls.crt \
-o yaml | \
kubectl apply -f -
Solution 2 - Kubernetes
You can delete and immediately recreate the secret:
kubectl delete secret production-tls \
--ignore-not-found
kubectl create secret generic production-tls \
--from-file=./tls.key \
--from-file=./tls.crt
I put these commands in a script. The --ignore-not-found
prevents getting a warning on the first run.
Solution 3 - Kubernetes
Alternatively, you can also use jq
's =
or |=
operator to update secrets on the fly.
TLS_KEY=$(base64 < "./tls.key" | tr -d '\n')
TLS_CRT=$(base64 < "./tls.crt" | tr -d '\n')
kubectl get secrets production-tls -o json \
| jq '.data["tls.key"] |= "$TLS_KEY"' \
| jq '.data["tls.crt"] |= "$TLS_CRT"' \
| kubectl apply -f -
Although it might not be as elegant or simple as the kubectl create secret generic --dry-run
approach, technically, this approach is truly updating values rather than deleting/recreating them. You'll also need jq
and base64
(or openssl enc -base64
) commands available, tr
is a commonly-available Linux utility for trimming trailing newlines.
See here for more details about jq
update operator |=
.
Solution 4 - Kubernetes
As I wasn't able to reply to Devy's answer above, which I like because it will preserve Ownership where deleting and recreating has the potential to lose any extra information in the record. I'm adding this for the newer people who may not immediately understand whey their variables aren't being interpolated.
TLS_KEY=$(base64 < "./tls.key" | tr -d '\n')
TLS_CRT=$(base64 < "./tls.crt" | tr -d '\n')
kubectl get secrets production-tls -o json \
| jq ".data[\"tls.key\"] |= \"$TLS_KEY\"" \
| jq ".data[\"tls.crt\"] |= \"$TLS_CRT\"" \
| kubectl apply -f -
This lead me to attempting to use the 'patch' method of kubectl, which also seems to work.
kubectl \
patch \
secret \
production-tls \
-p "{\"data\":{\"tls.key\":\"${TLS_KEY}\",\"tls.crt\":\"${TLS_CRT}\"}}"
Thanks Devy for the answer that best met my needs.
Solution 5 - Kubernetes
For more specific cases you might need to specify your namespace that the cert needs to be renewed and delete the old one.
For deletion of the cert
kubectl delete secret -n `namespace`
For the creation of new cert to specific namespace
kubectl create secret {your-cert-name} --key /etc/certs/{name}.com.key --cert /etc/certs/{name}.com.crt -n {namespace}
Solution 6 - Kubernetes
Just to expand on these answers I found that adding '--ignore-not-found' to the delete helped with our CICD as it wouldn't error out if the secret didn't exist, it would just go ahead and create it:
kubectl delete secret production-tls --ignore-not-found
kubectl create secret generic production-tls --from-file=./tls.key --from-file=./tls.crt.
Solution 7 - Kubernetes
Late to the party but still here are my inputs.
Potentially we can use both the patch
or edit
option.
-
With
edit
:kubectl edit secrets/<SECRET_NAME> -n <NAME_SPACE>
- NOT the recommended way of editing the secrets.
- You should have enough permission to do the above edit.
- The value should be
base64
encode by yourself and then the encoded value should be placed while editing.
-
With
patch
:
Solution 8 - Kubernetes
I've found a best way to do so:
kubectl create secret generic production-tls --from-file=./tls.key --from-file=./tls.crt --dry-run=client -o yaml | kubectl apply -f -