⚙️ ConfigMap
No sensibles
Variables de entorno, archivos de configuración, flags de feature. En texto plano, visible para cualquiera con acceso al namespace.
env var · envFrom · volumeMount (archivo)
🔐 Secret
Sensibles
Passwords, API keys, certs TLS, tokens. Almacenado en Base64 (no encriptado por defecto en Etcd). Usa Sealed Secrets o Vault para cifrado real.
env var · envFrom · volumeMount (archivo)
apiVersion: v1
kind: ConfigMap
metadata: { name: app-config }
data:
APP_ENV: production
LOG_LEVEL: info
app.properties: |
timeout=30
max-connections=100
apiVersion: v1
kind: Secret
metadata: { name: db-secret }
type: Opaque
data:
DB_PASSWORD: bWktcGFzc3dvcmQ=
DB_URL: cG9zdGdyZXMuZXhhbXBsZQ==
spec:
containers:
- name: app
envFrom:
- configMapRef: { name: app-config }
- secretRef: { name: db-secret }
volumeMounts:
- name: config-vol
mountPath: /etc/config
volumes:
- name: config-vol
configMap: { name: app-config }
Flujo de aprovisionamiento de almacenamiento persistente
👤
Developer
define PVC
"necesito 10Gi SSD"
→
📋
PVC
PersistentVolumeClaim
solicitud de almacenamiento
→
⚙️
StorageClass
provisioner automático
AWS EBS / GCP PD / NFS
→
💾
PV
PersistentVolume
disco real aprovisionado
🔑 El desarrollador solo ve el PVC — no le importa qué disco físico hay detrás. El Admin configura StorageClasses una vez. El PVC sobrevive al Pod — el disco persiste aunque el Pod se reinicie o se mueva de Node.
Reclaim Policy
Access Modes
StorageClass
PV es el disco real (aprovisionado por el admin o el StorageClass provisioner). PVC es la petición del desarrollador. K8s los empareja automáticamente por capacidad, access mode y StorageClass.
Access Modes:
ReadWriteOnce (RWO) → un Node puede escribir (EBS, discos)
ReadOnlyMany (ROX) → N Nodes pueden leer
ReadWriteMany (RWX) → N Nodes pueden escribir (NFS, EFS)
Reclaim Policy: Retain (datos seguros) vs Delete (se borra el disco al borrar PVC).
emptyDir
hostPath
persistentVolumeClaim
Dentro de un Pod puedes montar distintos tipos de volumen según la necesidad. No todos persisten cuando el Pod muere — elige el tipo correcto para cada caso.
emptyDir → temporal, vive con el Pod (caché, tmp)
hostPath → monta un directorio del Node ⚠️
configMap → monta ConfigMap como archivos
secret → monta Secret como archivos
persistentVolumeClaim → disco persistente real
projected → combina varios en uno
apiVersion: apps/v1
kind: StatefulSet
metadata: { name: postgres }
spec:
replicas: 1
selector: { matchLabels: { app: postgres } }
template:
spec:
containers:
- name: postgres
image: postgres:15
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef: { name: db-secret, key: DB_PASSWORD }
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata: { name: postgres-data }
spec:
accessModes: [ReadWriteOnce]
storageClassName: fast-ssd
resources:
requests: { storage: 20Gi }
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS
postgres-data-postgres-0 Bound pvc-abc123 20Gi RWO
kubectl delete pod postgres-0
⚙️
ConfigMap vs env vars en Dockerfile
Nunca hardcodees config en la imagen Docker. Un ConfigMap en K8s te permite cambiar config sin reconstruir la imagen. La misma imagen va a dev, QA y prod — solo cambia el ConfigMap.
🔐
Secret ≠ seguro por defecto
Base64 no es cifrado — es encoding. En Etcd, los Secrets están en claro por defecto. Para producción usa Sealed Secrets (Bitnami) o External Secrets Operator integrado con Vault o AWS Secrets Manager.
💾
PVC — el disco sobrevive al Pod
Si el Pod de postgres muere, el PVC permanece. K8s crea un nuevo Pod y monta el mismo disco. Los datos no se pierden. Esto es exactamente lo que no puedes hacer con un Deployment normal.