ZFS no “pierde” realmente tus datasets. Simplemente se vuelve extremadamente bueno en hacer que tengas la sensación de que lo hizo. Un minuto tus datos están bajo /srv/app, al siguiente minuto “desaparecen”, tu servicio está vacío y tu cerebro intenta recordar si ofendiste a los dioses del almacenamiento.
Esta es la trampa del mountpoint: un conjunto sorprendentemente ordinario de comportamientos —overlays de montaje, mountpoints legacy, ajustes de canmount, orden de arranque y algunas herramientas de automatización bienintencionadas— que pueden ocultar un dataset perfectamente sano detrás de otro sistema de ficheros. En producción, eso puede parecer exactamente una pérdida de datos hasta que recuerdas una regla: en Unix, la última montada gana.
Qué es la trampa del mountpoint (y por qué engaña a gente inteligente)
La trampa del mountpoint ocurre cuando un dataset ZFS está montado en un lugar que no esperabas —o no puede montarse donde sí esperabas— porque la ubicación de montaje ya está ocupada. Un sistema de ficheros diferente (otro dataset ZFS, un tmpfs, una partición ext4 antigua, un bind mount de un contenedor, una unidad systemd, lo que sea) se monta “encima” del directorio donde creías que vivía tu dataset.
Desde el shell, parece que tus datos han desaparecido:
lsmuestra un directorio vacío.- Las aplicaciones empiezan a crear nuevos directorios y ficheros, satisfechas, en el lugar equivocado.
- Los datos “perdidos” reaparecen si desmontas el sistema de ficheros que está sobre ellos —o vuelven a desaparecer cuando algo se monta en el arranque.
Por eso la trampa es tan convincente: no es un bug de ZFS. Es el kernel haciendo exactamente lo que debe hacer. El dataset sigue ahí, consistente y referenciado por su pool. Simplemente no es visible actualmente en la ruta que estás mirando.
Primer chiste (obligatorio, corto y merecido): ZFS no se comió tus datos; solo les puso una manta encima y te observó entrar en pánico.
Qué significa “desaparecer” en la práctica
La mayoría de las veces, una de estas cosas es cierta:
- El dataset está montado, pero no donde piensas (
mountpointcambió o se heredó). - El dataset no está montado porque se dijo a ZFS que no lo montara (
canmount=offonoauto). - El dataset está configurado como
mountpoint=legacy, así que ZFS no lo montará a menos que/etc/fstab(o el equivalente de tu distro) lo haga. - El dataset quiere montarse en una ruta que ya es mountpoint de otra cosa (overlay).
- El pool se importó, pero el montaje falló por claves faltantes (encriptación), directorios de montaje ausentes o el orden de arranque.
El peligro operativo no es solo la confusión. Es un estado de split-brain a nivel de sistema de ficheros en la capa de aplicación: tu servicio comienza a escribir nuevos datos en un directorio subyacente (normalmente en el filesystem raíz), mientras el dataset real permanece tranquilo en otro sitio. Ahora tienes dos realidades: la que ve tu app y la que ZFS protege.
Cómo funciona realmente el montaje en ZFS
Los datasets ZFS son sistemas de ficheros con propiedades. La propiedad en el centro de nuestro drama es mountpoint, emparejada con canmount. Entender la interacción es la mitad de la batalla; la otra mitad es recordar que ZFS vive dentro de un SO más amplio que puede montar otras cosas cuando le apetece.
Los tres pilares: mountpoint, canmount y “quién lo monta”
mountpoint es la ruta donde ZFS montará un dataset si es montado por ZFS. Valores comunes:
- Una ruta real, p.ej.
/srv/db none(nunca montar)legacy(ZFS delega a mecanismos de montaje tradicionales como/etc/fstab)
canmount controla si el dataset es elegible para montarse:
on: montable (por defecto)off: nunca montar (incluso si tiene mountpoint)noauto: no auto-montar en el arranque, pero permitirzfs mountmanual
Quién lo monta depende de la integración con tu SO. En muchos sistemas, el montaje ZFS lo gestionan scripts de init o servicios systemd que se ejecutan tras la importación del pool. Para datasets legacy, las unidades de montaje del sistema o mount -a lo harán. En plataformas de contenedores, los espacios de nombres de montaje y los bind mounts pueden añadir una segunda capa de “está montado, solo que no en el lugar que estás mirando”.
Overlays: la ley Unix que causa la mayoría de los actos de “desaparición”
Cuando montas el sistema de ficheros B en el directorio /srv/app, lo que antes era visible en /srv/app queda oculto hasta que desmontes B. Eso incluye:
- archivos que se crearon en ese directorio en el filesystem raíz,
- o un montaje anterior (como tu dataset ZFS),
- o un bind mount desde otro sitio.
Esto no es específico de ZFS; es comportamiento del VFS. ZFS simplemente facilita crear muchos sistemas de ficheros montables, por lo que es más fácil apilarlos accidentalmente.
Segundo chiste (también obligatorio y corto): Si los mounts tuvieran una app de citas, su bio sería “Oculto las cosas”.
Herencia: la trampa silenciosa
Las propiedades ZFS pueden heredarse por el árbol de datasets. Eso es una característica—hasta que te olvidas de que existe. Si estableces mountpoint en un dataset padre, los hijos lo heredan a menos que se establezca explícitamente lo contrario. Puedes terminar con mountpoints anidados como:
pool/servicesmontado en/srvpool/services/appmontado en/srv/apppool/services/app/logsmontado en/srv/app/logs
Eso puede ser perfectamente sensato. También puede convertirse en caos cuando alguien cambia el mountpoint del padre durante una migración y olvida que los hijos heredan—de repente todo se mueve, o los intentos de montaje colisionan con rutas existentes.
legacy mountpoints: control a la antigua, confusión moderna
mountpoint=legacy significa: “ZFS, no montes esto automáticamente. Yo lo manejaré mediante el sistema de montaje del SO.” A veces se usa para control estricto, ordenamiento especial o compatibilidad con herramientas de gestión.
La trampa: si confías en legacy, pero tu entrada en /etc/fstab falta, está mal o se retrasa en el arranque, el dataset existirá pero no estará montado. Mientras tanto, el directorio es solo un directorio—así que tu aplicación arranca y escribe allí como si no pasara nada.
Hechos interesantes y contexto histórico
Un poco de contexto ayuda, porque el comportamiento de montaje de ZFS no es aleatorio—es el resultado de decisiones de diseño que abarcan décadas.
- ZFS debutó en Sun a mediados de los 2000 con la idea de que “los sistemas de ficheros son baratos” y deben gestionarse como datasets, no como particiones.
- A diferencia de los sistemas de ficheros tradicionales, ZFS fomenta muchos mountpoints (uno por dataset), lo que incrementa la superficie para errores de orden de montaje.
- El mountpoint
legacyexiste principalmente por compatibilidad con herramientas de montaje Unix antiguas y secuencias de arranque donde ZFS no era el gestor de sistemas de ficheros por defecto. canmount=noautose hizo popular en entornos de arranque para que múltiples datasets coexistan sin montarse todos a la vez.- Los overlays de montaje son más antiguos que ZFS por décadas; son comportamiento fundamental del VFS de Unix. ZFS simplemente facilita crear escenarios de overlay accidentalmente.
- Muchos tickets de “pérdida de datos” en despliegues tempranos de ZFS eran errores de visibilidad: los datasets existían, pero estaban ocultos por montajes equivocados o pools no importados.
- OpenZFS se extendió por Linux, illumos y BSDs, y cada plataforma integró el montaje en tiempo de arranque de forma distinta—mismas propiedades, diferente coreografía.
- La encriptación añadió un nuevo modo de fallo: los datasets pueden estar presentes y sanos pero no montarse porque las claves no se cargaron durante el arranque.
Los síntomas: datasets “desapareciendo” en el mundo real
En la respuesta a incidentes, “dataset desaparecido” suele llegar envuelto en uno de estos casos:
Síntoma 1: El directorio está vacío (o parece recién creado)
Haces cd a /srv/app y está vacío, pero sabes que debería contener gigabytes. O peor: contiene un conjunto diferente de ficheros creados recientemente por una aplicación que no recibió el memo.
Síntoma 2: El dataset existe en los metadatos de ZFS
zfs list muestra el dataset, con un tamaño usado no nulo, y quizá incluso el mountpoint esperado. Aun así la ruta no muestra los datos.
Síntoma 3: Tras reiniciar, el problema aparece (o desaparece)
Si cambia con el reinicio, sospecha del orden de arranque, montajes legacy, unidades systemd o la carga de claves de encriptación.
Síntoma 4: El uso de disco no coincide con lo que ves
zfs list reporta cientos de gigabytes usados, pero du en el mountpoint muestra casi nada. O al revés: df reporta un filesystem raíz pequeño llenándose porque la app escribió en el directorio subyacente.
Síntoma 5: Los contenedores ven algo diferente al host
Los espacios de nombres de montaje significan que el host puede tener el dataset montado mientras un contenedor ve un directorio sin montar (o un bind mount distinto). Esta es una variante especial de “se fue”, a menudo atribuida a ZFS porque ese es el nombre que la gente reconoce.
Tareas prácticas: comandos que puedes ejecutar hoy
Estas son tareas aptas para producción que he usado bajo presión. Cada una incluye qué significa la salida y qué decisión informa. Los comandos asumen Linux con OpenZFS; ajusta rutas para tu SO.
Tarea 1: Lista datasets y sus mountpoints (la realidad base)
cr0x@server:~$ zfs list -o name,used,avail,mountpoint,canmount -r tank
NAME USED AVAIL MOUNTPOINT CANMOUNT
tank 320G 1.4T /tank on
tank/services 210G 1.4T /srv on
tank/services/app 180G 1.4T /srv/app on
tank/services/db 30G 1.4T /srv/db on
Interpretación: Si un dataset tiene un mountpoint real y canmount=on, ZFS pretende montarlo. Si no es visible, sospecha de overlays o de un fallo de montaje.
Tarea 2: Ver qué cree ZFS que está montado actualmente
cr0x@server:~$ zfs mount
tank
tank/services
tank/services/app
tank/services/db
Interpretación: Si tu dataset falta aquí, no está montado por ZFS. Si aparece listado pero aún no puedes ver archivos en la ruta, sospecha de espacios de nombres de montaje o que estés mirando el directorio equivocado en el host.
Tarea 3: Confirmar qué ha montado el kernel en la ruta (capturar overlays)
cr0x@server:~$ findmnt -T /srv/app
TARGET SOURCE FSTYPE OPTIONS
/srv/app tank/services/app zfs rw,xattr,noacl
Interpretación: Este es el comando más útil para la trampa de mountpoint. Si findmnt muestra otra cosa (ext4, overlayfs, tmpfs), tu dataset ZFS está siendo ocultado.
Tarea 4: Mostrar todos los montajes que podrían estar apilándose en el mismo árbol
cr0x@server:~$ findmnt -R /srv
TARGET SOURCE FSTYPE OPTIONS
/srv tank/services zfs rw,xattr
└─/srv/app tank/services/app zfs rw,xattr
└─/srv/db tank/services/db zfs rw,xattr
Interpretación: Si ves entradas inesperadas (como /srv/app siendo overlayfs), has encontrado el escondite.
Tarea 5: Comprobar si el dataset está configurado como legacy (culpable común de “¿por qué no se montó?”)
cr0x@server:~$ zfs get -H -o name,property,value,source mountpoint tank/services/app
tank/services/app mountpoint legacy local
Interpretación: Con legacy, ZFS no hará auto-mount. Si no tienes una entrada OS de montaje correspondiente, tu servicio escribirá en el directorio subyacente en su lugar.
Tarea 6: Comprobar canmount (el interruptor de “existe pero no montará”)
cr0x@server:~$ zfs get -H -o name,property,value,source canmount tank/services/app
tank/services/app canmount noauto local
Interpretación: noauto significa que no se montará en el arranque vía la ruta de auto-montaje habitual; debes montarlo explícitamente (o mediante herramientas). off significa que no lo montarás en absoluto a menos que lo cambies.
Tarea 7: Intentar un montaje manual y leer el error (no supongas)
cr0x@server:~$ sudo zfs mount tank/services/app
cannot mount 'tank/services/app': mountpoint or dataset is busy
Interpretación: “Busy” suele significar que /srv/app ya es un mountpoint para otra cosa. Ese es el escenario de overlay. Ejecuta findmnt -T /srv/app para identificar al ocupante.
Tarea 8: Identificar qué está ocupando el mountpoint
cr0x@server:~$ findmnt -T /srv/app -o TARGET,SOURCE,FSTYPE,OPTIONS
TARGET SOURCE FSTYPE OPTIONS
/srv/app /dev/nvme0n1p2[/app] ext4 rw,relatime
Interpretación: No estás viendo ZFS en absoluto; ext4 está montado ahí. Tu dataset no se ha ido—tu mountpoint está ocupado.
Tarea 9: Localizar el dataset escaneando mountpoints (cuando sospechas que está montado en otro lado)
cr0x@server:~$ zfs list -o name,mountpoint -r tank | grep app
tank/services/app /srv/app
Interpretación: Si el mountpoint es correcto aquí pero el kernel muestra otra cosa en esa ruta, tienes una colisión de montaje.
Tarea 10: Detectar los “datos sombra” subyacentes escritos cuando el dataset no estaba montado
cr0x@server:~$ sudo zfs unmount tank/services/app
cr0x@server:~$ ls -lah /srv/app | head
total 56K
drwxr-xr-x 14 root root 4.0K Dec 24 09:10 .
drwxr-xr-x 6 root root 4.0K Dec 24 09:09 ..
-rw-r--r-- 1 root root 2.1K Dec 24 09:10 app.log
drwxr-xr-x 2 root root 4.0K Dec 24 09:10 cache
Interpretación: Esos ficheros están en el sistema de ficheros subyacente (a menudo tu disco root), creados mientras ZFS no estaba montado. Así es como los filesystems raíz se llenan misteriosamente durante una falla de montaje ZFS.
Tarea 11: Comprobar importación del pool y servicios de montaje (fallos en arranque)
cr0x@server:~$ systemctl status zfs-import-cache zfs-mount
● zfs-import-cache.service - Import ZFS pools by cache file
Loaded: loaded (/lib/systemd/system/zfs-import-cache.service; enabled)
Active: active (exited)
● zfs-mount.service - Mount ZFS filesystems
Loaded: loaded (/lib/systemd/system/zfs-mount.service; enabled)
Active: failed (Result: exit-code)
Interpretación: El pool se importó, pero el montaje ZFS falló. No persigas fantasmas en el dataset; persigue los logs del servicio y la razón del fallo.
Tarea 12: Leer la razón del fallo de montaje en los logs
cr0x@server:~$ journalctl -u zfs-mount -b --no-pager | tail -n 20
Dec 24 09:01:12 server zfs[1123]: cannot mount 'tank/services/app': directory is not empty
Dec 24 09:01:12 server systemd[1]: zfs-mount.service: Main process exited, code=exited, status=1/FAILURE
Interpretación: “Directory is not empty” suele ser una pista de que algo creó ficheros antes de que ZFS se montara, o que otro mount/bind mount ocupa la ruta. También puede significar que estás montando sobre un directorio no vacío y la herramienta ZFS de tu sistema se niega a hacerlo automáticamente.
Tarea 13: Verificar que las claves de encriptación están cargadas (el “no montado” invisible)
cr0x@server:~$ zfs get -H -o name,property,value keystatus,encryptionroot tank/services/app
tank/services/app keystatus unavailable
tank/services/app encryptionroot tank
Interpretación: Si keystatus es unavailable, el dataset puede existir pero no puede montarse. Carga la clave y luego monta.
Tarea 14: Cargar clave y montar (con cuidado)
cr0x@server:~$ sudo zfs load-key -a
cr0x@server:~$ sudo zfs mount -a
cr0x@server:~$ zfs get -H -o name,property,value keystatus tank/services/app
tank/services/app keystatus available
Interpretación: Si esto lo resuelve, tu “dataset que desapareció” fue un problema de gestión de claves/orden de arranque, no de propiedad de mountpoint.
Tarea 15: Encontrar propiedades heredadas vs locales (para detectar cambios sorpresa)
cr0x@server:~$ zfs get -r -o name,property,value,source mountpoint,canmount tank/services | sed -n '1,8p'
NAME PROPERTY VALUE SOURCE
tank/services mountpoint /srv local
tank/services canmount on default
tank/services/app mountpoint /srv/app inherited from tank/services
tank/services/app canmount on default
Interpretación: Si un hijo está heredando un mountpoint, un cambio en el padre cambia también el mountpoint efectivo del hijo. Eso es poder y peligro en una línea.
Tarea 16: Cambiar un mountpoint de forma segura (y verificar)
cr0x@server:~$ sudo zfs set mountpoint=/srv/app2 tank/services/app
cr0x@server:~$ sudo zfs mount tank/services/app
cr0x@server:~$ findmnt -T /srv/app2
TARGET SOURCE FSTYPE OPTIONS
/srv/app2 tank/services/app zfs rw,xattr
Interpretación: ZFS hace sencillo cambiar mountpoints, pero debes confirmar que la nueva ruta no esté ya en uso y actualizar aplicaciones, entradas fstab (si es legacy) y la monitorización.
Tres mini-historias del mundo corporativo
1) Incidente causado por una suposición equivocada: “El dataset está vacío, así que el despliegue lo borró”
Empezó como muchos problemas de viernes: un despliegue terminó, la aplicación se reinició y de repente la capa web servía contenido por defecto—como si todo el sitio se hubiera reseteado. El ingeniero on-call hizo lo sensato primero: comprobó el directorio de datos. Estaba vacío. La conclusión llegó rápida y segura: el pipeline de despliegue debió haber eliminado el volumen.
Alguien lanzó un rollback. Alguien más empezó a redactar la actualización del incidente con frases como “borrado irrecuperable” y “restaurando desde backups”. El responsable de almacenamiento fue llamado y formuló una pregunta calmada que descarriló la narrativa: “¿Qué dice findmnt sobre esa ruta?”
Resultó que la ruta tenía dos montajes luchando por el mismo directorio. El servidor tenía una partición ext4 antigua todavía listada en una unidad de montaje del sistema, y se montó tarde en la secuencia de arranque—justo después de que ZFS hubiera montado con éxito el dataset. El montaje ext4 no borró nada; simplemente cubrió el montaje ZFS. Los datos nunca se movieron. Estaban solo ocultos detrás de un filesystem de una era anterior del host.
La solución fue dolorosamente simple: eliminar la unidad de montaje obsoleta y reiniciar. Pero la corrección real fue cultural: dejar de equiparar “directorio vacío” con “datos borrados”. Esa suposición provoca decisiones rápidas, caras e innecesarias, incluidos rollbacks que introducen nuevo riesgo.
2) Una optimización que salió mal: “Usemos mountpoint=legacy para tener más control”
Un equipo de plataforma quería montajes deterministas. Estaban cansados de la “magia” y optaron por explícito: poner datasets ZFS en mountpoint=legacy, luego gestionar todo en /etc/fstab para que el sistema OS decida el orden. En papel, parecía buena ingeniería: un único lugar para leer montajes, una forma de montar todo, auditoría fácil.
En la práctica, fue una optimización para humanos a costa de la fiabilidad. Durante una ventana de mantenimiento renombraron un dataset y actualizaron el lado ZFS pero olvidaron la línea fstab correspondiente en dos servidores. Esos dos arranques subieron “bien”, pero el dataset no se montó. El directorio existía, así que la aplicación arrancó y escribió felizmente en el filesystem root subyacente. En pocas horas, los discos root se llenaron, journald empezó a desechar logs y el incidente pasó de “¿por qué faltan métricas?” a “¿por qué se mueren los nodos?”
Empeoró: cuando el dataset finalmente se montó correctamente, los nuevos ficheros “desaparecieron”—porque esos ficheros nunca estuvieron en el dataset; estaban en el filesystem subyacente. Ahora la app tenía dos conjuntos de estado creados en dos lugares, y reconciliarlos requirió trabajo humano cuidadoso y mucha precaución.
El postmortem no concluyó “nunca uses legacy”. Concluyó: usa legacy solo cuando puedas demostrar que el montaje está forzado (mediante dependencias systemd, comprobaciones tempranas de arranque y monitorización), y cuando tu modelo operativo tenga en cuenta el modo de fallo: la aplicación escribiendo en el disco equivocado.
3) Una práctica aburrida pero correcta que salvó el día: “Monitorizamos la realidad del montaje, no solo las propiedades ZFS”
En otra empresa, un cluster de bases de datos corría sobre datasets ZFS con mountpoints cuidadosamente diseñados. Ya habían tenido demasiadas mañanas aterradoras donde el pool se importó pero un dataset no se montó por retrasos en la carga de claves. Así que implementaron una comprobación rutinaria que se ejecutaba en cada nodo después del arranque y tras cambios de configuración: verificar que rutas específicas estén respaldadas por la fuente de filesystem esperada.
La comprobación no preguntaba a ZFS qué pretendía hacer. Preguntaba al kernel qué realmente hizo: findmnt -T /var/lib/postgresql, y comparar la fuente con el dataset esperado. Si no coincidía, el nodo se marcaba como unhealthy y se retiraba del servicio antes de recibir tráfico. Nada sofisticado. Sin IA. Solo negarse a ejecutar servicios stateful sobre un montaje ambiguo.
Un día, una actualización rutinaria del SO introdujo un nuevo tmpfs para una ruta legacy usada por un agente. Accidentalmente aterrizó en un directorio padre y enmascaró un montaje hijo. El nodo volvió del reinicio y los montajes ZFS parecían “ok” a primera vista, pero la comprobación de ruta falló instantáneamente. El nodo nunca se unió al cluster. No hubo divergencia de datos, ni restauraciones de emergencia, ni pelea de “¿por qué root está lleno?”.
Fue el tipo de victoria que nadie celebra porque no pasó nada—el mayor cumplido que puedes hacer a la ingeniería operativa.
Guion de diagnóstico rápido
Este es el orden que uso cuando un dataset “falta”. El objetivo es velocidad: reducir el espacio de búsqueda en menos de cinco minutos, luego decidir si estás tratando con un overlay, un fallo de montaje o un problema de visibilidad entre namespaces/arranque.
Paso 1: Pregunta al kernel qué está montado en la ruta
cr0x@server:~$ findmnt -T /srv/app -o TARGET,SOURCE,FSTYPE,OPTIONS
TARGET SOURCE FSTYPE OPTIONS
/srv/app tank/services/app zfs rw,xattr
Si no es ZFS: tienes un overlay o un montaje equivocado. Identifica y elimina/ajusta el montaje que ocupa la ruta.
Paso 2: Pregunta a ZFS si cree que el dataset está montado
cr0x@server:~$ zfs mount | grep -F tank/services/app || echo "not mounted"
not mounted
Si no está montado: comprueba canmount, mountpoint, el estado de claves de encriptación y los logs. No asumas que es un error tipográfico en el mountpoint hasta que hayas comprobado lo aburrido.
Paso 3: Revisa las propiedades de mount del dataset y la herencia
cr0x@server:~$ zfs get -H -o property,value,source mountpoint,canmount tank/services/app
mountpoint /srv/app local
canmount on default
Si mountpoint=legacy: ve a montajes del SO. Si canmount=off/noauto: ve a la lógica de montaje y scripts de arranque.
Paso 4: Busca fallos de montaje en los logs (no minimizar)
cr0x@server:~$ journalctl -u zfs-mount -b --no-pager | tail -n 50
Hits comunes: “directory is not empty”, “mountpoint busy”, key not available, permisos en el directorio de montaje, o padre de montaje faltante.
Paso 5: Comprueba datos sombra y evita divergencia
Si el dataset falló al montarse, tu app pudo haber escrito en el directorio subyacente. Antes de remontar, detén el servicio, inspecciona los directorios subyacentes y planea una fusión o limpieza controlada. El peor movimiento es “simplemente montarlo y esperar”. Así creas estado dividido.
Paso 6: Solo entonces preocúpate por rendimiento
La gente salta a “ZFS es lento” cuando el problema real es “estás escribiendo en el disco root”. Confirma la fuente del montaje primero. Hacer debugging de rendimiento en el filesystem equivocado es una forma excelente de volverte extremadamente ocupado y completamente equivocado.
Errores comunes, síntomas y soluciones
Error 1: Colisión de mountpoint (dos filesystems quieren el mismo directorio)
Síntomas:
zfs mountfalla con “dataset is busy”findmnt -T /pathmuestra ext4/tmpfs/overlayfs en lugar de ZFS- Los datos “reaparecen” después de desmontar algo no relacionado
Solución: Identifica el montaje que ocupa la ruta actual (findmnt). Elimina o reubica el montaje conflictivo. Si es una entrada obsoleta en /etc/fstab o una unidad systemd, bórrala/desactívala y reinicia o remonta limpiamente.
Error 2: mountpoint=legacy sin entrada OS de montaje válida
Síntomas:
zfs listmuestra el dataset, perozfs mountno lo monta- Aplicaciones escriben en directorios subyacentes; el filesystem root se llena
Solución: O bien (a) añade la configuración de montaje del SO correcta, o (b) cambia a un mountpoint normal y deja que ZFS lo gestione: set mountpoint=/desired/path y asegúrate de canmount=on. Luego valida con findmnt.
Error 3: canmount=off o noauto sin automatización de montaje explícita
Síntomas:
- Dataset nunca se monta tras reiniciar
zfs mount datasetmanual funciona (en el caso denoauto)
Solución: Si lo necesitas montado en el arranque, pon canmount=on. Si necesitas noauto (entornos de arranque, datasets en staging), asegúrate de que una unidad systemd lo monte antes de que los servicios comiencen.
Error 4: El mountpoint del padre cambió y los hijos heredaron una nueva realidad
Síntomas:
- Varios datasets “se movieron” a la vez
- Los intentos de montaje fallan porque las rutas heredadas colisionan
Solución: Revisa la herencia con zfs get -r mountpoint. Establece mountpoints explícitos en los hijos que deben permanecer estables, o rediseña el árbol de datasets para que coincida con tu layout de directorios.
Error 5: Claves de encriptación no cargadas durante el arranque
Síntomas:
- Dataset existe,
keystatus=unavailable - El montaje falla hasta que alguien ejecuta
zfs load-key
Solución: Implementa la carga de claves en la secuencia de arranque (con los controles de seguridad apropiados), y añade una verificación post-arranque de montajes para evitar que servicios arranquen sobre directorios vacíos.
Error 6: Contenedores y namespaces de montaje ocultan la verdad del host
Síntomas:
- El host ve el dataset montado; el contenedor ve un directorio vacío
- Contenido distinto visible según dónde ejecutes
ls
Solución: Valida los montajes dentro del namespace del contenedor, no solo en el host. Asegura que los bind mounts apunten a la ruta host correcta y que la ruta host esté respaldada por el dataset ZFS previsto en el momento en que el contenedor arranca.
Listas de verificación / plan paso a paso
Checklist A: Cuando los datos “desaparecen” de un mountpoint
- Ejecuta
findmnt -T /pathpara ver el filesystem real en esa ruta. - Ejecuta
zfs mountyzfs list -o name,mountpoint,canmountpara el dataset. - Si
zfs mountfalla, lee el error; no improvises. - Comprueba
zfs get mountpoint,canmounty si los valores son heredados. - Revisa los logs por fallos del servicio de montaje.
- Detén las aplicaciones que escriben en la ruta hasta que el montaje sea correcto.
- Si el dataset no estaba montado, busca datos sombra en el directorio subyacente tras desmontar/asegurar que está desmontado.
- Solo después de que la visibilidad sea correcta, reanuda los servicios y valida el estado de la aplicación.
Checklist B: Migración segura de mountpoint (cambio en producción)
- Elige una nueva ruta que no sea actualmente un mountpoint: verifica con
findmnt -T. - Detén los servicios que escriben en el dataset.
- Confirma que el dataset está sano y montado donde crees.
- Cambia el mountpoint:
zfs set mountpoint=/new/path dataset. - Monta explícitamente:
zfs mount datasety verifica confindmnt. - Actualiza la configuración de la aplicación, unidades systemd, bind mounts de contenedores, backups y comprobaciones de monitorización.
- Arranca servicios y valida que las escrituras lleguen a ZFS (observa los bytes usados con
zfs list, no solo los logs de la app). - Limpa los directorios antiguos en el filesystem subyacente si acumularon ficheros sombra.
Checklist C: Prevenir la trampa (guardarraíles aburridos que funcionan)
- Monitoriza la realidad de montajes: para rutas críticas, alerta si
findmnt -Tno muestra la fuente esperada. - Haz que los servicios dependan de montajes ZFS (ordenamiento systemd) para que no arranquen sobre directorios vacíos.
- Evita mezclar gestión
legacyy no-legacy a menos que tengas una razón documentada y tests. - Documenta el árbol de datasets y las reglas de herencia de mountpoint para tu equipo.
- Durante la respuesta a incidentes, trata “directorio vacío” como “ambigüedad de montaje” hasta que se demuestre lo contrario.
Preguntas frecuentes (FAQ)
1) ¿Puede un dataset ZFS “desaparecer” realmente?
Rara vez en sentido literal. La mayoría de las veces no está montado, está montado en otro sitio o está oculto por otro montaje. Los metadatos ZFS normalmente todavía lo muestran en zfs list.
2) ¿Cuál es el comando más rápido para confirmar la trampa del mountpoint?
findmnt -T /your/path. Te dice qué ha montado realmente el kernel allí, que es la realidad en la que viven tus aplicaciones.
3) ¿Por qué a veces ZFS se niega a montar porque “directory is not empty”?
Algunas herramientas de montaje ZFS son conservadoras respecto a montar sobre directorios no vacíos para evitar ocultar ficheros que se escribieron allí (a menudo por error). Ese error es una pista: te está diciendo que existen datos sombra o que otra cosa posee esa ruta.
4) ¿Es malo mountpoint=legacy?
No. Es útil cuando necesitas control a nivel del SO. Es arriesgado cuando los equipos olvidan que ZFS no lo montará automáticamente y las apps escribirán en el directorio subyacente si el montaje del SO no ocurre.
5) ¿Cuál es la diferencia entre canmount=off y canmount=noauto?
off significa “nunca montar”. noauto significa “no montar automáticamente, pero permitir montaje manual”. noauto es común en entornos de arranque o datasets en staging.
6) ¿Cómo sé si un dataset hijo heredó un mountpoint?
Usa zfs get -o name,property,value,source mountpoint -r pool/dataset. Si el source dice “inherited from …” entonces cambiar el padre cambiará el mountpoint efectivo del hijo.
7) ¿Por qué un reinicio “arregló” el dataset que faltaba?
Porque la secuencia de arranque cambió el orden o el timing de los montajes. Tal vez ZFS se montó antes que el montaje conflictivo la última vez, o las claves se cargaron con éxito en el segundo arranque, o una unidad de montaje fallida no reintentó.
8) ¿Cómo evito que las aplicaciones escriban en el lugar equivocado cuando ZFS no está montado?
Dos capas: (1) dependencias systemd para que los servicios no arranquen hasta que exista el montaje correcto, y (2) monitorización que verifique la fuente del montaje (otra vez: findmnt) y retire nodos de rotación si está mal.
9) ¿Pueden las snapshots ayudar con la trampa del mountpoint?
Las snapshots protegen los datos dentro del dataset. No te protegen de que una aplicación escriba en el directorio subyacente equivocado cuando el dataset no está montado. También puedes snapshotear el filesystem equivocado—con éxito.
10) ¿Qué pasa si el dataset está montado, pero el directorio sigue pareciendo incorrecto?
Entonces podrías estar en un namespace de montaje diferente (contenedores), mirando un symlink que apunta a otro sitio, o confundiendo dos rutas similares. Confirma con findmnt en el mismo contexto donde corre la app.
Conclusión
La trampa del mountpoint en ZFS no es un caso límite raro. Es un resultado predecible de un sistema que hace que crear y montar sistemas de ficheros sea fácil, viviendo dentro de un SO que permite que los montajes se apilen y se oculten mutuamente sin ceremonia.
Si solo adoptas un hábito de esto: deja de confiar en listados de directorio cuando hay mucho en juego. Confía en la realidad del montaje. Pregunta al kernel qué está montado en la ruta, pregunta a ZFS qué cree que debería montarse, y haz que tus servicios se nieguen a ejecutarse cuando esas respuestas no coincidan. Así conviertes “mi dataset desapareció” de un incidente en una reparación de dos minutos.