DevOps

Configurar NFS Subdir External Provisioner en K3s

Guía para instalar NFS Subdir External Provisioner en K3s y gestionar el almacenamiento persistente de tus pods de forma dinámica.

k3skubernetesnfsstoragepvcdevops

Cuando quieres almacenamiento persistente en k3s y no quieres atarte al disco local de un nodo, lo habitual es montar un NAS y delegar en NFS. El reto es que Kubernetes, por defecto, no sabe “negociar” con un servidor NFS: necesitas un componente que traduzca las peticiones de almacenamiento (PVCs) en carpetas NFS reales.

Ahí entra NFS Subdir External Provisioner. Es un pequeño controlador que actúa como fábrica de PersistentVolumes: cada vez que creas un PVC, él crea la carpeta en el NAS y el PV correspondiente de forma automática. Tú solo pides almacenamiento; él se encarga del resto.

Requisitos previos

Antes de tocar k3s, asegúrate de que el NAS está listo:

  1. Servicio NFS habilitado. En el NAS (Synology, QNAP, TrueNAS, etc.) activa el servicio NFS. Apunta la ruta de la carpeta compartida, por ejemplo /volume1/cluster-datos.
  2. Permisos correctos. La carpeta compartida debe permitir lectura/escritura a las IPs de todos los nodos del clúster. Muy importante: en Synology, el ajuste de squash tiene que estar en No mapping o Map root to admin, porque Kubernetes monta como root y, si el NAS “aplana” el root a nobody, los pods no van a poder escribir.

Paso 1: Instalar Helm

Para instalar el provisioner de forma limpia usaremos Helm, el gestor de paquetes de Kubernetes. Si ya lo tienes, salta al paso 2. Si no, instálalo en el nodo master:

curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

Paso 2: Instalar el NFS Provisioner

Añade el repo oficial, actualiza e instala el provisioner. Cambia 192.168.1.50 por la IP de tu NAS y /volume1/cluster-datos por la ruta real de tu carpeta compartida:

# Añadir el repositorio de Helm
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

# Actualizar la lista de charts
helm repo update

# Instalar el provisioner
helm install nfs-proveedor-nas nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
    --set nfs.server=192.168.1.50 \
    --set nfs.path=/volume1/cluster-datos \
    --set storageClass.name=nas-storage \
    --set storageClass.defaultClass=false

Lo que le estamos diciendo a k3s, en una sola línea, es: “instala este programa, conéctalo al NAS en esa IP y ruta, y crea una nueva StorageClass llamada nas-storage”. El flag defaultClass=false es importante: hace que la StorageClass de k3s por defecto (local-path) siga siendo la principal. Si quieres que nas-storage sea la default, cámbialo a true, pero perderás la local.

Verifica que la “fábrica” está lista:

kubectl get storageclass

Deberías ver listadas dos: local-path (la de k3s) y nas-storage (la que acabas de crear).

Paso 3: El cambio mental importante

En el aprovisionamiento dinámico te saltas el paso de escribir el YAML del PV a mano. El provisioner que acabas de instalar lo hace por ti en cuanto detecta un PVC que solicita su StorageClass. Así que pasamos directo a crear el PVC.

Paso 4: Crear el PVC

Crea un archivo pvc-nas-dinamico.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-mi-wordpress
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: nas-storage
  resources:
    requests:
      storage: 5Gi

ReadWriteMany es clave cuando trabajas con NFS: significa que el PVC puede ser montado por varios pods a la vez, lo que te permite mover pods entre nodos sin que se bloqueen por un ReadWriteOnce que ya tiene otro nodo.

Aplica el archivo:

kubectl apply -f pvc-nas-dinamico.yaml

¿Qué pasa por detrás?

Tres cosas, casi en tiempo real:

  • kubectl get pvc muestra el PVC en estado Bound (vinculado).
  • kubectl get pv lista un PV nuevo con un nombre largo del estilo pvc-12345678-abcd..., creado sin que escribieras una sola línea de su manifiesto.
  • En el NAS, dentro de /volume1/cluster-datos/, aparece una carpeta real con un nombre del tipo default-pvc-mi-wordpress-pvc-XXXXXX.

Si todo eso ocurre, el provisioner está funcionando.

Paso 5: Crear un Pod que consuma el PVC

Para cerrar el ciclo, monta el PVC en un Pod. Si ese Pod muere y se levanta en otro nodo, se conectará a la misma carpeta del NAS sin que tengas que hacer nada.

Crea un archivo pod-nas.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-nas
spec:
  containers:
  - name: webserver
    image: nginx:alpine
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: datos-nas
  volumes:
  - name: datos-nas
    persistentVolumeClaim:
      claimName: pvc-mi-wordpress

Aplica el archivo:

kubectl apply -f pod-nas.yaml

Lo que acabas de conseguir

  • Configuración única (Paso 2): el provisioner queda instalado apuntando a la IP raíz del NAS.
  • Para cada nueva app (Pasos 4 y 5): solo tienes que crear un PVC pidiendo espacio a nas-storage y un Pod que lo monte. k3s se encarga de crear subcarpetas organizadas en el NAS y generar los PV transparentemente.

Resultado: persistencia externa, orden en el NAS y aplicaciones 100% movibles entre nodos. Una vez que lo tienes funcionando, añadir almacenamiento a una app nueva cuesta tres líneas de YAML.