Kubernetes Kubernetes

Almacenamiento persistente: volúmenes, PersistentVolumes y claims

Mantén los datos vivos entre reinicios de Pods con PVCs y entiende cómo las StorageClasses unen las piezas.

14 min Intermedio

El sistema de archivos de un contenedor dura solo lo que dura el contenedor. Cuando se reemplaza un Pod, todo lo que escribió desaparece. Eso está bien para servidores web sin estado y es un problema para bases de datos, subidas de archivos y todo lo demás que debe sobrevivir. Esta guía muestra cómo Kubernetes adjunta almacenamiento duradero a los Pods.

Por qué el almacenamiento del contenedor no basta

Los contenedores están pensados para ser pequeños y desechables, así que poner datos dentro de ellos derrota el modelo. Los datos tienen que vivir fuera del contenedor y fuera del Pod, en almacenamiento que Kubernetes adjunta cuando arranca un Pod. Kubernetes es agnóstico sobre qué es ese almacenamiento: un disco en la nube, un recurso compartido de red o una unidad local. Tampoco hace copias de seguridad de los datos por ti. Eso sigue siendo tu trabajo.

La cadena de almacenamiento

Cuatro objetos trabajan juntos:

  • Una StorageClass describe un tipo de almacenamiento y cómo crearlo bajo demanda (por ejemplo, “volúmenes SSD rápidos del proveedor de nube”).
  • Un PersistentVolume (PV) es una pieza real de almacenamiento en el clúster.
  • Un PersistentVolumeClaim (PVC) es una petición de almacenamiento por parte de un usuario o una aplicación: “necesito 1 GiB que un nodo pueda leer y escribir”.
  • El Pod referencia el claim como un volumen y lo monta en un contenedor.
Contenedor ─ mountPath ─▶ Volumen del Pod ─▶ PVC ─ se enlaza con ─▶ PV ─▶ almacenamiento real
                                                                     ▲
                                              La StorageClass crea PV bajo demanda

Un PVC se enlaza exactamente con un PV. El Pod nunca hace referencia al PV, solo al claim, que es lo que mantiene a las aplicaciones independientes de los detalles del almacenamiento.

Solicita almacenamiento con un PVC

La mayoría de los clústeres tienen una StorageClass predeterminada que crea volúmenes bajo demanda (llamado aprovisionamiento dinámico), y minikube incluye una. Comprueba la tuya:

kubectl get storageclass

Luego pide almacenamiento:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
kubectl apply -f pvc.yaml
kubectl get pvc,pv

El claim debería pasar a Bound, y aparece un PV correspondiente. Algunas clases de almacenamiento esperan a que un Pod use realmente el claim antes de crear el volumen, así que Pending en este punto no es necesariamente un error.

Móntalo en un Pod y demuestra la persistencia

apiVersion: v1
kind: Pod
metadata:
  name: storage-demo
spec:
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]
      volumeMounts:
        - name: data
          mountPath: /data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: data

Escribe un archivo, destruye el Pod, vuelve a crearlo y comprueba que el archivo sobrevivió:

kubectl apply -f pod.yaml
kubectl exec storage-demo -- sh -c 'echo persisted > /data/proof.txt'
kubectl delete pod storage-demo
kubectl apply -f pod.yaml
kubectl exec storage-demo -- cat /data/proof.txt

El nuevo Pod es un contenedor completamente distinto, pero el claim, y los datos que hay detrás, se volvieron a adjuntar.

Modos de acceso, política de reclamación y volúmenes estáticos

  • Los modos de acceso indican cómo se puede montar un volumen. ReadWriteOnce significa lectura-escritura por un solo nodo, así que varios Pods de ese nodo aún pueden compartirlo. ReadOnlyMany y ReadWriteMany permiten muchos nodos, si el almacenamiento lo soporta. ReadWriteOncePod lo restringe a un solo Pod.
  • La política de reclamación (reclaim policy) decide qué ocurre con el volumen cuando se elimina el claim. Los volúmenes aprovisionados dinámicamente suelen tener Delete por defecto, lo que elimina el almacenamiento subyacente y sus datos. Usa Retain cuando quieras conservar los datos.
  • El aprovisionamiento estático significa que un administrador crea los PV a mano y los claims se enlazan con el que encaje. Un PV de tipo hostPath, que usa un directorio de un nodo, es una demo habitual, pero ata los datos a una sola máquina y solo es adecuado para desarrollo en un solo nodo.

Bases de datos y StatefulSets

Puedes montar un claim en los Pods de un Deployment, pero las réplicas de un Deployment son intercambiables e idénticas, y la mayoría de las bases de datos no funcionan así. Un StatefulSet está pensado para cargas de trabajo con estado. Da a cada Pod una identidad estable (db-0, db-1), los inicia y actualiza en orden y puede crear un PVC separado para cada réplica:

spec:
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 5Gi

Un StatefulSet gestiona la identidad y el almacenamiento, no la replicación de datos. Hacer que las réplicas sean consistentes entre sí es trabajo de la base de datos, razón por la cual ejecutar bases de datos en Kubernetes es más difícil que ejecutar servicios sin estado. Muchos equipos usan una base de datos administrada o un operator de base de datos, y mantienen las aplicaciones sin estado en el clúster.

Guías populares