Replace a Kubernetes TLS Secret Certificate
Replace the certificate in a kubernetes.io/tls Secret: check who manages it (cert-manager, Helm, GitOps), update it in place or via a new Secret, restart workloads only if needed, verify.
Kubernetes applications usually take their certificate from a kubernetes.io/tls
Secret with the keys tls.crt (server certificate followed by intermediates) and
tls.key. An Ingress references it in spec.tls[].secretName, a Gateway in its
listener's certificateRefs. Updating the Secret changes the stored data; the Ingress
controller or workload decides when the new data becomes active.
Before you begin
First check who owns the Secret - a manual change is overwritten otherwise:
- cert-manager: if a
Certificateresource manages the Secret (kubectl get certificate -A), renew through cert-manager instead of editing the Secret. - Helm or GitOps (Argo CD, Flux): the source of truth is the chart values or the Git repository - often encrypted with Sealed Secrets or SOPS, or synced by External Secrets. Change the certificate there and let it sync; a live change is reverted.
- Otherwise you can update the Secret directly, as below.
Also note the context and namespace, the Secret name, which Ingress, Gateway or workloads use it, and whether it is immutable:
kubectl -n <namespace> get secret <secret> -o jsonpath='{.immutable}'Back up the current certificate and key as files (not as YAML - a dumped Secret contains fields that make re-applying it fail):
kubectl -n <namespace> get secret <secret> -o jsonpath='{.data.tls\.crt}' | base64 -d > old-tls.crt
kubectl -n <namespace> get secret <secret> -o jsonpath='{.data.tls\.key}' | base64 -d > old-tls.key
chmod 600 old-tls.keyStep-by-step certificate replacement
-
Check the new files - the key must belong to the certificate:
openssl pkey -in private.key -pubout | sha256sum openssl x509 -in fullchain.pem -noout -pubkey | sha256sum -
Update the Secret in place:
kubectl -n <namespace> create secret tls <secret> \ --cert=fullchain.pem --key=private.key \ --dry-run=client -o yaml | kubectl apply -f -This replaces only the data. Do not delete and re-create the Secret - that leaves a gap in which the Ingress has no certificate.
-
Immutable Secret: it cannot be changed. Create a new one and point the Ingress (or Gateway) at it:
kubectl -n <namespace> create secret tls <secret>-2026 --cert=fullchain.pem --key=private.key kubectl -n <namespace> patch ingress <ingress> --type=json \ -p '[{"op":"replace","path":"/spec/tls/0/secretName","value":"<secret>-2026"}]'Delete the old Secret once the new one is verified.
-
Activation:
- Ingress controllers such as ingress-nginx and Traefik watch Secrets and use the new certificate without a restart.
- A workload that mounts the Secret as a volume sees the new files after a short
delay - except with a
subPathmount, which never updates. - An application that reads the files only at start, or gets them through environment variables, needs a rollout:
kubectl -n <namespace> rollout restart deployment/<deployment> kubectl -n <namespace> rollout status deployment/<deployment>
Verify the new certificate
Check the certificate in the Secret without printing the key, then the hostname:
kubectl -n <namespace> get secret <secret> -o jsonpath='{.data.tls\.crt}' |
base64 -d | openssl x509 -noout -subject -issuer -enddate -fingerprint -sha256
openssl s_client -connect app.example.com:443 -servername app.example.com -showcerts </dev/nullThe first command shows the first certificate in tls.crt, the server certificate.
The served certificate must have the same fingerprint and the intermediates must be
sent. Also check the controller's and Pods' events and logs.
Rollback
Apply the backed-up files the same way as step 2 (or point the Ingress back to the old Secret after step 3), or revert the change in Git or Helm. Repeat the activation step if the workload needed one.
Common problems
tls.crtcontains only the server certificate, without intermediates.- The Secret was changed in the wrong context or namespace.
- cert-manager, GitOps or Helm restored the old Secret.
- The application reads the certificate only at start and no rollout happened.
- A
subPathmount never sees the update. - Broad RBAC lets unrelated users or workloads read the private key.
Automating certificate replacement with aethercert
The aethercert Kubernetes target creates or patches a kubernetes.io/tls Secret
through the API and can trigger rolling restarts for explicitly listed Deployments in
the same namespace.
See Deploy targets for the fields this preset takes, what it needs on the host, and how far it has been verified.