Working with Secrets and Sensitive Data
1. Creating Secret Templates
Example: Opaque Secret
apiVersion: v1
kind: Secret
metadata:
name: {{ include "myapp.fullname" . }}-secret
type: Opaque
stringData:
api-key: {{ required "apiKey required" .Values.apiKey | quote }}
db-url: {{ printf "postgres://%s:%s@db:5432/api" .Values.db.user .Values.db.password | quote }}
2. Encoding Secret Values
| Field | Encoding |
|---|---|
data | Base64-encoded values required; use | b64enc |
stringData | Plain strings; K8s base64-encodes on write |
3. Using External Secrets
Example: ExternalSecret CR
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ include "myapp.fullname" . }}
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secretsmanager
kind: ClusterSecretStore
target:
name: {{ include "myapp.fullname" . }}-secret
data:
- secretKey: api-key
remoteRef: { key: prod/api, property: apiKey }
4. Integrating with HashiCorp Vault
| Method | Pattern |
|---|---|
| Vault Agent Injector | Annotate pods; sidecar fetches secrets at runtime |
| External Secrets Operator | SecretStore kind: Vault |
| CSI Secrets Store | Mount as volume via secrets-store.csi.k8s.io |
5. Using SOPS for Encryption
Example: helm-secrets plugin
helm plugin install https://github.com/jkroepke/helm-secrets
sops -e -i values-prod.yaml # encrypt in place
helm secrets upgrade api ./chart -f secrets://values-prod.yaml
6. Managing TLS Certificates
Example: cert-manager Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ include "myapp.fullname" . }}-tls
spec:
secretName: {{ include "myapp.fullname" . }}-tls
issuerRef: { name: letsencrypt-prod, kind: ClusterIssuer }
dnsNames: [{{ .Values.host | quote }}]
7. Using Sealed Secrets
| Step | Command |
|---|---|
| Install controller | helm install sealed-secrets sealed-secrets/sealed-secrets -n kube-system |
| Encrypt | kubeseal -f secret.yaml > sealed.yaml |
| Commit | SealedSecret CR safe to store in Git |
| Controller decrypts | Produces a regular Secret in target namespace |
8. Passing Secrets via Values
Example: CI injection
# Never commit secrets — read from CI vault
helm upgrade --install api ./chart \
--set-file dbPassword=<(vault kv get -field=password kv/db)
9. Using Secret Files
| Flag | Use |
|---|---|
--set-file key=path | Read file as value (escapes contents) |
--values secrets-file.yaml | Pull from gitignored or SOPS-decrypted file |
10. Avoiding Hardcoded Secrets
Warning: Anything in
values.yaml, Chart.lock, or templates is plaintext in source control. Hard-coded credentials are the #1 chart vulnerability. Use external secret backends.