iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Secrets

Kubernetes Secrets hold sensitive data — tokens, passwords, certs. Base64-encoded (NOT encrypted) by default; encrypt at rest in etcd, mount as env vars or files, never log them.

Create, mount, sealed / external secrets

EXAMPLE
# 1) Create a Secret (literals)
kubectl create secret generic db-credentials \
    --from-literal=DB_USER=app \
    --from-literal=DB_PASSWORD='s3cr3t-p@ss'

# From files
kubectl create secret generic tls-key --from-file=tls.crt --from-file=tls.key

# 2) YAML form — IMPORTANT: base64 encode values
echo -n 's3cr3t-p@ss' | base64
apiVersion: v1
kind: Secret
metadata:
    name: db-credentials
type: Opaque
data:
    DB_USER:     YXBw
    DB_PASSWORD: czNjcjN0LXBAc3M=
# Or use 'stringData' to skip base64 (Kubernetes encodes for you):
stringData:
    DB_USER:     app
    DB_PASSWORD: 's3cr3t-p@ss'

# 3) Consume as ENV vars
apiVersion: apps/v1
kind: Deployment
metadata: { name: web }
spec:
    selector: { matchLabels: { app: web } }
    template:
        metadata: { labels: { app: web } }
        spec:
            containers:
                - name: web
                  image: myapp:1.0
                  envFrom:
                      - secretRef: { name: db-credentials }    # all keys → env vars
                  env:
                      - name: STRIPE_KEY
                        valueFrom:
                            secretKeyRef:
                                name: stripe
                                key:  api_key

# 4) Consume as a FILE (volume mount)
spec:
    containers:
        - name: app
          image: myapp:1.0
          volumeMounts:
              - name:      tls-files
                mountPath: /etc/tls
                readOnly:  true
    volumes:
        - name: tls-files
          secret:
              secretName: tls-key
              items:
                  - key:  tls.crt
                    path: tls.crt
                    mode: 0400
                  - key:  tls.key
                    path: tls.key
                    mode: 0400
              defaultMode: 0400

# 5) Built-in Secret TYPES — Kubernetes-aware schemas
# Opaque                        — generic (default)
# kubernetes.io/tls             — { tls.crt, tls.key } for Ingress TLS
# kubernetes.io/dockerconfigjson — pull secret for private registries
# kubernetes.io/basic-auth       — { username, password }
# kubernetes.io/ssh-auth         — { ssh-privatekey }

# Image pull secret
kubectl create secret docker-registry ghcr-pull \
    --docker-server=ghcr.io \
    --docker-username=USER \
    --docker-password=TOKEN \
    --docker-email=ops@example.com

# Attach to a Pod
spec:
    imagePullSecrets:
        - name: ghcr-pull

# 6) Secret rotation
# Pods mounted as VOLUMES see updates within ~60s (kubelet polls)
# Pods consuming as ENV VARS do NOT see updates — restart needed
kubectl rollout restart deployment/web

# Versioned name pattern (no in-place rotation):
#   db-credentials-v3 → bump the version, update Deployment spec → rolling restart

# 7) Immutable secrets (perf + safety)
apiVersion: v1
kind: Secret
metadata: { name: db-credentials-v3 }
immutable: true
data: { ... }
# Reduces kube-apiserver/kubelet load; prevents accidental edits.

# === Encryption + Access ===

# 8) Encrypt secrets at rest in etcd
# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
    - resources: [secrets]
      providers:
        - aescbc:
            keys:
                - name: key1
                  secret: <base64-32-byte-key>
        - identity: {}
# Reference in kube-apiserver: --encryption-provider-config=/etc/kubernetes/encryption-config.yaml
# Most managed services (EKS, GKE, AKS) offer this with KMS-backed keys.

# 9) RBAC — restrict who can read secrets
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: { name: secret-reader, namespace: app }
rules:
    - apiGroups: ['']
      resources: [secrets]
      resourceNames: [db-credentials]    # restrict to specific secret
      verbs: [get]

# === Better: external secret managers ===

# 10) SealedSecrets (Bitnami) — encrypt secrets in git
# Install the SealedSecrets controller in the cluster
kubeseal --format yaml < secret.yaml > sealed-secret.yaml
# sealed-secret.yaml is safe to commit; controller decrypts in-cluster.

# 11) External Secrets Operator — sync from AWS Secrets Manager, GCP Secret Manager, Vault, Doppler
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata: { name: aws-secretsmanager }
spec:
    provider:
        aws:
            service: SecretsManager
            region:  us-east-1
            auth:
                jwt:
                    serviceAccountRef: { name: external-secrets }

---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata: { name: db-credentials }
spec:
    refreshInterval: '1h'
    secretStoreRef: { name: aws-secretsmanager, kind: SecretStore }
    target:
        name: db-credentials                  # creates a k8s Secret
    data:
        - secretKey: DB_USER
          remoteRef: { key: prod/app/db, property: user }
        - secretKey: DB_PASSWORD
          remoteRef: { key: prod/app/db, property: password }

# Rotation in the cloud → automatic propagation into the cluster.

# 12) HashiCorp Vault — agent injector pattern
# Pods get secrets injected as files by the Vault agent sidecar.
# Best for high-security environments + dynamic database creds.

# === Best practices ===

# 1. NEVER commit raw Secret manifests to git — use SealedSecrets or external-secrets
# 2. Mount as FILES with 0400 mode (instead of env vars) — fewer ways to leak
# 3. Per-Service Account credentials, not per-cluster
# 4. Restrict via RBAC — Pod can only read secrets it needs
# 5. Enable encryption-at-rest in etcd (KMS-backed in managed clusters)
# 6. Rotate regularly + automate (External Secrets + cloud rotation policies)
# 7. Audit access — kube-apiserver audit logs to SIEM
# 8. Don't print secrets to logs — use stdout-safe values only
# 9. Use immutable secrets for stable references
# 10. PolicyAgent (Kyverno, OPA Gatekeeper) — block plain Secret manifests in CI

Why it matters

Stop committing raw Secret manifests. Use SealedSecrets (encrypted in git) or External Secrets (synced from a cloud manager) so rotation in the source of truth flows into the cluster automatically.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
kubectl create secret generic db-pass --from-literal=password=s3cret
# Mount the same way as ConfigMaps.
Try it Yourself »

Discussion

Loading…