Kubernetes Secrets vs. ConfigMaps: Sensitive Data Storage and Base64 Limitations
Secrets store sensitive data (passwords, tokens, certificates) and are base64-encoded (NOT encrypted by default) — the real security comes from RBAC restrict...
Quick Answer: Secrets store sensitive data (passwords, tokens, certificates) and are base64-encoded (NOT encrypted by default) — the real security comes from RBAC restricting who can read them and enabling etcd encryption at rest.
Detailed Answer:
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
namespace: production
type: Opaque # Most common type
data:
# Values MUST be base64 encoded
username: YWRtaW4= # echo -n 'admin' | base64
password: cGFzc3dvcmQxMjM= # echo -n 'password123' | base64
stringData:
# stringData accepts plain text — K8s encodes it automatically
# Useful for readability; merged with data on apply
api-key: "my-plain-text-api-key"
# Create secrets imperatively (avoids plain text in shell history)
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password=password123
# Create from files (e.g., TLS certs)
kubectl create secret tls myapp-tls \
--cert=path/to/cert.crt \
--key=path/to/cert.key
# Create from .env file
kubectl create secret generic app-secrets \
--from-env-file=.env.production
# Decode a secret value
kubectl get secret db-credentials \
-o jsonpath='{.data.password}' | base64 --decode
Secret Types:
| Type | Use Case |
|---|---|
| Opaque | Generic key-value secrets (default) |
| kubernetes.io/tls | TLS certificates (cert + key) |
| kubernetes.io/dockerconfigjson | Registry pull credentials |
| kubernetes.io/service-account-token | SA tokens (auto-created) |
| kubernetes.io/ssh-auth | SSH private keys |
| kubernetes.io/basic-auth | Username/password pairs |
# Consuming secrets in pods
containers:
- name: app
# As individual env vars (avoid — visible in process list)
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
# As mounted files (preferred — better security, supports rotation)
volumeMounts:
- name: secrets-vol
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secrets-vol
secret:
secretName: db-credentials
defaultMode: 0400 # Restrictive permissions
The Hard Truth About K8s Secrets:
Base64 is encoding, NOT encryption. Anyone with kubectl get secret permission can read the value. Real secret security requires:
- etcd encryption at rest (encrypt Secret objects in etcd)
- RBAC restricting
get/liston secrets to only what needs it - External Secrets Operator pulling from AWS Secrets Manager (best practice for EKS)
Key Takeaway: Native Kubernetes Secrets are only as secure as your RBAC and etcd encryption — for production on EKS, use External Secrets Operator with AWS Secrets Manager instead.
Finished reading?
Mark as complete to claim your +10 XP and track progress.
