By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
A hyper-practical, zero-fluff guide for engineers in production
You’re deploying a microservice in Kubernetes, and your app needs: - Database credentials (username/password) - API keys (Stripe, Twilio, AWS) - Environment-specific configs (dev vs. prod URLs, feature flags)
Problem: If you hardcode these in your Docker image or YAML manifests, you violate security best practices (secrets in Git = bad). If you use plain Kubernetes ConfigMaps or Secrets, they’re: - Base64-encoded, not encrypted (anyone with kubectl get secret can decode them).- Mutable by default (accidental changes can break prod).- Stored in etcd (a single point of failure if compromised).
ConfigMaps
Secrets
kubectl get secret
Solution:- ConfigMap-immutable → Lock down configs to prevent drift.- Sealed-Secrets → Encrypt secrets so they can be safely committed to Git.
ConfigMap-immutable
Sealed-Secrets
Real-world scenario:You inherit a legacy Kubernetes cluster where: - Secrets are stored in plaintext in Helm charts.- A junior dev accidentally overwrites a ConfigMap in prod, causing an outage.- Your security team flags Git history for exposed credentials.
ConfigMap
This guide fixes all three.
kubectl edit
immutable: true
Secret
kubectl get secret -o yaml
SealedSecret
sealed-secrets
kubeseal
SealedSecrets
etcd
RBAC
get
kubectl
brew install kubeseal
# Install the controller in the cluster kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.22.0/controller.yaml # Verify it's running kubectl get pods -n kube-system | grep sealed-secrets
Expected output:
sealed-secrets-controller-abc123 1/1 Running 0 1m
# Fetch the public key from the controller kubeseal --fetch-cert > pub-cert.pem
Why? kubeseal needs this to encrypt secrets locally.
# configmap-immutable.yaml apiVersion: v1 kind: ConfigMap metadata: name: app-config data: LOG_LEVEL: "info" API_URL: "https://api.example.com" immutable: true # <-- This locks it down
kubectl apply -f configmap-immutable.yaml
Verify:
kubectl get configmap app-config -o yaml | grep immutable
# secret.yaml apiVersion: v1 kind: Secret metadata: name: db-credentials type: Opaque data: username: YWRtaW4= # echo -n "admin" | base64 password: cGFzc3dvcmQxMjM= # echo -n "password123" | base64
⚠️ Never commit this to Git!
kubeseal --format yaml --cert pub-cert.pem < secret.yaml > sealed-secret.yaml
What just happened?- kubeseal encrypted the Secret into a SealedSecret.- The output (sealed-secret.yaml) is safe to commit to Git.
sealed-secret.yaml
kubectl apply -f sealed-secret.yaml
kubectl get sealedsecret kubectl get secret db-credentials -o yaml
Expected output:- The SealedSecret is created.- The Secret is automatically decrypted by the controller.
# pod.yaml apiVersion: v1 kind: Pod metadata: name: app-pod spec: containers: - name: app image: nginx envFrom: - configMapRef: name: app-config env: - name: DB_USERNAME valueFrom: secretKeyRef: name: db-credentials key: username - name: DB_PASSWORD valueFrom: secretKeyRef: name: db-credentials key: password
kubectl apply -f pod.yaml
kubectl exec -it app-pod -- env | grep DB_
DB_USERNAME=admin DB_PASSWORD=password123
prod-db-credentials-sealed
environment: prod
bash kubectl logs -n kube-system sealed-secrets-controller-abc123
kubectl get pods -n kube-system
kubeseal --fetch-cert
❌ Trap: "Use RBAC" (RBAC restricts access but doesn’t prevent edits).
"What’s the difference between a Secret and a SealedSecret?"
❌ Trap: "They’re the same" (they’re not—SealedSecret is encrypted).
"How do you rotate a SealedSecret key?"
Challenge:You have a Secret with an API key (api-key: c3VwZXItc2VjcmV0). Seal it, deploy it, and verify the pod can access it.
api-key: c3VwZXItc2VjcmV0
Solution:
# 1. Create secret.yaml echo "apiVersion: v1 kind: Secret metadata: name: api-key type: Opaque data: key: c3VwZXItc2VjcmV0" > secret.yaml # 2. Seal it kubeseal --format yaml --cert pub-cert.pem < secret.yaml > sealed-secret.yaml # 3. Deploy kubectl apply -f sealed-secret.yaml # 4. Verify kubectl get secret api-key -o yaml | grep key
Why it works:- kubeseal encrypts the Secret into a SealedSecret.- The controller decrypts it into a Secret in the cluster.
kubeseal --cert pub-cert.pem
kubectl get sealedsecret
echo -n "value" | base64
kubectl logs -n kube-system sealed-secrets-controller
Final Tip:Always test SealedSecrets in a non-prod cluster first. If the controller isn’t running, your SealedSecret won’t decrypt—and your app will fail silently. ?
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.