Longhorn: Almacenamiento Distribuido para Kubernetes
Longhorn es un sistema de almacenamiento de bloques distribuido nativo de Kubernetes desarrollado por Rancher que convierte los discos locales de los nodos en volúmenes replicados de alta disponibilidad. Con Longhorn puedes crear volúmenes persistentes con réplicas automáticas, instantáneas y backups a S3, todo gestionado mediante una interfaz web intuitiva directamente desde el clúster.
Requisitos Previos
- Kubernetes 1.21+ con al menos 3 nodos worker
- Mínimo 1 disco dedicado por nodo (SSD recomendado para producción)
open-iscsiinstalado en todos los nodosnfs-commoninstalado en todos los nodoscryptsetupsi se va a usar cifrado de volúmenes- Mínimo 4 GB de RAM y 2 vCPUs por nodo worker
# Instalar dependencias en todos los nodos worker (Ubuntu/Debian)
apt update
apt install -y open-iscsi nfs-common cryptsetup
# Habilitar el servicio iSCSI
systemctl enable iscsid && systemctl start iscsid
# Para CentOS/Rocky Linux
yum install -y iscsi-initiator-utils nfs-utils cryptsetup
systemctl enable iscsid && systemctl start iscsid
# Verificar que los nodos cumplen los requisitos con el script oficial
curl -sSfL https://raw.githubusercontent.com/longhorn/longhorn/v1.6.0/scripts/environment_check.sh | bash
Instalación de Longhorn
# Instalación mediante Helm (recomendado)
helm repo add longhorn https://charts.longhorn.io
helm repo update
# Crear el namespace
kubectl create namespace longhorn-system
# Instalar Longhorn con valores por defecto
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--set defaultSettings.defaultReplicaCount=3
# Verificar la instalación
kubectl get pods -n longhorn-system
# Esperar a que todos los pods estén en estado Running
kubectl wait --for=condition=ready pod \
-l app=longhorn-manager \
-n longhorn-system \
--timeout=300s
Instalación con valores personalizados para producción:
cat > longhorn-values.yaml << 'EOF'
defaultSettings:
# Número de réplicas por volumen (mínimo 3 para HA)
defaultReplicaCount: 3
# Porcentaje mínimo de espacio libre antes de marcar el nodo como no apto
storageMinimalAvailablePercentage: 25
# Porcentaje de espacio reservado por Longhorn del disco total
storageOverProvisioningPercentage: 200
# Habilitar backups automáticos de instantáneas
recurringJobSelector: '[{"name":"backup","isGroup":true}]'
# Endpoint de backup (S3)
backupTarget: "s3://mi-bucket-longhorn@us-east-1/"
backupTargetCredentialSecret: "longhorn-s3-secret"
# Garantizar que las réplicas están en nodos diferentes
replicaSoftAntiAffinity: false
# Compresor de datos para backups
backupCompressionMethod: lz4
persistence:
defaultClass: true
defaultFsType: ext4
defaultClassReplicaCount: 3
defaultDataLocality: best-effort
ingress:
enabled: true
ingressClassName: nginx
host: longhorn.midominio.com
tls: true
tlsSecret: longhorn-tls
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: longhorn-auth
longhornManager:
priorityClass: system-node-critical
EOF
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--values longhorn-values.yaml
Configuración del StorageClass
# Ver el StorageClass creado por Longhorn
kubectl get storageclass
# Crear un StorageClass personalizado para SSDs de alto rendimiento
cat > storageclass-ssd.yaml << 'EOF'
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: longhorn-ssd
annotations:
storageclass.kubernetes.io/is-default-class: "false"
provisioner: driver.longhorn.io
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate
parameters:
# Número de réplicas para este StorageClass
numberOfReplicas: "3"
# Política de datos en caché (best-effort, strict-local, disabled)
dataLocality: "best-effort"
# Montar solo en el nodo donde vive la réplica primaria
fromBackup: ""
# Cifrado del volumen
encrypted: "true"
# Seleccionar solo nodos con el label ssd=true
diskSelector: "ssd"
nodeSelector: "storage=ssd"
EOF
kubectl apply -f storageclass-ssd.yaml
# Crear un PVC que use el StorageClass personalizado
cat > pvc-ejemplo.yaml << 'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: datos-aplicacion
namespace: produccion
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn-ssd
resources:
requests:
storage: 50Gi
EOF
kubectl apply -f pvc-ejemplo.yaml
kubectl get pvc -n produccion
Backups a S3
# Crear el Secret con las credenciales de S3
kubectl create secret generic longhorn-s3-secret \
--from-literal=AWS_ACCESS_KEY_ID=tu-access-key \
--from-literal=AWS_SECRET_ACCESS_KEY=tu-secret-key \
--from-literal=AWS_ENDPOINTS=https://s3.amazonaws.com \
-n longhorn-system
# Configurar el target de backup en Longhorn
kubectl patch settings.longhorn.io backup-target \
-n longhorn-system \
--type merge \
-p '{"value":"s3://mi-bucket-longhorn@us-east-1/"}'
kubectl patch settings.longhorn.io backup-target-credential-secret \
-n longhorn-system \
--type merge \
-p '{"value":"longhorn-s3-secret"}'
# Crear un RecurringJob para backups automáticos diarios
cat > backup-job.yaml << 'EOF'
apiVersion: longhorn.io/v1beta2
kind: RecurringJob
metadata:
name: backup-diario
namespace: longhorn-system
spec:
cron: "0 2 * * *" # Todos los días a las 2:00 AM
task: "backup"
groups:
- default
retain: 14 # Mantener los últimos 14 backups
concurrency: 2
labels:
backup-type: daily
EOF
kubectl apply -f backup-job.yaml
Instantáneas de Volúmenes
# Crear una instantánea manualmente de un volumen
cat > snapshot.yaml << 'EOF'
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: snapshot-datos-app-$(date +%Y%m%d)
namespace: produccion
spec:
volumeSnapshotClassName: longhorn
source:
persistentVolumeClaimName: datos-aplicacion
EOF
kubectl apply -f snapshot.yaml
# Listar las instantáneas
kubectl get volumesnapshots -n produccion
# Restaurar un PVC desde una instantánea
cat > pvc-desde-snapshot.yaml << 'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: datos-restaurados
namespace: produccion
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn-ssd
resources:
requests:
storage: 50Gi
dataSource:
name: snapshot-datos-app-20240101
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
EOF
kubectl apply -f pvc-desde-snapshot.yaml
Recuperación ante Desastres
# Restaurar un volumen desde backup en S3 (en un clúster nuevo o diferente)
cat > pvc-desde-backup.yaml << 'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: datos-recuperados
namespace: produccion
annotations:
# URL del backup en S3
longhorn.io/restore-volume-name: "backup-nombre-del-volumen"
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 50Gi
dataSource:
name: mi-backup
kind: LonghornBackup
apiGroup: longhorn.io
EOF
# Ver los backups disponibles en S3
kubectl get backups -n longhorn-system
# Ver el estado de un backup específico
kubectl describe backup <backup-name> -n longhorn-system
# Expandir un volumen en uso (sin reiniciar el pod)
kubectl patch pvc datos-aplicacion \
-n produccion \
--type merge \
-p '{"spec":{"resources":{"requests":{"storage":"100Gi"}}}}'
Monitoreo con Prometheus
# Longhorn expone métricas en el puerto 9500
# Crear un ServiceMonitor para Prometheus Operator
cat > longhorn-servicemonitor.yaml << 'EOF'
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: longhorn
namespace: longhorn-system
labels:
app: longhorn-manager
spec:
selector:
matchLabels:
app: longhorn-manager
endpoints:
- port: manager
path: /metrics
interval: 30s
EOF
kubectl apply -f longhorn-servicemonitor.yaml
# Verificar que las métricas están disponibles
kubectl port-forward -n longhorn-system svc/longhorn-backend 9500:9500 &
curl -s http://localhost:9500/metrics | grep longhorn_volume
# Métricas importantes de Longhorn:
# longhorn_volume_capacity_bytes - Capacidad total de los volúmenes
# longhorn_volume_usage_bytes - Uso actual
# longhorn_volume_state - Estado del volumen (1=healthy)
# longhorn_node_storage_capacity_bytes - Capacidad del almacenamiento del nodo
Solución de Problemas
Volúmenes en estado Degraded:
# Ver el estado de los volúmenes
kubectl get volumes -n longhorn-system
# Ver qué réplicas están caídas
kubectl get replicas -n longhorn-system | grep -v Running
# Forzar la reconstrucción de una réplica
kubectl edit volume <volume-name> -n longhorn-system
# Cambiar spec.numberOfReplicas y volver al valor original
# Ver logs del manager de Longhorn
kubectl logs -n longhorn-system -l app=longhorn-manager -f
Nodo en estado de mantenimiento:
# Verificar el estado de los nodos en Longhorn
kubectl get nodes.longhorn.io -n longhorn-system
# Habilitar un nodo que está deshabilitado para scheduling
kubectl edit nodes.longhorn.io <node-name> -n longhorn-system
# Cambiar spec.allowScheduling: true
Backup fallido:
# Ver los backups y su estado
kubectl get backups -n longhorn-system -o wide
# Ver los logs del backup controller
kubectl logs -n longhorn-system -l longhorn.io/component=backup-controller
Conclusión
Longhorn transforma el almacenamiento local de los nodos Kubernetes en un sistema de almacenamiento de bloques distribuido, replicado y con backup automático, sin necesidad de infraestructura de almacenamiento externa. Su interfaz web, la integración nativa con Kubernetes y las capacidades de backup a S3 lo convierten en una solución de almacenamiento completa especialmente adecuada para clústeres en bare metal o VPS donde no hay almacenamiento gestionado disponible.


