Volúmenes efímeros vs persistentes

Por defecto, los contenedores en Kubernetes tienen almacenamiento efímero: cuando el Pod muere, los datos desaparecen. Para aplicaciones con estado (bases de datos, sistemas de archivos, colas de mensajes) necesitamos almacenamiento persistente que sobreviva al ciclo de vida del Pod.

Kubernetes abstrae el almacenamiento con dos recursos clave: PersistentVolume (PV) y PersistentVolumeClaim (PVC). El PV es el recurso físico (un disco en la nube, un NFS, un hostPath), mientras que el PVC es la solicitud de almacenamiento que hace el usuario.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-postgres
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: standard
  hostPath:
    path: /data/postgres
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-postgres
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: standard

StatefulSet: aplicaciones con identidad y orden

Mientras que un Deployment es ideal para aplicaciones stateless (donde cualquier réplica es idéntica y reemplazable), un StatefulSet está diseñado para aplicaciones stateful. Cada Pod en un StatefulSet tiene una identidad única (nombre ordinal: postgres-0, postgres-1) y un storage persistente vinculado a esa identidad.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres
  replicas: 3
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:16
        env:
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: pg-secret
              key: POSTGRES_PASSWORD
        volumeMounts:
        - name: pgdata
          mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
  - metadata:
      name: pgdata
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 20Gi
      storageClassName: standard
# Orden de creación recomendado para PostgreSQL en Kubernetes
kubectl create secret generic pg-secret \
  --from-literal=POSTGRES_PASSWORD=miPassSegura

kubectl apply -f pv-pvc.yaml   # PV y PVC (opcional si usas StorageClass dinámico)
kubectl apply -f postgres-sts.yaml

# Verificar
kubectl get statefulset
kubectl get pods -l app=postgres   # postgres-0, postgres-1, postgres-2
kubectl get pvc                     # pgdata-postgres-0, pgdata-postgres-1...

# Conectarse al primer Pod
kubectl exec -it postgres-0 -- psql -U postgres

Diferencias clave StatefulSet vs Deployment:

  • Los Pods de un StatefulSet se crean en orden (0, 1, 2…) y se eliminan en orden inverso (2, 1, 0).
  • Cada Pod tiene un hostname estable (postgres-0.nombre-svc).
  • Los PVCs no se eliminan automáticamente al escalar hacia abajo — los datos persisten.
  • Para replicación de bases de datos, necesitas configurar la replicación a nivel de aplicación (no es automática).
Infografía Kubernetes: Volúmenes persistentes (PVC, PV) y StatefulSets
Infografía: Kubernetes: Volúmenes persistentes (PVC, PV) y StatefulSets