Capitulo 11: Volumenes Persistentes

Por: Artiko
k3skubernetesstoragepersistent-volumes

Capitulo 11: Volumenes Persistentes

< Volver al Indice del Tutorial

El Problema del Almacenamiento Efimero

Los contenedores son efimeros por diseno. Cuando un pod se reinicia, se elimina o se reprograma en otro nodo, todo su sistema de archivos se destruye y se crea uno nuevo desde la imagen.

Esto significa que cualquier dato escrito dentro del contenedor (base de datos, archivos subidos, logs) desaparece con el pod. Para aplicaciones que necesitan persistir datos, Kubernetes ofrece el sistema de volumenes persistentes.

Local-Path Provisioner en K3s

K3s incluye el local-path provisioner de Rancher preinstalado. Este provisioner crea volumenes en el sistema de archivos local del nodo, especificamente en:

/var/lib/rancher/k3s/storage/

Verifica que esta disponible:

kubectl get storageclass

Veras una StorageClass llamada local-path marcada como (default):

NAME                   PROVISIONER             RECLAIMPOLICY   AGE
local-path (default)   rancher.io/local-path   Delete          30d

Esto significa que cualquier PVC que crees sin especificar StorageClass usara local-path automaticamente.

Conceptos Fundamentales

PersistentVolume (PV)

Un PersistentVolume es un recurso de almacenamiento en el cluster, similar a un nodo que provee computo. Es el “disco” fisico (o logico) disponible.

Con el local-path provisioner, los PV se crean automaticamente cuando un PVC los solicita. No necesitas crearlos manualmente en la mayoria de los casos.

PersistentVolumeClaim (PVC)

Un PVC es una solicitud de almacenamiento hecha por un pod. Especifica cuanto espacio necesita y con que modo de acceso. Es la “peticion” que un pod hace para obtener un disco.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: datos-app
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Al crear este PVC, el local-path provisioner automaticamente crea un PV y lo asocia (binding).

kubectl apply -f datos-app-pvc.yaml
kubectl get pvc

La columna STATUS debe mostrar Bound.

StorageClass

Una StorageClass define el tipo de almacenamiento disponible y como se provisiona. El local-path provisioner tiene su propia StorageClass que soporta provisionamiento dinamico: los PV se crean bajo demanda cuando aparece un PVC.

En clusters con almacenamiento externo (NFS, Longhorn, Ceph), tendrias multiples StorageClasses. En K3s con local-path solo tienes una por defecto.

Si necesitas especificar la StorageClass explicitamente:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: datos-app
spec:
  storageClassName: local-path
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Access Modes

Los modos de acceso determinan como los pods pueden usar el volumen:

ModoAbreviaturaDescripcion
ReadWriteOnceRWOUn solo nodo puede montar el volumen en lectura/escritura
ReadOnlyManyROXMultiples nodos pueden montar el volumen en solo lectura
ReadWriteManyRWXMultiples nodos pueden montar en lectura/escritura

El local-path provisioner de K3s solo soporta ReadWriteOnce porque los datos viven en el disco local de un nodo especifico. Para RWX necesitarias soluciones como NFS o Longhorn.

Reclaim Policies

La politica de reclamacion define que pasa con el PV cuando se elimina el PVC asociado:

Para datos criticos, cambia la politica a Retain:

kubectl patch pv <nombre-pv> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'

Montar un PVC en un Pod

Para usar un PVC en un pod, lo declaras en volumes y lo montas en un contenedor con volumeMounts:

apiVersion: v1
kind: Pod
metadata:
  name: app-con-datos
spec:
  containers:
    - name: app
      image: nginx:alpine
      volumeMounts:
        - name: almacenamiento
          mountPath: /datos
  volumes:
    - name: almacenamiento
      persistentVolumeClaim:
        claimName: datos-app

El contenedor vera el volumen montado en /datos. Todo lo que escriba ahi persiste aunque el pod se reinicie.

Ejemplo Completo

Vamos a crear una aplicacion que escribe datos y demuestra que sobreviven a reinicios del pod.

Primero el PVC:

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

Ahora un Deployment que usa el PVC:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: contador-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: contador
  template:
    metadata:
      labels:
        app: contador
    spec:
      containers:
        - name: contador
          image: busybox
          command: ["/bin/sh", "-c"]
          args:
            - |
              if [ ! -f /datos/contador.txt ]; then
                echo "0" > /datos/contador.txt
              fi
              while true; do
                VALOR=$(cat /datos/contador.txt)
                NUEVO=$((VALOR + 1))
                echo "$NUEVO" > /datos/contador.txt
                echo "Contador: $NUEVO"
                sleep 5
              done
          volumeMounts:
            - name: almacenamiento
              mountPath: /datos
      volumes:
        - name: almacenamiento
          persistentVolumeClaim:
            claimName: contador-pvc

Aplica ambos archivos:

kubectl apply -f contador-pvc.yaml
kubectl apply -f contador-app.yaml

Verifica que el PVC este vinculado:

kubectl get pvc contador-pvc

Observa los logs del pod para ver el contador incrementando:

kubectl logs -f deployment/contador-app

Ahora elimina el pod para simular un reinicio:

kubectl delete pod -l app=contador

El Deployment crea un nuevo pod automaticamente. Revisa los logs nuevamente:

kubectl logs -f deployment/contador-app

El contador continua desde donde quedo, no empieza en 0. Los datos persisten en el PVC a traves del reinicio del pod.

Para ver donde se almacenan fisicamente los datos en el nodo:

ls /var/lib/rancher/k3s/storage/

Veras un directorio con el nombre del PVC que contiene el archivo contador.txt.

Limitaciones del Local-Path Provisioner

El local-path provisioner es simple y funcional pero tiene limitaciones:

Para produccion con requisitos de alta disponibilidad, considera Longhorn (de Rancher) o soluciones NFS.


Siguiente: Capitulo 12: Bases de Datos en K3s —>