
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Kubernetes stores all cluster state, including Secrets, as plaintext objects in etcd by default. If an attacker gains read access to the etcd data directory or a backup snapshot, they can extract every credential, TLS certificate, and API token without touching your application layer. To encrypt etcd secrets at rest, you must configure the API server’s EncryptionConfiguration resource so that sensitive data is written to disk in ciphertext rather than raw JSON. This guide walks through the exact configuration, key management, and verification steps required for production clusters in 2026.
Why should you encrypt etcd secrets at rest in Kubernetes?
Etcd is the single source of truth for your entire cluster. Without encryption at rest, anyone with filesystem access—whether through a compromised node, a leaked backup, or a misconfigured cloud storage bucket—can read every Secret in cleartext. In my work with SOC 2 and ISO 27001 audits across Nepal-based fintechs and global SaaS platforms, this is consistently the first finding auditors check. Compliance frameworks explicitly require cryptographic protection for stored credentials, and "we trust our infrastructure team" does not satisfy evidence requirements.
Beyond compliance, defense-in-depth demands this control. Network policies, RBAC, and pod security standards protect the API surface, but they do nothing if the underlying datastore is exposed. As discussed in Kubernetes secrets management done right, application-layer secret injection tools like Vault or External Secrets Operator complement but do not replace datastore encryption. You need both: external tools prevent secrets from living in manifests, while etcd encryption protects whatever still lands in the database.
How do you configure EncryptionConfiguration to encrypt etcd secrets at rest?
The EncryptionConfiguration is a structured YAML file read by the kube-apiserver at startup. It defines an ordered list of providers for each resource type. The API server uses the first provider for encryption and tries all listed providers in order for decryption, which enables safe key rotation.
Create the configuration file
Save this to /etc/kubernetes/enc/enc-config.yaml on each control plane node:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- kms:
name: aws-kms-provider
endpoint: unix:///var/run/kms-plugin/socket.sock
cachesize: 1000
timeout: 3s
- identity: {} The kms provider delegates envelope encryption to an external key management service via a gRPC plugin. The identity provider performs no encryption and exists solely as a fallback during rotation. Never place aescbc or secretbox above kms unless you are intentionally migrating away from managed keys.
Mount and reference the file in the API server
For kubeadm-managed clusters, edit /etc/kubernetes/manifests/kube-apiserver.yaml:
- Add a volume:
- name: enc-config\n hostPath:\n path: /etc/kubernetes/enc\n type: DirectoryOrCreate - Add a volumeMount to the container:
- name: enc-config\n mountPath: /etc/kubernetes/enc\n readOnly: true - Add the flag:
--encryption-provider-config=/etc/kubernetes/enc/enc-config.yaml - If using KMS v2 (recommended for 2026), also add:
--encryption-provider-config-automatic-reload=trueto allow config changes without full restart.
The kubelet watches the static manifest directory and restarts the API server pod automatically when the file changes. Expect 30–90 seconds of API unavailability during this restart; schedule it during a maintenance window.
Which encryption provider should you choose for etcd?
Kubernetes supports several providers, but only two are appropriate for production in 2026. The choice depends on your operational maturity, compliance requirements, and whether you can manage key lifecycle externally.
| Provider | Key Storage | Audit Trail | Rotation Complexity | Best For |
|---|---|---|---|---|
| KMS v2 (Recommended) | External (AWS KMS, GCP Cloud KMS, Azure Key Vault) | Yes — cloud provider logs every key operation | Low — rotate KEK in cloud console; API server auto-reloads | Production, SOC 2/ISO 27001, multi-team clusters |
| aescbc | Local file on control plane nodes | No — manual log correlation required | High — requires config edit + full re-encryption + restart | Air-gapped environments, labs, legacy clusters pre-v1.29 |
| identity | N/A (plaintext) | N/A | N/A | Decryption fallback during rotation only |
| secretbox | Local file | No | High | Deprecated for new deployments; use KMS v2 instead |
In practice, I recommend KMS v2 for every cluster that has internet connectivity and runs on a major cloud or hybrid platform with HSM-backed key management. The audit trail alone satisfies most compliance evidence requests without custom logging pipelines. Reserve aescbc for genuinely air-gapped government or industrial environments where external KMS is impossible—and pair it with rigorous key distribution procedures documented in your ISMS.
How do you rotate encryption keys without downtime?
Key rotation is where most teams break their clusters. The critical rule: never remove a provider that still holds live encrypted data. The API server decrypts using the first matching provider in the list, so you must maintain backward compatibility until every object has been re-encrypted.
Safe rotation procedure
- Add the new key as the first provider. Keep the old key second. The API server now encrypts new writes with the new key but can still decrypt old objects.
- Re-encrypt all existing secrets. Run:
kubectl get secrets --all-namespaces -o json | kubectl replace -f -. This reads each secret (decrypting with any available provider) and writes it back (encrypting with the new primary provider). For large clusters, batch this by namespace to avoid API throttling. - Verify ciphertext. Use
etcdctl get /registry/secrets/default/my-secret --print-value-only | hexdump -Cto confirm the stored value begins with the new provider’s prefix (e.g.,k8s:enc:kms:v2:aws-kms-provider:). - Remove the old provider from the configuration only after verification completes across all namespaces.
- Restart the API server if automatic reload is disabled.
This process is identical whether you rotate a cloud KEK version or swap local AES keys. The difference is that cloud KMS rotations often happen transparently on the provider side; you still need to trigger re-encryption in Kubernetes because the DEK wrapping metadata must update.
How do you verify that secrets are actually encrypted on disk?
Configuration alone is not proof. Auditors and security teams need binary evidence that plaintext no longer exists in etcd. This verification step is non-negotiable for Kubernetes RBAC and security hardening attestations.
Direct etcd inspection
# Access etcd with proper certs
ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get /registry/secrets/default/my-db-password \
--print-value-only | strings | head -5 If encryption is active, output will show binary gibberish and a provider prefix like k8s:enc:kms:v2:. If you see readable JSON with "password":"...", encryption is not applied to that object. Re-run the re-encryption command and check again.
Automated compliance checks
For continuous validation, integrate etcd encryption checks into your monitoring stack. A simple cron job that samples random secrets and validates the ciphertext prefix catches configuration drift before auditors do. Pair this with Prometheus metrics monitoring fundamentals to alert on API server encryption errors or KMS latency spikes that could indicate plugin failures.
Common mistakes when implementing etcd encryption
After reviewing dozens of cluster configurations, these errors appear repeatedly:
- Forgetting to re-encrypt existing secrets. Enabling encryption only affects new writes. Old secrets remain plaintext indefinitely. Always run the replacement command immediately after configuration.
- Storing encryption keys on the same disk as etcd data. With
aescbc, if your key file lives in/etc/kubernetes/enc/on the same volume as/var/lib/etcd/, a single disk compromise exposes everything. Use separate volumes with strict permissions (0600, owned by root). - Not testing decryption after KMS outages. If your cloud KMS becomes unreachable, the API server cannot decrypt existing secrets. Configure health checks and have a disaster recovery runbook that includes temporary identity-provider fallback for emergency access.
- Ignoring backup encryption. Etcd snapshots contain the same data as the live store. Ensure your backup toolchain (Velero, etcdctl snapshot, cloud-native backup) also encrypts artifacts at rest, or your encryption effort is bypassed entirely.
Next steps for securing your Kubernetes datastore
Encrypting etcd secrets at rest is foundational, but it is one layer in a broader security posture. Combine it with RBAC least privilege, network policies, pod security standards, and external secret stores to achieve genuine defense-in-depth. Document your encryption configuration, key rotation schedule, and verification procedures as part of your compliance evidence package—auditors will ask for them.
If you need help designing a compliant Kubernetes security architecture or validating your existing etcd encryption setup, reach out to discuss your cluster security requirements. I work with teams across Nepal and globally to build infrastructure that passes audits and survives incidents.