Las banderas de características de ZFS son una de esas ideas de ingeniería que se ven educadas en una diapositiva y se vuelven profundamente personales a las 03:17 cuando intentas importar un pool en el “otro” host y simplemente se niega. Son los marcadores del ADN de tu pool: una vez que ciertos rasgos se expresan, no puedes fingir que no existen. Y el pool no hará caso de tu nostalgia por núcleos antiguos, bootloaders viejos, o esa caja de espera que nadie actualizó porque “solo es una copia de seguridad”.
Este artículo trata sobre portabilidad: cómo mover pools entre hosts, cómo las actualizaciones cambian lo que un pool requiere y cómo replicar de forma segura entre versiones. Está escrito desde el punto de vista de alguien que ha visto un confiado “simplemente actualízalo” convertirse en una llamada de incidentes, y que también ha visto la disciplina aburrida y cuidadosa de compatibilidad salvar discretamente un fin de semana.
Qué son las feature flags (y por qué existen)
El ZFS tradicional tenía un número de “versión de pool”. Actualizabas un pool de la versión N a la N+1, y ese número publicitaba lo que el pool podía hacer y lo que requería. Funcionó hasta que dejó de hacerlo: distintos proveedores incluían distintas funcionalidades bajo el mismo número de versión, y la gente obtuvo pools que “deberían” importar pero no podían—o peor, importaban y se comportaban de forma extraña.
Las feature flags reemplazaron la versión monolítica con un modelo más honesto: un pool anuncia un conjunto de características, cada una con su propio nombre (como feature@async_destroy o feature@encryption) y un estado. Los hosts anuncian qué características entienden. La compatibilidad se convierte en un problema de intersección de conjuntos en lugar de un solo entero engañoso.
Operativamente, las feature flags importan porque son pegajosas. Algunas características solo están “enabled” y son inofensivas hasta que se usan; otras pasan a “active” y cambian estructuras en disco de una manera que las implementaciones antiguas no pueden leer. Cuando eso ocurre, el pool no puede importarse en un host que carezca de la característica—por más promesas de cuidado que hagas.
Broma #1: Las banderas de características de ZFS son como los tatuajes: fáciles de hacerse, difíciles de quitar, y tu yo futuro puede cuestionar tus decisiones.
El modelo de compatibilidad: enabled vs active vs supported
Cuando la gente dice “feature flags”, a menudo se refiere a “la lista que vi en zpool get all”. Esa lista es el inicio, no la historia. La historia es la máquina de estados detrás de cada bandera y lo que ese estado implica para importaciones y replicación.
Estado de la feature: disabled, enabled, active
En términos de OpenZFS, las banderas de características suelen presentarse como:
- disabled: el pool no tiene la característica enabled; nada acerca de ella importa.
- enabled: el pool conoce la característica y puede usarla en el futuro, pero no ha escrito necesariamente estructuras específicas todavía.
- active: el pool ha usado la característica; existen estructuras en disco que requieren soporte para leerlas (y usualmente para importar en absoluto).
No todas las características se comportan exactamente igual, pero la regla práctica es: las características active son las que te dejan varado en hosts antiguos. Las características enabled-pero-no-active todavía pueden crear problemas si el host de destino rechaza pools con características enabled desconocidas, pero la mayoría de fallos de compatibilidad ocurren cuando una característica se vuelve active.
Capacidad del host: “supported” no es “enabled”
Un host (módulo del kernel + herramientas userland) soporta un conjunto de características. Eso no significa que esas características estén enabled en cada pool. Significa que el host puede importar pools que tengan esas características active.
La trampa común: “Actualizamos el OS, así que somos compatibles.” Eres compatible con pools que requieren como máximo lo que tu host soporta. Si importas un pool en un host más nuevo, no has cambiado necesariamente el pool todavía. Pero si ejecutas zpool upgrade, o habilitas ciertas propiedades de dataset (como encriptación nativa), es posible que acabes haciendo tu pool incompatible con hosts más antiguos de forma permanente.
Importaciones en modo solo-lectura y el mito de “no lo tocaré”
La gente trata de salvarse con importaciones solo-lectura. Puede ayudar en casos estrechos (por ejemplo, para extraer datos de un pool con daño menor), pero no es una salida universal de compatibilidad. Si el host no entiende una característica active, no puede analizar de forma fiable los metadatos del pool—aunque sea en modo solo-lectura. La incompatibilidad de características no es un problema de seguridad de escritura; es un problema de “¿puedo entender lo que estoy viendo?”.
Reglas de portabilidad: los tres únicos resultados que importan
Cuando mueves pools o replicás entre hosts, quieres predecir cuál de estos tres resultados obtendrás:
Resultado 1: Importación limpia (aburrida, deseable)
El host de destino soporta cada característica active en el pool. El pool se importa normalmente. Puedes montar datasets, scrubear, resilverizar, hacer todas las operaciones habituales. Este es el único resultado que quieres para cortes de producción.
Resultado 2: Importación rechazada (falla ruidosa, a menudo recuperable)
El host de destino ve una o más características active no soportadas y se niega a importar. Esto es disruptivo, pero honesto: no has corrompido datos en silencio; te han detenido antes de hacer algo peligroso.
En la práctica, esto ocurre cuando intentas importar un pool actualizado en un OpenZFS más nuevo dentro de un entorno más antiguo (kernel de distro antiguo, firmware de appliance antiguo, imagen de rescate antigua). La solución suele ser “actualizar el host de destino” o “no actualizar el pool en primer lugar”. Lo último solo es posible si lo detectas antes de activar características.
Resultado 3: Importa, pero otras operaciones fallan (sutil, costoso operativamente)
Esto es más raro con feature flags que con el caos de versiones de pool antiguas, pero todavía sucede: flujos de replicación, bootloaders, herramientas de initramfs o software de gestión pueden no entender nuevas propiedades o comportamientos por defecto incluso si el módulo del kernel puede importar el pool.
Ejemplos incluyen: entornos de arranque que asumen un comportamiento de montaje heredado, imágenes de recuperación sin soporte para crypto en root encriptado, o destinos de replicación que aceptan streams pero no pueden manejar correctamente bloques grandes o configuraciones de datos embebidos. El pool se importa, pero el ecosistema alrededor se convierte en el incidente.
Broma #2: Lo único más permanente que una actualización de pool ZFS es la invitación del calendario para el postmortem.
Hechos interesantes y contexto histórico
Estos son los puntos que hacen que las feature flags tengan sentido—y que también explican por qué dos máquinas que ejecutan “ZFS” pueden comportarse como primos lejanos.
- ZFS nació en Sun y se lanzó en Solaris; el diseño original incluyó checksums end-to-end y semántica copy-on-write mucho antes de que fueran populares en pilas de almacenamiento Linux de commodity.
- Los “números de versión” de pool se volvieron un lío porque múltiples downstreams implementaron características en distinto orden o bajo incrementos de versión conflictivos, haciendo la compatibilidad basada en versión poco fiable entre proveedores.
- Se introdujeron las feature flags para reemplazar las versiones de pool para que un pool pudiera autodescribir capacidades con precisión en lugar de hacerlo mediante un único entero.
- OpenZFS unificó bases de código divergentes (Illumos, FreeBSD, puertos de Linux) alrededor de un modelo compartido de feature flags, pero el calendario de lanzamientos aún difiere entre plataformas.
- La encriptación nativa es una característica clave: no es solo una propiedad de dataset; cambia los flujos de gestión de claves, el comportamiento de send/receive y las suposiciones de recuperación ante desastres.
- Algunas características se activan implícitamente—no siempre ejecutas “enable feature” explícitamente. Establecer una propiedad (por ejemplo, habilitar clases especiales de asignación de vdev, uso de large_dnode por ciertas herramientas) puede cambiar una feature a active.
- Los boot pools son especiales: el kernel puede importar un pool bien, pero el bootloader puede no entender características on-disk más nuevas. Esa es una axis de compatibilidad diferente que la mayoría aprende por las malas.
- Los streams de replicación codifican requisitos de características. Incluso si el pool fuente se importa en todas partes, un stream de send puede requerir soporte en el destino dependiendo de flags y propiedades.
- Las feature flags están con espacio de nombres (a menudo con un prefijo de proveedor o proyecto históricamente), que fue un compromiso pragmático para evitar colisiones mientras el desarrollo de ZFS estaba fragmentado.
Tres mini-historias del mundo corporativo
Mini-historia 1: El incidente causado por una suposición errónea
Tenían dos centros de datos y un plan simple: el primario corría en Linux más nuevo, el DR en una build “estable” ligeramente más antigua porque “no hace mucho”. La replicación era ZFS send/receive. La caja de DR se trataba como un extintor: se inspeccionaba ocasionalmente, y en su mayoría se ignoraba.
Durante una ventana de mantenimiento rutinaria, un ingeniero actualizó las features del pool primario para obtener una capacidad nueva que querían para rendimiento y manejo de snapshots. El cambio parecía inofensivo: zpool upgrade se ejecutó limpio, nada explotó, y las gráficas de la aplicación se mantuvieron planas. El equipo se chocó las manos y siguió adelante.
Dos meses después, hicieron una prueba de DR y descubrieron que el lado receptor había estado fallando silenciosamente durante días. Los streams de send ahora requerían features que el host de DR no soportaba. El monitoreo no alertó porque solo vigilaba la presencia de snapshots, no el éxito de los receives incrementales. Cuando finalmente intentaron importar el pool replicado en DR, se negó: features no soportadas. La réplica no solo estaba desactualizada; no era utilizable.
La recuperación fue poco glamorosa: actualizaciones de emergencia en DR, alineamiento de kernel y módulo ZFS, reconstrucción de la base de replicación con un send completo. Funcionó, pero les costó un fin de semana y quemó confianza. La causa raíz no fue “ZFS es difícil.” Fue la suposición equivocada: que una actualización de pool es una optimización local, no un evento de compatibilidad global.
La acción del postmortem que realmente importó: implementaron un “contrato de compatibilidad” entre sitios—conjunto mínimo documentado de features soportadas, versiones de OpenZFS fijadas en ambos lugares, y una prueba que intentaba un receive en seco en DR antes de cualquier upgrade de pool en prod.
Mini-historia 2: La optimización que salió mal
Otra compañía quería operaciones de metadatos más rápidas para una flota de servidores de build. Alguien leyó sobre special vdevs, clases de asignación de metadatos y formatos de puntero de bloque más nuevos. El argumento fue convincente: “Haremos que los stat de archivos y las cargas de archivos pequeños vuelen.” Implementaron NVMe nuevo, crearon un special vdev y habilitaron un conjunto de features “recomendadas” por la build de OpenZFS más nueva que usaban.
El rendimiento mejoró de inmediato. Luego vino el contragolpe: el ciclo de renovación del hardware movió algunos pools a hosts de repuesto más antiguos durante el mantenimiento. Esos repuestos ejecutaban un OpenZFS más antiguo porque el kernel del proveedor se quedaba atrás. De pronto, pools con features recién activadas no podían importarse en los repuestos. Las ventanas de mantenimiento se alargaron porque “simplemente fallar a repuesto” se convirtió en “primero, actualizar el repuesto, luego reconstruir initramfs, luego reiniciar, luego rezar”.
Peor aún, descubrieron que las herramientas del entorno de arranque de esa distro no gustaban del conjunto de features más nuevo en el pool root, y un puñado de cajas se hicieron incómodas de recuperar. Nada fue irrecuperable, pero el tiempo de reparación aumentó drásticamente. La optimización era real; el coste operativo también era real, y nadie lo había presupuestado en la decisión.
Lo que cambiaron: separaron preocupaciones. Dejaron de tratar “actualizaciones de features de pool” como parte del tuning de rendimiento. Fijaron los boot pools al conjunto mínimo de features soportado por las herramientas de arranque, y aislaron el uso agresivo de features a pools de datos que no necesitaban arrancar en entornos de rescate extraños. Los servidores de build mantuvieron su velocidad; la rotación on-call mantuvo su sueño.
Mini-historia 3: La práctica aburrida pero correcta que salvó el día
Este equipo ejecutaba hosts mixtos: algunos en FreeBSD para servicios de red, otros en Linux para cómputo, todos compartiendo una estrategia de backups basada en ZFS. El entorno no era llamativo, pero era disciplinado. Cada trimestre, hacían un “ejercicio de portabilidad de pools”: exportaban un pool no crítico e importaban en un host de reserva que ejecutaba la pila ZFS más antigua soportada en la flota.
Se sentía como trabajo ocupado hasta el día que dio sus frutos. Un host de producción tuvo una falla de placa base, y la forma más rápida de salir fue cablear los discos en una máquina de repuesto. El repuesto era más antiguo y no se había actualizado en meses. En muchas organizaciones, eso habría sido el inicio de un mal día.
En cambio, el pool se importó limpiamente, porque el equipo tenía una regla: no actualizar pools a menos que cada host en la matriz de soporte pudiera importar el pool, y no activar nuevas features sin una prueba de portabilidad. También mantenían un pequeño conjunto de imágenes de recuperación “conocidas buenas” con soporte ZFS coincidente.
El incidente todavía dolió—el hardware siempre duele—pero se mantuvo en la categoría de “cambiar piezas, importar pool, reanudar servicio”. Sin banderas de features sorpresa, sin bloqueo accidental, sin actualizaciones frenéticas del OS bajo presión. Su victoria fue aburrida, y ese es el mayor cumplido que puedes hacer a una práctica de SRE.
Tareas prácticas: comandos que realmente ejecutarás
El objetivo aquí es darte memoria muscular operativa: cómo inspeccionar features, predecir importaciones y gestionar actualizaciones sin convertirlas en ruleta. Los comandos se muestran con fragmentos típicos de salida y cómo interpretarlos. Ajusta nombres de pool y dataset según convenga.
Task 1: Identify ZFS and zpool versions on a host
cr0x@server:~$ zfs version
zfs-2.2.4-1
zfs-kmod-2.2.4-1
Interpretación: El userland y el módulo del kernel OpenZFS de este host están alineados. La desalineación (userland más nuevo que el módulo) puede causar comportamientos confusos; para la planificación de portabilidad, te importa el soporte de features del módulo.
Task 2: List pools and confirm health before you touch anything
cr0x@server:~$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 3.62T 1.88T 1.74T - - 18% 51% 1.00x ONLINE -
Interpretación: No hagas trabajo de features en un pool que esté DEGRADED, resilverizando, o mostrando errores de I/O a menos que tu objetivo sea la recuperación. Las actualizaciones no suelen dañar pools sanos, pero estrechan tus rutas de escape.
Task 3: See which feature flags exist on the pool and their states
cr0x@server:~$ zpool get all tank | grep '^tank feature@' | head
tank feature@async_destroy enabled local
tank feature@bookmarks enabled local
tank feature@embedded_data active local
tank feature@enabled_txg active local
tank feature@extensible_dataset active local
Interpretación: Cualquier línea active es un requisito firme: importar este pool requiere un host que soporte esa feature. Las líneas enabled pueden convertirse en requisitos más adelante cuando la feature se active.
Task 4: Show unsupported features on this host (pre-check imports)
cr0x@server:~$ zpool get -H -o value unsupported@features tank
-
Interpretación: Un guion normalmente significa “ninguna”. Si ves una lista, ya tienes una descoincidencia (por ejemplo, importaste el pool en un host que puede leerlo pero carece de alguna capacidad que las herramientas esperan, o estás revisando en una pila parcialmente compatible).
Task 5: Predict what zpool upgrade would do (do not run it yet)
cr0x@server:~$ zpool upgrade -v
This system supports ZFS pool feature flags.
The following features are supported:
FEAT DESCRIPTION
async_destroy Destroy filesystems asynchronously.
embedded_data Blocks which compress very well are stored embedded in metadata.
encryption Dataset level encryption.
Interpretación: Esto muestra lo que el host actual soporta, no lo que tu pool necesita. El movimiento peligroso es actualizar un pool en un host que soporta más que el resto de tu flota.
Task 6: Check if a pool has pending feature upgrades available
cr0x@server:~$ zpool status
pool: tank
state: ONLINE
status: Some supported features are not enabled on the pool. The pool can
still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
the pool may no longer be accessible by software that does not support
the features. See zpool-features(7) for details.
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
sda ONLINE 0 0 0
Interpretación: Este mensaje es ZFS siendo útil y peligroso al mismo tiempo. “Some supported features are not enabled” no es un problema; es un trade-off. La línea de acción es la parte que puede dejar el pool varado en hosts más antiguos.
Task 7: Safely check importability on a target host (without importing)
cr0x@drhost:~$ sudo zpool import
pool: tank
id: 1234567890123456789
state: ONLINE
action: The pool can be imported using its name or numeric identifier.
config:
tank ONLINE
sda ONLINE
Interpretación: Si el pool aparece con un mensaje normal de “can be imported”, el host de destino probablemente soporte las features active. Si se queja de features no soportadas, detente y corrige la desalineación de versiones del host de destino antes del cutover.
Task 8: Attempt a read-only import for inspection (when you’re cautious)
cr0x@drhost:~$ sudo zpool import -o readonly=on -N tank
cr0x@drhost:~$ zpool status tank
pool: tank
state: ONLINE
Interpretación: -N importa sin montar datasets. Es una forma segura de inspeccionar feature flags y propiedades en un host de destino durante un ensayo de migración. No resuelve la falta de soporte de features; solo reduce la posibilidad de alterar datos mientras inspeccionas.
Task 9: Confirm feature states after import on the target
cr0x@drhost:~$ zpool get all tank | grep '^tank feature@' | grep -E 'active|enabled' | head
tank feature@async_destroy enabled local
tank feature@embedded_data active local
tank feature@extensible_dataset active local
Interpretación: Compara esta salida entre hosts. Si un host puede importar pero reporta rarezas (features faltantes en herramientas), puede que tengas una desalineación userland/módulo o un userland más antiguo que no puede mostrar todos los estados limpiamente.
Task 10: Identify encryption usage and key status (compatibility landmine)
cr0x@server:~$ zfs get -r -o name,property,value -s local,received encryption,keylocation,keystatus tank | head -n 12
NAME PROPERTY VALUE SOURCE
tank encryption off default
tank/secure encryption aes-256-gcm local
tank/secure keylocation prompt local
tank/secure keystatus unavailable -
Interpretación: Los datasets encriptados requieren soporte en el destino para la feature de encriptación y flujos de gestión de claves. Si DR no puede cargar claves (o no soporta encriptación), no tienes DR—solo ciphertext costoso.
Task 11: Test a replication receive in a safe sandbox dataset
cr0x@source:~$ sudo zfs snapshot -r tank/app@replica-test
cr0x@source:~$ sudo zfs send -R tank/app@replica-test | ssh drhost sudo zfs receive -uF tank/replica-sandbox
Interpretación: Esta es una prueba práctica de compatibilidad: si el receive falla con errores relacionados con features, lo sabrás ahora en lugar de durante una caída. -u evita auto-montar; -F fuerza rollback en la ruta del dataset en el destino si es necesario (usar con cuidado).
Task 12: Inspect why a receive failed (look for feature requirements)
cr0x@drhost:~$ sudo zfs receive -uF tank/replica-sandbox < /tmp/stream.zfs
cannot receive: stream has unsupported feature(s)
Interpretación: El stream está demandando algo que el destino no puede hacer. Esto puede ser una feature más nueva en el stream de send, o una propiedad que requiere una feature flag. La solución suele ser “actualizar OpenZFS del destino” o “cambiar el modo/properties de replicación para evitar ese requisito”, dependiendo de lo que contenga el stream.
Task 13: Freeze a pool’s portability by refusing feature upgrades (policy, not tech)
cr0x@server:~$ sudo zpool status tank | sed -n '1,12p'
pool: tank
state: ONLINE
status: Some supported features are not enabled on the pool. The pool can
still be used, but some features are unavailable.
Interpretación: La jugada “aburrida” es dejarlo así. Si necesitas soportar hosts de rescate más antiguos o importaciones entre plataformas, no actualizar features es una elección deliberada de compatibilidad.
Task 14: Perform a controlled pool feature upgrade (when you’ve earned it)
cr0x@server:~$ sudo zpool upgrade tank
This system supports ZFS pool feature flags.
Successfully upgraded 'tank'.
Interpretación: Esto habilita todas las features soportadas por este host. Puede que no las active inmediatamente, pero has cambiado las capacidades declaradas del pool. Trátalo como una puerta de una sola dirección para la portabilidad hacia hosts más antiguos.
Task 15: Verify boot pool constraints (don’t brick your reboot)
cr0x@server:~$ zpool list -o name,size,health,altroot
NAME SIZE HEALTH ALTROOT
rpool 238G ONLINE -
tank 3.62T ONLINE -
Interpretación: Si rpool es tu boot pool, sé conservador. Un pool de datos varado en hosts más antiguos es molesto; un boot pool que deje de ser compatible con tu bootloader es catastrófico de una manera específica y que consume mucho tiempo.
Task 16: Export a pool cleanly before moving disks between hosts
cr0x@server:~$ sudo zpool export tank
cr0x@server:~$ zpool list
no pools available
Interpretación: Un export limpio reduce la fricción de importación y evita confusiones de “pool en uso”. No cambia las feature flags, pero sí previene problemas de caché de host y hace la próxima importación más limpia.
Guía rápida de diagnóstico
Este es el playbook “tengo diez minutos antes de que la reunión se vuelva incidente”. El objetivo es encontrar si estás lidiando con incompatibilidad de features, desajuste de versiones, o un cuello de botella de rendimiento que solo parece un problema de compatibilidad.
Step 1: Is it a hard compatibility failure or a general import failure?
cr0x@target:~$ sudo zpool import
pool: tank
id: 1234567890123456789
state: UNAVAIL
status: The pool uses the following feature(s) not supported by this system:
com.datto:encryption
action: The pool cannot be imported. Access the pool on a system that supports
the required feature(s), or restore the pool from backup.
Interpretación: Si ves explícito “feature(s) not supported”, deja de depurar discos y comienza a depurar versiones. Esto no es un problema de I/O; es una descoincidencia de capacidad de software.
Step 2: Confirm what the target host supports
cr0x@target:~$ zfs version
zfs-2.1.11
zfs-kmod-2.1.11
Interpretación: Si el host fuente está en 2.2.x y el destino en 2.1.x, deberías asumir que las descoincidencias de features son posibles. Alinea versiones intencionalmente; no esperes que la intersección funcione por sí sola.
Step 3: If import works but performance is awful, check for obvious pool stress
cr0x@target:~$ zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 1.88T 1.74T 120 980 8.2M 112M
sda - - 60 490 4.1M 56M
sdb - - 60 490 4.1M 56M
Interpretación: Si estás limitado por ancho de banda o IOPS durante import/receive/scrub, puedes atribuir erróneamente que “está atascado” a la compatibilidad. La incompatibilidad de features falla rápido y ruidosamente; los problemas de rendimiento fallan lentamente y de forma ambigua.
Step 4: Check whether a resilver or scrub is dominating the box
cr0x@target:~$ zpool status tank | sed -n '1,25p'
pool: tank
state: ONLINE
scan: resilver in progress since Tue Dec 24 22:10:01 2025
312G scanned at 1.20G/s, 58.4G issued at 230M/s, 312G total
58.4G resilvered, 18.72% done, 0 days 00:18:22 to go
Interpretación: Un resilver puede hacer que receives e importaciones “se sientan” rotas. Esto no son feature flags; es física. Si necesitas rapidez, pospone receives o limita cargas competidoras.
Step 5: If replication is failing, reproduce with a tiny stream
cr0x@source:~$ sudo zfs create -o mountpoint=none tank/_compat_test
cr0x@source:~$ sudo zfs snapshot tank/_compat_test@x
cr0x@source:~$ sudo zfs send tank/_compat_test@x | ssh target sudo zfs receive -u tank/_compat_rx
Interpretación: Un stream mínimo ayuda a aislar si la falla se debe a las propiedades/features del dataset o al pipeline (ssh, buffer, cuotas, espacio en el destino).
Errores comunes, síntomas y soluciones
Mistake 1: Upgrading the pool on one host and assuming the rest will cope
Síntoma: El host de DR rechaza la importación con “unsupported feature(s)” o recibes errores de receive de replicación después de un mantenimiento aparentemente no relacionado.
Solución: Alinea versiones de OpenZFS en todos los hosts que puedan importar el pool. Si eso no es posible, no ejecutes zpool upgrade en ese pool. Trata las actualizaciones de pool como un cambio en toda la flota.
Mistake 2: Treating boot pools like data pools
Síntoma: El sistema importa el pool en un entorno de rescate pero no arranca normalmente; o arranca de forma intermitente después de habilitar nuevas features.
Solución: Mantén los boot pools en conjuntos conservadores de features. Valida el soporte del bootloader antes de habilitar características. Prueba reinicios reales, no solo importaciones.
Mistake 3: Confusing “enabled” features with “active” consequences
Síntoma: El pool se importó en un host más antiguo el mes pasado, ahora se niega después de un cambio de propiedad o una nueva carga de trabajo.
Solución: Rastrea qué features pueden volverse active debido a cambios operativos. Cuando habilitas una propiedad que depende de una feature, asume que puede activarse inmediatamente y cambiar la portabilidad.
Mistake 4: Replicating without testing receives on the oldest target
Síntoma: La replicación incremental empieza a fallar, pero el monitoreo solo comprueba snapshots o los códigos de salida de trabajos de send se pierden.
Solución: Implementa verificación explícita de receives y alerta en salidas no nulas. Periódicamente realiza una pequeña prueba end-to-end de send/receive para compatibilidad.
Mistake 5: Thinking read-only import solves unsupported feature flags
Síntoma: Intentas -o readonly=on y aún no puedes importar; la frustración aumenta.
Solución: Si el host no soporta una feature active, necesitas un host que lo haga. Solo-lectura cambia el comportamiento de escritura, no la comprensión de metadatos.
Mistake 6: Userland and kernel module mismatch
Síntoma: Reportes extraños de features, propiedades faltantes, o herramientas que se comportan diferente en hosts con paquetes de “misma versión”.
Solución: Verifica que zfs version muestre userland y módulo alineados. En Linux, asegúrate de que DKMS/kmod y paquetes userland coincidan. Reconstruye initramfs si es necesario después de actualizaciones.
Mistake 7: Importing pools on random rescue media
Síntoma: El pool no se importa durante una recuperación, pero sí en el host de producción.
Solución: Mantén un entorno de recuperación conocido-bueno que coincida con el conjunto de features ZFS de producción. Pruébalo trimestralmente. Trata las herramientas de recuperación como parte del sistema.
Listas de verificación / plan paso a paso
Checklist A: Before enabling new features or running zpool upgrade
- Inventaria cada host que pueda necesitar importar el pool (producción, DR, standby, backup, imágenes de rescate).
- Registra las versiones de OpenZFS en cada host con
zfs version. - En el pool, lista las features active:
zpool get all POOL | grep '^POOL feature@' | grep active. - En cada host destino, ejecuta
zpool import(con los discos visibles) para confirmar que al menos puede ver el pool y no se queja de features. - Ejecuta una prueba send/receive en sandbox al host más antiguo de la matriz.
- Para boot pools, valida la ruta de reinicio: bootloader, initramfs, carga de claves (si está encriptado), y procedimiento de rollback.
- Solo entonces decide si la nueva feature vale la pena a costa de reducir la portabilidad.
Checklist B: Migration between hosts (export/import) without surprises
- En el origen: confirma la salud del pool (
zpool status), estado de scrub y contadores de error. - En el origen: captura snapshot de features y propiedades para registros:
zpool get all POOL | grep feature@zfs get -r all POOL > /var/tmp/pool-properties.txt(ten cuidado con info sensible)
- Exporta limpiamente:
zpool export POOL. - En el destino: verifica versiones; asegúrate de que el módulo del kernel esté cargado.
- En el destino: ejecuta
zpool importpara comprobar si hay quejas de features. - Importa con
-Nprimero para inspección, luego monta intencionalmente.
Checklist C: Replication compatibility across versions
- Identifica la versión más antigua del receptor que debes soportar.
- Prueba receives con un dataset mínimo (Task 5 en el playbook).
- Para datasets encriptados, verifica flujos de carga de claves en el receptor antes de llamarlo “réplica”.
- Alerta explícitamente en fallos de receive; no infieras salud de replicación solo por snapshots.
- Cuando actualices features del pool, vuelve a ejecutar pruebas de replicación inmediatamente después.
Preguntas frecuentes
1) If I upgrade OpenZFS on a host, does that upgrade my pools?
No. Actualizar el software aumenta lo que el host puede soportar. Tus pools mantienen sus estados de feature existentes hasta que explícitamente habilites features (vía zpool upgrade) o actives features indirectamente (vía propiedades/cargas de trabajo que dependen de ellas).
2) Is zpool upgrade reversible?
En la práctica, no. A veces puedes “evitar activar” ciertas features no usándolas, pero una vez que una feature está active y el pool ha escrito estructuras que la requieren, no puedes degradar el pool para que sea importable en hosts más antiguos.
3) What’s the difference between “enabled” and “active” in terms of portability?
Active significa que el pool está usando la feature y hosts más antiguos que no la soportan se negarán a importar. Enabled significa que el pool puede usarla más adelante. Las features enabled pueden importar, pero las active suelen ser el muro duro.
4) Can I import a pool on an older host if I promise not to mount it or write to it?
Si el host carece de soporte para una feature active, generalmente no puede importar el pool en absoluto—en modo solo-lectura o no—porque no puede interpretar metadatos requeridos de forma segura.
5) Why did replication start failing after months of working?
O bien el pool fuente activó una feature (posiblemente vía un cambio de propiedad), o el stream de send ahora incluye requisitos que el receptor no puede satisfacer. Otra causa común es que el receptor fue actualizado/retrocedido inadvertidamente y perdió soporte o alineamiento de herramientas.
6) Does cross-platform ZFS (Linux ↔ FreeBSD) change the rules?
La lógica central de feature flags es la misma, pero el calendario de lanzamientos difiere. Una feature que es común en una plataforma puede retrasarse en otra. Trata “diferencias de plataforma” como “diferencias de versión”, y prueba importaciones y receives en los builds exactos que ejecutas.
7) Should I always run zpool upgrade to get rid of the status warning?
No. Esa advertencia es informativa, no una alarma de fiabilidad. Dejar un pool sin actualizar es una estrategia válida cuando la portabilidad importa—especialmente para pools removibles, importaciones de DR, o entornos con hosts heterogéneos.
8) How do I design a safe compatibility policy for a fleet?
Elige una versión mínima de OpenZFS que cada host relevante deba ejecutar. Solo habilita features de pool que estén soportadas por esa mínima. Cuando necesites una nueva feature, trátala como una migración de esquema: actualiza hosts primero, luego actualiza pools al final, y prueba DR/replicación en cada paso.
9) What about encrypted datasets—are they compatible with send/receive everywhere?
La encriptación introduce requisitos adicionales: el receptor debe soportar la feature de encriptación y tu modo de replicación debe alinearse con tus objetivos de gestión de claves. Incluso cuando el pool se importa, la preparación operativa depende de si las claves pueden cargarse y cómo manejas keylocation y keystatus en DR.
10) What’s the single safest habit with feature flags?
Asume que cualquier actualización de feature de pool es una degradación de portabilidad. Si estás de acuerdo con ese trade-off, procede deliberadamente; si no lo estás, no dejes que un mensaje de estado te avergüence para pulsar el botón.
Conclusión
Las banderas de características de ZFS no son trivia; son el contrato de tu pool con cada máquina que pueda necesitar leerlo bajo presión. Hacen la compatibilidad más explícita que el antiguo sistema de versiones de pool, pero también vuelven las actualizaciones más trascendentes: no puedes permanecer accidentalmente portátil una vez que cruzas el umbral de una feature.
Si recuerdas solo una cosa, recuerda esto: actualiza hosts primero, valida importaciones y receives en el entorno más antiguo, y actualiza pools al final. Los equipos que hacen esto parecen aburridos en las revisiones de cambios. También parecen brillantes el día que la caja de repuesto se convierte en la caja de producción.