- A single-node kubeadm cluster (control plane) with terminal access on the control plane node.
- Root or sudo access to edit static pod manifests and move files on the host.
1) Create a Secret and inspect how it is stored
Create a Secret from a literal value:data is Base64-encoded, not encrypted):
Base64 encoding is not encryption. Anyone with read access to etcd or Secret manifests can decode the values. Never store raw Secret YAMLs with encoded data in public repositories.
2) Inspect how the Secret is stored in etcd (raw view)
etcd stores Kubernetes objects under keys such as/registry/secrets/<namespace>/<name>. To read that raw key you need etcdctl configured to use the v3 API and valid etcd client TLS certificates.
Install etcdctl (Debian/Ubuntu example):
ETCDCTL_API=3 and read the raw key (adjust paths and secret name). On kubeadm clusters, the apiserver-etcd-client certs are commonly accepted by etcd:
supersecret), demonstrating that direct etcd access with valid certs reveals Secret contents.
Reference: etcdctl v3 usage.
3) Check whether the API server is configured for encryption
The kube-apiserver enables encryption-at-rest using the--encryption-provider-config flag. On kubeadm single-node control planes the API server runs as a static pod; inspect the static pod manifest:
--encryption-provider-config=/path/to/enc.yaml in the command args. If it’s absent, encryption is not enabled.
Tip: You can also inspect the running process args after kube-apiserver is started:
4) Create an EncryptionConfiguration file
Create anEncryptionConfiguration file (example enc.yaml). Only resources listed under resources will be affected—here we list secrets. Provider order matters: the first provider is used for encrypting new writes; later providers are used for decryption of older records.
Example enc.yaml using aescbc plus an identity fallback. Replace the example base64 key with a securely generated 32-byte key encoded in base64:
identity: {}means “no encryption” as a fallback for decryption. Ifidentityis listed first, data will not be encrypted.aescbcrequires a 32-byte key; provide the key base64-encoded.
enc.yaml locally and move it to a directory the kube-apiserver static pod can mount (example /etc/kubernetes/enc):
5) Configure the kube-apiserver static pod to use the configuration
Edit/etc/kubernetes/manifests/kube-apiserver.yaml and make three changes:
- Add the
--encryption-provider-configflag in thecommandargs:
- Mount the host directory into the kube-apiserver container by adding a
volumeMountundercontainers[0].volumeMounts:
- Add a matching
volumesentry at the pod spec level:
Modifying the kube-apiserver manifest will restart the API server. On single-node clusters this causes a brief outage. Plan for downtime or perform changes during a maintenance window.
6) Verify the API server restarted with the encryption flag
After saving the manifest, verify the API server is running and that the--encryption-provider-config flag is present:
crictl ps, docker ps) and kubectl -n kube-system get pods after the API server is ready.
7) Create a new Secret (will be encrypted) and inspect etcd
Create a new Secret after the API server is configured for encryption:k8s:enc:aescbc:v1:key1: followed by ciphertext bytes. The plaintext topsecret will not appear in the raw etcd output.
Example (truncated hexdump):
8) Re-encrypt existing Secrets
Enabling encryption affects new writes only. Secrets created or written before enabling encryption remain in their original form in etcd until the resource is written again. Options to re-encrypt existing Secrets:- Reapply or replace a specific Secret to force a rewrite:
- Force an update with an annotation (no data change required):
- Reapply/replace all Secrets across all namespaces (use carefully — this rewrites all secret objects):
etcdctl method shown earlier.
Quick reference table
Summary & best practices
- Kubernetes Secrets are Base64-encoded by default (not encrypted). Protect etcd access and avoid committing Secrets into public repositories.
- Use the kube-apiserver
--encryption-provider-configflag with anEncryptionConfigurationto enable encryption-at-rest for resources such assecrets. - Provider order matters: the first provider is used for encrypting new writes; later providers are used for decryption.
- After enabling encryption, re-write existing objects to ensure they are stored encrypted in etcd.
- Securely store and rotate encryption keys regularly; follow your organization’s key management policies.
- Kubernetes: Encrypting Secret Data at Rest — https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/
- etcd: Interacting with etcd v3 — https://etcd.io/docs/