Active Nerds
Module #72 · beginner Article

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...

4 min read+10 XPPublished 2026-05-24

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:

  1. etcd encryption at rest (encrypt Secret objects in etcd)
  2. RBAC restricting get/list on secrets to only what needs it
  3. 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.