Secrets#
In the YAML config chapter we saw that ConfigMaps are a great way to manage innocent environment variables - ports, URLs, feature flags. But we also learned that ConfigMaps are not encrypted, and anyone with access to the cluster can read them.
Secrets are the Kubernetes object designed for sensitive data: passwords, tokens, and keys. Functionally, they look a lot like ConfigMaps. The differences are:
- Values are stored base64-encoded in the object
- Access can be restricted with RBAC (who can read which secrets)
- etcd can be configured to encrypt secret data at rest
Creating a Secret#
The imperative way:
kubectl create secret generic db-auth \
--from-literal=username=admin \
--from-literal=password=correct-horse-battery-stapleOr the declarative way, in YAML:
apiVersion: v1
kind: Secret
metadata:
name: db-auth
type: Opaque
data:
password: Y29ycmVjdC1ob3JzZS1iYXR0ZXJ5LXN0YXBsZQ==Notice the data values are base64 encoded. You can produce them like this:
echo -n "correct-horse-battery-staple" | base64There’s also a stringData field where you can put plaintext values and Kubernetes will encode them for you when the secret is stored:
stringData:
password: correct-horse-battery-stapleLet’s inspect what we created:
kubectl get secrets
kubectl describe secret db-authdescribe won’t show you the values, just the keys and their byte sizes. To see the raw (encoded) data:
kubectl get secret db-auth -o yamlUsing a Secret#
Just like ConfigMaps, secrets can be injected into pods in a few ways.
As Environment Variables#
Use secretKeyRef instead of configMapKeyRef:
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-auth
key: passwordOr import all keys with envFrom:
envFrom:
- secretRef:
name: db-authAs Files#
You can also mount a secret as a volume, and each key becomes a file:
volumes:
- name: db-auth-vol
secret:
secretName: db-authBase64 Şifreleme Değildir!#
Dikkat: Secret değerlerinin base64 ile kodlanmış olması onları güvenli yapmaz. Base64 sadece bir encoding tekniğidir, şifreleme (encryption) değildir. kubectl get secret db-auth -o yaml çıktısını görüp base64 -d çalıştırabilen herkes değerleri geri okur.
Yani secret’ların “güvenliği” şunlardan gelir:
- RBAC: Kimin hangi secret’ı okuyabildiğini kısıtlar - rbac notlarında ele aldim.
- etcd encryption at rest: Disk üzerinde şifreli saklanması
- Least privilege: Secret’ları sadece ihtiyacı olan deployment’ların namespace’lerinde tutmak
Kısacası: kubectl erişimi olan birinden base64 korumaz, ama yanlışlıkla bir ConfigMap’te password: gizli-parola yazmaktan daha iyidir.
Alternatives#
If you need more serious secret management, there are third-party options:
- Sealed Secrets: Encrypt secrets in your git repo, only the cluster can decrypt them
- External Secrets Operator: Sync secrets from external stores like AWS Secrets Manager or HashiCorp Vault
In most production clusters I’d recommend one of these over raw Secrets, especially if secrets live in your git repos.
Assignment#
Let’s create a secret for the synergychat-api. Create a file called api-secret.yaml:
apiVersion:v1kind:Secretmetadata/name:synergychat-api-secrettype:Opaquedata/API_KEY: base64-encoded fake token of your choice (echo -n "xxx" | base64)
Apply it:
kubectl apply -f api-secret.yaml
kubectl get secretsNow connect it to the api deployment. In api-deployment.yaml, add to the container’s env section:
- name: API_KEY
valueFrom:
secretKeyRef:
name: synergychat-api-secret
key: API_KEYApply, then prove the env var made it into the container:
kubectl exec <pod-name> -- printenv | grep API_KEYIf you see your token, congrats - your deployment is pulling sensitive config from a Secret instead of a plaintext ConfigMap.
for more rbac