Encrypting Kubernetes Secrets at rest in etcd
Kubernetes Secrets are only base64 by default. Turn on an EncryptionConfiguration and rotate the key without downtime.
A Kubernetes Secret is not encrypted — it is base64-encoded, which is not the same thing. Anyone who can read etcd (a backup, a snapshot, a compromised control-plane node) can read every secret in the cluster. An EncryptionConfiguration on the API server fixes that by encrypting Secrets before they hit etcd.
ETCDCTL_API=3 etcdctl get /registry/secrets/shop/db | stringsk8s Secret ... password: c3VwZXItc2VjcmV0echo c3VwZXItc2VjcmV0 | base64 -d -> super-secretTurn on encryption at rest
apiVersion: apiserver.config.k8s.io/v1kind: EncryptionConfigurationresources:- resources: [secrets]providers:- secretbox:keys:- name: key1secret: <32-byte base64 key>- identity: {} # read old plaintext during rollout
Point the API server at it with --encryption-provider-config=/etc/kubernetes/enc/enc.yaml and restart. New Secrets are now encrypted; existing ones are still plaintext until you rewrite them.
Encrypt what already exists
kubectl get secrets -A -o json | kubectl replace -f -each secret re-written through the encrypting API serververify with etcdctl again — the value is now ciphertextRotating the key
Add the new key first in the provider list, restart, rewrite all secrets, then remove the old key on a second pass. Keeping identity last during the first rollout lets the API server still read anything not yet encrypted.