OpenEBS es un proyecto de la CNCF que proporciona almacenamiento persistente para Kubernetes ejecutándose como pods dentro del propio clúster. Desde la versión 4 se organiza en dos familias: Local PV (Hostpath, LVM y ZFS), que guarda los datos en el disco del nodo donde corre el pod, y Replicated PV Mayastor, que replica cada volumen entre varios nodos y lo sirve por NVMe over TCP. En este tutorial instalarás OpenEBS con Helm en nodos Ubuntu 24.04, crearás volúmenes Local PV Hostpath y después activarás Mayastor para tener volúmenes replicados.
Notalos antiguos motores Jiva y cStor ya no forman parte de OpenEBS 4 y sus repositorios están archivados. Si encuentras guías que los usan, son para versiones anteriores; para almacenamiento replicado la opción actual es Mayastor.
Requisitos previos
Para seguir esta guía necesitas:
- Un clúster Kubernetes 1.23 o superior con nodos Ubuntu 24.04 LTS, por ejemplo sobre VPS de CubePath. Para Mayastor, al menos tres nodos worker x86_64.
kubectlcon permisos de administrador del clúster y Helm 3 en tu equipo.- Acceso SSH con un usuario con
sudoa los nodos. - Solo para Mayastor: en cada nodo de almacenamiento, 2 núcleos de CPU libres para el motor de E/S, al menos 4 GB de RAM (de los que 2 GiB se reservan como hugepages) y un disco o partición vacío dedicado, sin sistema de archivos ni particiones montadas.
Paso 1: Instalar OpenEBS con Local PV Hostpath
Añade el repositorio del chart oficial:
helm repo add openebs https://openebs.github.io/openebs
helm repo update
Instala OpenEBS empezando solo con los motores locales. Mayastor se activa en el paso 4, cuando los nodos estén preparados; si lo activas sin hugepages sus pods no arrancan:
helm install openebs openebs/openebs \
--namespace openebs \
--create-namespace \
--set engines.replicated.mayastor.enabled=false
Comprueba que los pods están en Running:
kubectl -n openebs get pods
Deberías ver el provisionador openebs-localpv-provisioner y, si no los has desactivado, los controladores y pods de nodo de LVM y ZFS Local PV, todos en Running.
El chart crea la StorageClass openebs-hostpath:
kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
openebs-hostpath openebs.io/local Delete WaitForFirstConsumer false 70s
Los drivers LVM y ZFS solo se usan si creas StorageClasses para ellos, así que puedes dejarlos instalados. Si prefieres no tenerlos, añade --set engines.local.lvm.enabled=false --set engines.local.zfs.enabled=false al comando de instalación.
Paso 2: Crear un volumen Local PV Hostpath
Local PV Hostpath crea un directorio por volumen en el nodo, por defecto bajo /var/openebs/local. Ofrece el rendimiento del disco local sin sobrecarga, pero los datos no se replican: si el nodo se pierde, el volumen también. Es adecuado para bases de datos que ya replican por su cuenta (PostgreSQL con réplicas, Kafka, Elasticsearch) o para cachés.
Crea un namespace de pruebas:
kubectl create namespace demo-openebs
Crea un manifiesto con un PVC y un pod que lo usa:
nano hostpath-demo.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: datos-locales
namespace: demo-openebs
spec:
accessModes:
- ReadWriteOnce
storageClassName: openebs-hostpath
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Pod
metadata:
name: escritor
namespace: demo-openebs
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "date >> /datos/log.txt && sleep 3600"]
volumeMounts:
- name: datos
mountPath: /datos
volumes:
- name: datos
persistentVolumeClaim:
claimName: datos-locales
kubectl apply -f hostpath-demo.yaml
kubectl -n demo-openebs wait --for=condition=Ready pod/escritor --timeout=120s
La StorageClass usa WaitForFirstConsumer, así que el PV no se crea hasta que el pod se programa en un nodo. Comprueba que el PVC está enlazado y en qué nodo está el pod:
kubectl -n demo-openebs get pvc datos-locales
kubectl -n demo-openebs get pod escritor -o wide
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
datos-locales Bound pvc-0b7c2f3e-91a4-4d0e-8f7a-5e2c6d1b3a90 5Gi RWO openebs-hostpath 30s
En ese nodo, el directorio del volumen contiene el archivo que escribió el pod:
sudo ls /var/openebs/local/
NotaHostpath no aplica límites de tamaño. El valor
5Gidel PVC es informativo, y un volumen puede llenar el sistema de archivos del nodo. Si necesitas cuotas reales, usa Local PV LVM o ZFS.
StorageClass Hostpath en otro directorio
Si tienes un disco de datos montado, por ejemplo en /mnt/datos, crea una StorageClass que guarde ahí los volúmenes. La ruta se define en la anotación cas.openebs.io/config:
nano storageclass-hostpath-datos.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: hostpath-datos
annotations:
openebs.io/cas-type: local
cas.openebs.io/config: |
- name: StorageType
value: hostpath
- name: BasePath
value: /mnt/datos
provisioner: openebs.io/local
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
kubectl apply -f storageclass-hostpath-datos.yaml
El directorio indicado en BasePath debe existir en todos los nodos donde puedan programarse pods que usen esta clase.
Paso 3: Preparar los nodos para Mayastor
Mayastor necesita hugepages de 2 MiB, el módulo del kernel nvme_tcp y una etiqueta que indique en qué nodos debe ejecutarse su motor de E/S. Ejecuta en cada nodo de almacenamiento:
echo 'vm.nr_hugepages = 1024' | sudo tee /etc/sysctl.d/20-openebs-hugepages.conf
sudo sysctl --system
Carga el módulo nvme_tcp y déjalo configurado para el arranque:
sudo modprobe nvme_tcp
echo nvme_tcp | sudo tee /etc/modules-load.d/nvme_tcp.conf
Comprueba ambos:
grep HugePages_Total /proc/meminfo
lsmod | grep nvme_tcp
HugePages_Total: 1024
nvme_tcp 53248 0
El kubelet solo detecta las hugepages al arrancar, así que reinícialo en cada nodo (en k3s el servicio es k3s o k3s-agent, y en RKE2 rke2-server o rke2-agent):
sudo systemctl restart kubelet
Desde tu equipo, etiqueta los nodos que ejecutarán Mayastor y verifica que el kubelet anuncia las hugepages:
kubectl label node worker-1 worker-2 worker-3 openebs.io/engine=mayastor
kubectl get node worker-1 -o jsonpath='{.status.allocatable.hugepages-2Mi}{"\n"}'
2Gi
Paso 4: Activar Mayastor
Actualiza la release existente para activar el motor replicado, conservando el resto de valores:
helm upgrade openebs openebs/openebs \
--namespace openebs \
--reuse-values \
--set engines.replicated.mayastor.enabled=true
Mayastor despliega bastantes componentes (API REST, agentes, etcd, el io-engine en cada nodo etiquetado y el driver CSI). Espera unos minutos y comprueba que los pods io-engine están listos:
kubectl -n openebs get pods -o wide | grep io-engine
Todos deben estar en Running con todos sus contenedores listos, uno por nodo etiquetado.
Paso 5: Crear un DiskPool en cada nodo
Mayastor no usa directorios: gestiona dispositivos de bloque completos agrupados en DiskPool, uno por nodo. Localiza el identificador estable del disco vacío en cada nodo, ya que los nombres como /dev/sdb pueden cambiar entre reinicios:
ls -l /dev/disk/by-id/
Crea un manifiesto con un pool por nodo, sustituyendo los identificadores de ejemplo por los tuyos:
nano diskpools.yaml
apiVersion: openebs.io/v1beta2
kind: DiskPool
metadata:
name: pool-worker-1
namespace: openebs
spec:
node: worker-1
disks: ["aio:///dev/disk/by-id/tu_disco_worker_1"]
---
apiVersion: openebs.io/v1beta2
kind: DiskPool
metadata:
name: pool-worker-2
namespace: openebs
spec:
node: worker-2
disks: ["aio:///dev/disk/by-id/tu_disco_worker_2"]
---
apiVersion: openebs.io/v1beta2
kind: DiskPool
metadata:
name: pool-worker-3
namespace: openebs
spec:
node: worker-3
disks: ["aio:///dev/disk/by-id/tu_disco_worker_3"]
AdvertenciaMayastor toma el control total del disco indicado. Cualquier dato que contenga se perderá.
kubectl apply -f diskpools.yaml
kubectl -n openebs get diskpools
Al cabo de unos segundos, los tres pools deben mostrar el estado Online y su capacidad total. Si alguno se queda en otro estado, revisa los eventos con kubectl -n openebs describe diskpool <nombre>.
Paso 6: Crear una StorageClass replicada y probarla
Crea una StorageClass con tres réplicas servidas por NVMe over TCP:
nano storageclass-mayastor-3r.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: mayastor-3r
provisioner: io.openebs.csi-mayastor
parameters:
protocol: nvmf
repl: "3"
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate
kubectl apply -f storageclass-mayastor-3r.yaml
Crea un PVC de prueba y un pod que lo monte:
nano mayastor-demo.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: datos-replicados
namespace: demo-openebs
spec:
accessModes:
- ReadWriteOnce
storageClassName: mayastor-3r
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Pod
metadata:
name: escritor-replicado
namespace: demo-openebs
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "date >> /datos/log.txt && sleep 3600"]
volumeMounts:
- name: datos
mountPath: /datos
volumes:
- name: datos
persistentVolumeClaim:
claimName: datos-replicados
kubectl apply -f mayastor-demo.yaml
kubectl -n demo-openebs wait --for=condition=Ready pod/escritor-replicado --timeout=180s
kubectl -n demo-openebs exec escritor-replicado -- cat /datos/log.txt
Thu Sep 25 10:42:17 UTC 2026
Comprueba que la capacidad usada ha aumentado en los tres pools, lo que indica que cada nodo tiene una réplica:
kubectl -n openebs get diskpools
Solución de problemas
PVC Hostpath en Pending. Es normal hasta que un pod lo usa, por el modo WaitForFirstConsumer. Si sigue así con el pod creado, revisa los eventos con kubectl -n demo-openebs describe pvc datos-locales y los logs del provisionador con kubectl -n openebs logs deploy/openebs-localpv-provisioner.
Los pods io-engine no arrancan o no se crean. Comprueba que el nodo tiene la etiqueta openebs.io/engine=mayastor, que allocatable muestra hugepages-2Mi: 2Gi y que has reiniciado el kubelet tras configurar las hugepages. Revisa los eventos con kubectl -n openebs describe pod <pod-io-engine>.
El pod con un volumen Mayastor no monta. El nodo donde corre el pod necesita el módulo nvme_tcp aunque no tenga pool. Cárgalo como en el paso 3 en todos los nodos worker.
DiskPool que no pasa a Online. Suele ser un disco con particiones o firmas de un sistema de archivos anterior, o una ruta by-id incorrecta. Verifica la ruta en el nodo y limpia el disco con sudo wipefs -a /dev/disk/by-id/<id> si estás seguro de que no contiene nada que necesites.
Conclusión
Has instalado OpenEBS con Local PV Hostpath para volúmenes locales rápidos y Mayastor para volúmenes replicados en tres nodos, y has comprobado ambos con un pod real. A partir de aquí puedes marcar mayastor-3r como StorageClass predeterminada, probar la tolerancia a fallos apagando uno de los nodos mientras el pod escribe, o configurar snapshots CSI con una VolumeSnapshotClass del driver io.openebs.csi-mayastor.
