Una guía sencilla para implementar almacenamiento persistente en Kubernetes

Aprende cómo implementar almacenamiento persistente para aplicaciones con estado en Kubernetes. Esta guía desmitifica los PersistentVolumes (PVs) y PersistentVolumeClaims (PVCs), explicando los modos de acceso y las StorageClasses. Incluye ejemplos prácticos en YAML para definir PVCs y montar almacenamiento en tus Pods, lo que permite una persistencia de datos fiable en tus aplicaciones en contenedores.

Una Guía Sencilla para Implementar Almacenamiento Persistente en Kubernetes

El almacenamiento persistente en Kubernetes resuelve un problema simple: tu contenedor puede desaparecer, pero tus archivos de base de datos, cargas o datos de cola no pueden. Los Pods sin estado pueden ser reemplazados en cualquier momento. Las aplicaciones con estado necesitan almacenamiento que sobreviva a reinicios de Pods, reasignaciones y mantenimiento de nodos.

Esta guía explica PersistentVolumes (PV), PersistentVolumeClaims (PVC), modos de acceso y StorageClasses con YAML práctico que puedes adaptar para una carga de trabajo real.

Entendiendo PersistentVolumes (PV) y PersistentVolumeClaims (PVC)

Antes de montar almacenamiento en un Pod, conoce qué objeto tiene qué trabajo:

  • PersistentVolume (PV): Un PV es una pieza de almacenamiento en el clúster que ha sido aprovisionada por un administrador o aprovisionada dinámicamente usando StorageClasses. Los PV son recursos del clúster, muy similares a los Nodos. Tienen un ciclo de vida independiente de cualquier Pod individual que use el PV. Los PV abstraen los detalles de implementación del almacenamiento subyacente (por ejemplo, NFS, iSCSI, almacenamiento en bloque del proveedor de la nube).
  • PersistentVolumeClaim (PVC): Un PVC es una solicitud de almacenamiento por parte de un usuario. Consume recursos de almacenamiento que están disponibles en el clúster como PV. Los PVC son similares a los Pods en que consumen recursos de cómputo, y están limitados a un namespace. Un PVC especifica la capacidad de almacenamiento deseada, los modos de acceso y, opcionalmente, una StorageClass.

Esta separación permite que los equipos de plataforma gestionen los detalles de almacenamiento mientras que los equipos de aplicación solicitan la capacidad y el patrón de acceso que necesitan.

Conceptos Clave: Modos de Acceso y StorageClasses

Dos configuraciones controlan la mayoría del comportamiento de los PVC: cómo se puede montar el volumen y qué backend de almacenamiento debe crearlo.

Modos de Acceso

Los modos de acceso definen cómo se puede montar un volumen en un Pod. Los modos de acceso disponibles son:

  • ReadWriteOnce (RWO): El volumen se puede montar como lectura-escritura por un solo nodo.
  • ReadOnlyMany (ROX): El volumen se puede montar como solo lectura por muchos nodos.
  • ReadWriteMany (RWX): El volumen se puede montar como lectura-escritura por muchos nodos.
  • ReadWriteOncePod (RWOP): El volumen se puede montar como lectura-escritura por un solo Pod. Esto es útil cuando necesitas un comportamiento de escritor único más estricto y tu controlador CSI lo soporta.

Es importante tener en cuenta que el soporte real para estos modos depende del proveedor de almacenamiento subyacente.

StorageClasses

Una StorageClass proporciona una forma para que los administradores describan las "clases" de almacenamiento que ofrecen. Diferentes clases pueden corresponder a niveles de calidad de servicio, políticas de respaldo o políticas arbitrarias determinadas por los administradores del clúster. Una StorageClass tiene un aprovisionador que aprovisiona almacenamiento y un conjunto de parámetros para el aprovisionador. Cuando se crea un PVC sin un PV específico y solicita una StorageClass, Kubernetes aprovisionará dinámicamente un PV usando la StorageClass especificada.

Implementando Almacenamiento Persistente Paso a Paso

Vamos a recorrer un escenario común: solicitar y usar almacenamiento persistente para un Pod.

Paso 1: Definir un PersistentVolumeClaim (PVC)

Primero, necesitas crear un PVC que especifique tus requisitos de almacenamiento. Este PVC actuará como la solicitud de almacenamiento para tu aplicación.

Ejemplo pvc.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

En este ejemplo:

  • name: my-pvc: Este es el nombre de nuestro PVC.
  • accessModes: - ReadWriteOnce: Estamos solicitando almacenamiento que se pueda montar como lectura-escritura por un solo nodo.
  • resources.requests.storage: 1Gi: Estamos solicitando 1 Gigabyte de almacenamiento.

Aplicando el PVC:

Guarda el contenido anterior en un archivo llamado pvc.yaml y aplícalo a tu clúster:

kubectl apply -f pvc.yaml

Después de aplicar, puedes verificar el estado del PVC:

kubectl get pvc my-pvc

Deberías ver una salida que indica que el PVC está Bound si hay un PV adecuado disponible o ha sido aprovisionado dinámicamente.

Paso 2: Crear un Pod que Use el PVC

Ahora, creemos un Pod que utilizará el almacenamiento solicitado por nuestro PVC. Montaremos el volumen proporcionado por el PVC en un directorio específico dentro de nuestro contenedor.

Ejemplo pod-with-pv.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: my-stateful-pod
spec:
  containers:
    - name: my-container
      image: nginx
      ports:
        - containerPort: 80
      volumeMounts:
        - name: my-persistent-storage
          mountPath: /usr/share/nginx/html
  volumes:
    - name: my-persistent-storage
      persistentVolumeClaim:
        claimName: my-pvc

En este ejemplo:

  • volumes: Definimos un volumen llamado my-persistent-storage.
  • persistentVolumeClaim.claimName: my-pvc: Esto vincula nuestro volumen al PVC que creamos anteriormente.
  • volumeMounts: Dentro de la definición del contenedor, especificamos dónde se debe montar este volumen (mountPath: /usr/share/nginx/html).

Aplicando el Pod:

Guarda el contenido anterior en un archivo llamado pod-with-pv.yaml y aplícalo:

kubectl apply -f pod-with-pv.yaml

Ahora, tu contenedor nginx tendrá acceso al almacenamiento persistente definido por my-pvc en la ruta /usr/share/nginx/html. Cualquier dato escrito en esta ruta dentro del contenedor se conservará incluso si el Pod se elimina y se recrea, siempre que el PVC y su PV subyacente permanezcan.

Aprovisionamiento Dinámico con StorageClasses

Crear PVs manualmente puede ser tedioso. Kubernetes ofrece aprovisionamiento dinámico, donde los PVs se crean automáticamente cuando un PVC solicita almacenamiento que no puede ser satisfecho por los PVs existentes. Esto se logra a través de StorageClasses.

La mayoría de los proveedores de la nube (AWS, GCP, Azure) ofrecen StorageClasses preconfiguradas. Puedes inspeccionarlas con:

kubectl get storageclass

Para usar el aprovisionamiento dinámico, simplemente agregas un campo storageClassName a tu definición de PVC:

Ejemplo pvc-dynamic.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-dynamic-pvc
spec:
  storageClassName: standard # Reemplaza 'standard' con un nombre real de StorageClass
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Cuando aplicas este PVC, Kubernetes buscará una StorageClass llamada standard (o cualquier nombre que especifiques) e indicará a su aprovisionador que cree un nuevo PV de 5Gi y lo vincule a este PVC.

Consejos y Mejores Prácticas

  • Elige el Modo de Acceso Correcto: Considera cuidadosamente el modo de acceso requerido por tu aplicación. ReadWriteOnce es común para bases de datos de una sola réplica, mientras que ReadWriteMany es necesario para sistemas de archivos compartidos utilizados por múltiples Pods.
  • Comprende el Rendimiento del Almacenamiento: Diferentes proveedores de almacenamiento y StorageClasses ofrecen características de rendimiento variables (IOPS, rendimiento). Elige una StorageClass que cumpla con las necesidades de rendimiento de tu aplicación.
  • Estrategia de Respaldo: El almacenamiento persistente no significa automáticamente respaldo. Implementa una estrategia de respaldo robusta para tus volúmenes persistentes, especialmente para datos críticos.
  • Política de Reclamación de PV: Los PV tienen una persistentVolumeReclaimPolicy, comúnmente Delete o Retain. Los volúmenes aprovisionados dinámicamente a menudo usan la política de reclamación definida por su StorageClass. La antigua política Recycle está obsoleta y no debe usarse para nuevas configuraciones.
  • Consideraciones de Namespace: Los PVC tienen ámbito de namespace. Asegúrate de que tu Pod y PVC estén en el mismo namespace para que ocurra la vinculación.

Conclusión

El almacenamiento persistente en Kubernetes comienza con un PVC, un montaje de Pod y una StorageClass que coincida con tu carga de trabajo. Para una base de datos de una sola réplica, comienza con una reclamación ReadWriteOnce, verifica que llegue al estado Bound, móntala en el contenedor y haz que las copias de seguridad sean parte del diseño desde el primer día.