IDKMANAGER
Volver al blog
· IDK Manager · Infraestructura

TrueNAS + Proxmox: arreglamos el CHAP iSCSI roto en SCALE 25.10

Llevamos el plugin de almacenamiento TrueNAS para Proxmox VE a producción: NVMe/TCP y iSCSI, snapshots ZFS, LXC y multipath. Por el camino encontramos dos bugs upstream que hacían imposible autenticar iSCSI con CHAP contra TrueNAS SCALE 25.10 — uno era código muerto. Los arreglamos y el PR está abierto.

proxmoxtruenasalmacenamientonvmeopen-sourceinfraestructura

TL;DR

Estuvimos poniendo en producción el plugin de almacenamiento de TrueNAS para Proxmox VE — el que deja que Proxmox cree, agrande y snapshotee zvols en una cabina TrueNAS por API, en vez de que alguien lo haga a mano. Funciona bien, y sobre él montamos tres series de parches propias.

Lo que más nos costó, y lo que probablemente te interese si estás en la misma: la autenticación CHAP de iSCSI no podía funcionar contra TrueNAS SCALE 25.10. No era un problema de configuración. Eran dos bugs distintos, uno de ellos código que llevaba tiempo sin ejecutarse nunca. Los arreglamos, los verificamos en vivo y el pull request está abierto en el repositorio oficial: truenas/truenas-proxmox-plugin#95. El fork completo, con todo lo demás que le hicimos, está publicado bajo GPLv3 en github.com/alfonsokuen/truenas-proxmox-plugin.

Si tu cabina tiene CHAP activado y el plugin te dice initiator failed authorization, no estás haciendo nada mal. Sigue leyendo.


El contexto: por qué este plugin importa

Proxmox VE habla iSCSI de forma nativa, pero de la manera aburrida: tú creas el LUN en la cabina, tú lo expones, tú lo mapeas. Cuando quieres un snapshot, Proxmox no puede pedírselo a ZFS — o metes LVM por encima (y pierdes las capacidades del sistema de archivos que ya pagaste) o te vas a NFS con qcow2 (y pierdes rendimiento de bloque).

El plugin de TrueNAS cierra ese hueco: Proxmox habla con la API de la cabina y el zvol se crea, se mapea, se agranda y se snapshotea solo. Los snapshots son de ZFS: instantáneos y sin coste de espacio hasta que divergen. Y desde TrueNAS SCALE 25.10 puedes usar NVMe/TCP en vez de iSCSI, con menos latencia y menos CPU por operación.

Es software libre (GPLv3) del propio TrueNAS. Nosotros trabajamos sobre él, no en su lugar.


Los dos bugs de CHAP

CHAP es la autenticación de iSCSI: sin credenciales correctas, el target no te deja ni mirar. Es lo mínimo que quieres si el tráfico de almacenamiento comparte cableado con cualquier otra cosa.

Al activarlo, el plugin dejaba de encontrar el target. El mensaje era el clásico initiator failed authorization — que normalmente significa “escribiste mal el secreto”. No era eso.

Bug 1 — el CHAP de discovery ahora es implícito

TrueNAS SCALE 25.10 cambió el modelo: en cuanto existe cualquier grupo de autenticación iSCSI en la cabina, el descubrimiento de targets exige CHAP. Y el interruptor que antes permitía separar ambas cosas (discovery_authmethod en el portal) ya no existe en la API — pedirlo devuelve un error de campo desconocido.

El plugin configuraba las credenciales de la sesión, pero no las del descubrimiento. Resultado: la sesión nunca llegaba a intentarse, porque el paso previo moría.

Detalle que nos costó una sesión entera de diagnóstico: un grupo de autenticación huérfano — uno que quedó de una prueba vieja y al que ningún target apunta — es suficiente para activar este comportamiento en todo el portal. Ves el portal abierto, el target sin autenticación, la lista de iniciadores permitida, y aun así te rechaza. Si te está pasando: busca registros iscsi/auth que ya no use nadie.

Bug 2 — el bucle de login llevaba tiempo sin ejecutarse

Este es el que da miedo. El plugin listaba los nodos iSCSI descubiertos para iniciar sesión en cada uno, con iscsiadm -m node -T <iqn>. Ese comando no imprime una lista: imprime el registro completo de configuración de ese nodo. El parser esperaba líneas del tipo portal,tpgt iqn, no encontraba ninguna, y la lista quedaba siempre vacía.

Es decir: el bucle principal de login era código muerto. Toda sesión entraba por la ruta de respaldo, que inicia sesión sin autenticación — y de paso reinicia la base de datos de descubrimiento.

Sin CHAP, esto colaba: la sesión sin autenticar funcionaba y nadie notaba nada. Con CHAP no había sesión posible. Un camino de respaldo que tapa que el camino principal jamás se ejecuta es el tipo de fallo que sobrevive años: todo se ve verde porque el error nunca se nota.

Nuestro arreglo lista todos los nodos y filtra, tolera el sufijo ,tpgt del formato real y hace que el respaldo también sepa de CHAP. Ambos bugs existen igual en el código oficial, con las mismas líneas exactas — por eso el PR va contra master y no contra nuestra copia.

Cómo lo verificamos: sesión CHAP completa desde un cliente en limpio (sin restos de sesiones previas) en dos servidores distintos, VM real con entrada/salida sobre el LUN, y el caso negativo obligatorio — intentar sesión sin credenciales y ver que el target la rechaza. Un login que funciona no prueba que la autenticación esté activa; solo lo prueba ver el rechazo.


La otra serie: qué pasa cuando la cabina se cae

El segundo frente no era un bug, sino un comportamiento incómodo bajo fallo.

Proxmox sondea cada almacenamiento periódicamente para pintarte el estado. Cuando la cabina no responde, cada sondeo se queda esperando a que expire el tiempo de espera de la API. Con varios almacenamientos configurados, el demonio de estadísticas se atasca y el panel entero se pone lento, aunque las máquinas virtuales sigan corriendo tan tranquilas.

Lo interesante es dónde estaba el coste. Hay un cortacircuitos que protege la consulta de estado, pero Proxmox llama a “activar el almacenamiento” antes que a “consultar estado” en cada barrido — y esa activación hacía su propia consulta a la API, sin protección. Medido: 15 de 15 sondeos tardando unos 10 segundos cada uno, con el cortacircuitos marcando “todo bien”.

La solución no fue saltarse ese paso — es el único que vuelve a publicar los portales cuando la cabina revive, así que saltarlo convierte un corte temporal en uno permanente. Lo que hicimos fue acotarlo: mientras hay un fallo reciente, ese trabajo tiene 2 segundos de presupuesto en vez del tiempo de espera completo. Se sigue intentando; simplemente deja de secuestrar el sondeo.

Dos lecciones que nos llevamos, y que valen fuera de este plugin:

  • Un mecanismo de supresión sin traza visible se diagnostica como averiado. Nuestro cortacircuitos funcionaba, pero su única señal estaba en un nivel de registro que por defecto se descarta. Parecía roto. Casi lo “arreglamos” a peor.
  • No clasifiques errores buscando palabras dentro de un mensaje ajeno. Un error de integridad de datos puede arrastrar la palabra “timeout” en su traza y hacerse pasar por un corte de red — y entonces archivas en silencio justo la única pista que tenías. Ahora clasificamos por las frases que genera el propio motor de reintentos, ancladas al inicio del mensaje.

Verificado con cortes de verdad: apagón controlado de la API con carga viva, primer fallo ruidoso, luego silencio acotado, y recuperación limpia al volver — sin tormenta de reintentos ni de alertas.


Qué probamos, una por una

El README del plugin promete dieciséis capacidades. Las recorrimos las dieciséis con evidencia, porque una matriz de funciones sin pruebas es una lista de deseos. Estas son las que más se notan:

CapacidadCómo quedó
Doble transporte (iSCSI y NVMe/TCP)Ambos activos y probados por separado
Snapshots ZFSInstantáneos, con rollback verificado por hash
Snapshot en vivo con RAMDisco + estado de memoria; la VM reanuda tras el rollback
Almacenamiento para contenedores LXCRaíz en el plugin, respaldo en caliente y restauración idéntica
ClústerMigración en vivo entre tres nodos, 7-8 s por salto, hash idéntico
MultipathApagón de un camino con escritura viva: continúa por el otro y se reengancha en 5 s
RedimensionarSolo crecer; encoger se rechaza con un mensaje que dice cuánto falta
Aprovisionamiento fino y compresión8 GB reservados que ocupan 0 en disco hasta que se escriben
CHAPFuncional tras nuestros dos parches
Validación de configuraciónRechaza configuraciones inválidas sin dejar el archivo a medias
Recuperación de erroresLa serie de resiliencia de arriba
Tamaño de bloqueValor explícito respetado en ambos transportes

También montamos NTFS sobre un volumen NVMe/TCP, con snapshot y rollback, para confirmar que al plugin le da igual lo que el sistema operativo invitado escriba dentro: 201 archivos, rollback exacto, copia y restauración byte a byte.

Suite de pruebas: 332 casos automáticos, más pruebas de mutación (introducir errores a propósito en el código para comprobar que alguna prueba lo caza). En tres rondas de revisión, los mutantes que sobrevivieron se convirtieron en pruebas nuevas.


Rendimiento: el número honesto

Lo que medimos en el laboratorio: 26.600 IOPS de lectura aleatoria 4K, 12.300 de escritura aleatoria, y unos 107 MB/s secuenciales.

Ese último número delata la medición: son los ~107 MB/s de un enlace de 1 Gb. No medimos el plugin, medimos el cable. Y está bien que así sea, porque explica de dónde viene el rendimiento real: una vez el volumen está mapeado, los datos no pasan por el plugin. Van por el driver NVMe/TCP del kernel, exactamente igual que un LUN configurado a mano. El plugin trabaja en el plano de control — crear, mapear, snapshotear, autenticar — no en el de datos.

Por eso no hicimos una comparativa contra nuestra cabina productiva: no habría medido nada nuevo, y habría metido carga sintética en un sistema con clientes encima.


En qué estado está

El plugin corre en un clúster Proxmox de tres nodos contra el almacenamiento productivo, en modo cerrado: lista blanca de iniciadores y autenticación DH-CHAP sobre NVMe/TCP. La cabina de laboratorio donde hicimos las pruebas destructivas ya se desmanteló — cumplió su función y no tiene sentido dejar credenciales vivas de algo que no vuelve a usarse.

La primera ola de máquinas ya está migrada. Cuatro cargas de bajo riesgo, elegidas a propósito para estrenar el camino. La más interesante se movió sin apagarla: 80 GB de disco copiados en 34 segundos mientras el servidor seguía atendiendo, con tres semanas de tiempo activo ininterrumpido antes y después. Los discos de origen siguen ahí, marcados como no usados, hasta que cierre el periodo de observación — liberar el espacio antiguo es lo último que se hace, no lo primero.

Las olas siguientes llevan una puerta de control antes de cada una, y los volúmenes grandes van al final. Mover el disco de una máquina que está sirviendo a clientes no es una operación que merezca prisa, aunque ya sepamos que funciona.

Los dos parches de CHAP están propuestos al proyecto oficial en el PR #95. Si el mantenedor los acepta, cualquiera que use TrueNAS SCALE 25.10 con Proxmox y CHAP se ahorra el diagnóstico completo. Nos parece el mejor destino posible para ese trabajo.

Y el fork entero está publicado, con la misma licencia que el original (GPLv3): github.com/alfonsokuen/truenas-proxmox-plugin. Ahí están las tres series de parches, la batería de pruebas, las herramientas de diagnóstico y provocación de fallos que usamos, y un DIVERGENCE-IDK.md que explica qué cambia respecto al oficial y por qué. Si solo te interesa el arreglo de CHAP, está aislado en el PR; si quieres lo demás, está entero ahí — incluido lo que no acabamos de cerrar, anotado como tal.


Actualización — 19 de septiembre de 2026

Casi un mes después, lo que ha pasado con esto, para bien y para mal.

Sigue en producción, y ha crecido. Los tres nodos llevan desde entonces sirviendo sus máquinas desde la cabina por NVMe/TCP, y el fork va por su decimonovena build. Lo que se le ha añadido desde que escribimos lo de arriba: reconocimiento de portales por nombre DNS en PVE 9, reintentos acotados para que pvestatd no se quede colgado cuando la cabina no contesta, aceptación de los nombres de campo antiguos para que una configuración vieja no deje de funcionar al actualizar, y un rollback de snapshot que ya no es recursivo ni edita la configuración de la VM a mano.

Lo más pedido: ver en Proxmox los snapshots hechos desde TrueNAS. Si una tarea periódica de la cabina fotografía el zvol de una VM, Proxmox no se entera: el snapshot no sale en la pestaña correspondiente y, si es más reciente que el último que hiciste desde Proxmox, qm rollback se niega con «not most recent snapshot» sin darte forma de ver ni borrar el que estorba. Ahora hay un comando que los importa a la configuración del invitado —con la fecha real de creación en ZFS como marca de tiempo—, para máquinas virtuales y para contenedores:

truenas-proxmox-manage import-snapshots <vmid> --dry-run

Está enviado al proyecto oficial en el PR #110. Si lo aceptan, dejará de hacer falta ningún fork para esto, que es exactamente lo que queremos.

Un hallazgo que no es del plugin y que conviene que sepas. Persiguiendo otra cosa nos topamos con que mover o migrar un disco a cualquier almacenamiento de bloques —no solo este— ejecuta qemu-img convert con la caché por defecto. Si un fallo de escritura llega después de que el dato ya esté en la caché de página, el error se descarta: la copia termina, qemu-img sale con código 0, la tarea dice OK y al destino le faltan datos. Lo reprodujimos con dm-flakey sobre un dispositivo de bucle: con la caché por defecto, 1,9 de 2 GiB no llegaron nunca al disco y nada falló; la misma copia con -t none aborta con error y no pierde nada. Está reportado con la receta completa en el bug 8054 de Proxmox. No decimos que la solución sea trivial, porque -t none es más lento y el compromiso es real; decimos que hoy un almacenamiento que descarta escrituras informa de éxito, y eso conviene saberlo antes de fiarse de una migración que dijo OK.

Y lo que no salió bien. El install.sh que enlaza el README de la rama principal del proyecto oficial pertenece a una generación anterior a las betas actuales: pide la clave de API con los nombres de campo viejos y el asistente falla con broker: scfg missing api_host/api_key aunque la red y la clave sean correctas. Lo reportamos como issue #107 y resulta que no éramos los únicos: otros dos forks del proyecto habían parcheado lo mismo por su cuenta.

Instalar nuestra build ya no requiere clonar ni compilar nada:

curl -sSL https://github.com/alfonsokuen/truenas-proxmox-plugin/releases/latest/download/install-idk.sh | bash

Descarga el .deb de la release, comprueba su sha256 antes de instalar y admite --dry-run para ver qué haría sin tocar el sistema. Los paquetes, con sus sumas y las notas de cada versión, están en las releases del repositorio.

Si estás montando esto

Tres cosas que nos habría gustado saber antes:

  1. Un grupo de autenticación iSCSI huérfano cambia el comportamiento de todo el portal. Antes de perseguir credenciales, revisa si quedó alguno de una prueba anterior.
  2. Prueba siempre el caso negativo. Que la sesión conecte no prueba que CHAP esté activo; solo lo prueba ver un intento sin credenciales siendo rechazado.
  3. La resiliencia se prueba apagando cosas. Un cortacircuitos que nunca viste dispararse no es un cortacircuitos, es una suposición.

¿Tienes Proxmox y una cabina TrueNAS, o estás evaluando salir de un almacenamiento compartido que se quedó corto? Esto es exactamente lo que hacemos: diseño, migración en caliente y operación de infraestructura virtualizada. Escríbenos y lo vemos con tu caso concreto.

¿Vas a instalarlo? El procedimiento nodo por nodo, con los tres errores que dejan el plugin a medias, está en la guía de instalación del plugin en un clúster.


Si lo que necesitas es almacenamiento centralizado en tu oficina sin operar nada de esto tú mismo: NAS on-site. Y si la infraestructura completa te queda grande, cloud privado y DevOps.

¿Listo para liberar tu equipo de la gestión IT?

Conversemos 15 minutos. Te decimos exactamente qué necesitas y cuánto cuesta — sin compromiso.