Your only option is to delete and recreate the secret with the correct type. Alternatively, you could roll the change by creating a new secret with a different name and then pointing any resources to use it. For example, if you want to change an Opaque secret to the kubernetes.io/tls type you'll have to recreate it.
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 -
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.
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 |=
.
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.
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.
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}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With