How can I update a secret on Kubernetes when it is generated from a file?

Solution 1:

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:

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:

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 |=.