ZFS zpool split: clonar un pool mirror para migración o DR

¿Te fue útil?

Hay dos tipos de migraciones: las que planificas y las que tu almacenamiento te obliga a realizar a las 2 a.m. tras una actualización de firmware “menor”. Si gestionas pools ZFS en espejo, zpool split es una de las pocas herramientas que puede convertir una migración en una operación controlada y en su mayoría aburrida: literalmente separas un lado de tus mirrors y te vas con un segundo pool.

Esto no es un cuento de hadas de “clon instantáneo” para marketing. Dividir un pool es algo decisivo: cambias la postura de redundancia, creas una segunda identidad para el almacenamiento y haces promesas a tu yo futuro sobre importabilidad, puntos de montaje, claves de cifrado y el estado del último grupo de transacciones (TXG) cuando tiraste del seguro. Bien hecho, es una semilla de DR limpia o un arranque rápido para migración. Hecho de forma descuidada, es un billete hacia el país de “¿por qué producción montó la copia de DR y empezó a escribir en ella?”.

Qué es realmente zpool split (y qué no es)

zpool split toma un pool que contiene vdevs en espejo y crea un nuevo pool separando miembros del mirror. Conceptualmente: cada vdev mirror es un par (o más) de discos; el split te permite despegar un disco de cada mirror para formar un nuevo pool con la misma estructura de datasets y metadatos. No es copiar bloques; es reasignar la propiedad de discos existentes.

Por eso es rápido. También explica la primera regla del split: solo obtienes un “pool completo” si tienes suficientes mirrors como para donar un miembro de cada vdev en espejo. Si tu pool es un único vdev mirror de dos discos, un split aún puede crear un nuevo pool, pero efectivamente estás convirtiendo un disco en un pool de un solo disco. Eso puede ser aceptable para una etapa temporal de migración y puede ser inaceptable para cualquier cosa con la que planees dormir tranquilo.

Para qué sirve

  • Etapa de migración: Split, envía discos (o muévelos a un nuevo chasis), importa y habrás trasladado la identidad del pool sin transferencia por red.
  • Creación de semilla de DR: Divide para crear rápidamente un pool DR inicial y luego usa zfs send incremental para mantenerlo actualizado.
  • Duplicación rápida de entornos: Clona un árbol de datasets de producción para un trabajo puntual de análisis y luego destruye el pool split.

Lo que no es

  • No es una copia de seguridad. Si tus datos están corruptos, con suerte tendrás dos copias de la corrupción.
  • No es un mecanismo de snapshots. El pool dividido refleja el estado del pool en el límite TXG cuando se realizó el split, no es un snapshot de dataset que puedas navegar.
  • No sustituye una estrategia de replicación. Es una herramienta en la caja de herramientas, no la caja entera.

Broma #1: Dividir un pool mirror es como fotocopiar la llave de tu casa serrándola a la mitad: tendrás dos llaves, pero la cerradura puede empezar a tener opiniones.

Datos & contexto histórico (el “porqué” del control)

ZFS tiene buena memoria, al igual que los ingenieros que dejaron flujos operativos montados sobre él. Aquí hay algunos hechos y puntos de contexto que explican por qué existe zpool split y cómo terminó en runbooks reales:

  1. ZFS se diseñó alrededor del almacenamiento agrupado, no dispositivos por sistema de ficheros. Por eso operaciones como split actúan sobre la topología del pool, no sobre “un filesystem” como hacían herramientas antiguas.
  2. Los mirrors siempre fueron el vdev “amigable operacionalmente”. En producción, los mirrors son populares porque se sanan rápido, degradan de forma predecible y toleran reemplazos de disco mezclados mejor que los vdevs paridad.
  3. El formato en disco es portátil entre sistemas que comparten feature flags. Importar un pool en otro host es normal, pero solo si las feature flags coinciden y el SO las soporta.
  4. Split es una transformación de topología, no un movimiento de datos. Por eso es instantáneo comparado con zfs send, y también por eso cambia tu redundancia de inmediato.
  5. Históricamente, las migraciones por “sneakernet” eran comunes. Antes de que 10/25/40/100GbE baratos fueran ubicuos (y confiables al 95% de utilización por 12 horas), mover discos era un camino legítimo de migración.
  6. Los checksums de ZFS hicieron mover discos más seguro que en sistemas de ficheros antiguos. Al importar en el extremo remoto tienes verificación end-to-end mediante scrub y checksums por bloque.
  7. Los GUIDs de pool y las rutas de dispositivos están intencionalmente abstraídos. ZFS rastrea GUIDs de vdev; los nombres de dispositivos del SO pueden cambiar y el pool aún así importará—si usaste rutas estables by-id en primer lugar.
  8. Las feature flags convirtieron “importa en cualquier lado” en “importa donde debe”. Habilitar características nuevas puede bloquear la importación en plataformas más antiguas; split no cambia eso, pero te obliga a enfrentarlo.
  9. Los entornos de arranque y root-on-ZFS hicieron el split más interesante. Dividir un pool que contiene el SO es posible, pero entonces entras en el terreno de compatibilidad del bootloader y los host IDs.

Cuándo usar split vs send/receive vs replicación

Si tienes un pool mirror y acceso físico a los discos, split es la forma más rápida de crear un segundo pool con el mismo árbol de datasets. Pero “rápido” no es lo mismo que “mejor”. Así es como decido.

Usa zpool split cuando

  • Tienes vdevs en espejo y puedes ceder temporalmente un lado.
  • Necesitas una semilla DR rápida y la ventana de replicación por red es inaceptable.
  • Quieres migrar un pool grande a nuevo hardware sin saturar enlaces por días.
  • Puedes tolerar una reducción temporal de redundancia en el pool origen (porque tras el split, el origen tendrá menos miembros del mirror).

Prefiere zfs send | zfs receive cuando

  • Necesitas semántica punto-en-el-tiempo: snapshots, incrementales, opciones de rollback.
  • No puedes reducir la redundancia en producción ni siquiera brevemente.
  • Tus vdevs no son mirrors (RAIDZ no se divide así).
  • Necesitas transformar propiedades como recordsize, cifrado o layout de datasets durante la migración y quieres control deliberado.

Prefiere replicación verdadera cuando

  • Necesitas DR continuo auditado con objetivos RPO y RTO.
  • Debes conservar puntos históricos (políticas de retención de snapshots).
  • Tienes múltiples destinos downstream o necesitas replicar a través de límites de confianza.

Broma #2: La transferencia de datos más rápida sigue siendo una persona cargando discos—hasta que alguien los pone en una mochila con un imán, y ahora has inventado arte de performance.

Preflight: qué confirmar antes de dividir

Dividir un pool es sencillo. Dividir un pool y estar seguro de lo que ocurre después es donde los adultos se ganan el café.

Confirmar topología: solo mirrors

Necesitas vdevs mirror. Si tu pool incluye vdevs RAIDZ, zpool split no hará lo que quieres. Los pools de topología mixta son comunes en entornos “crecimos con el tiempo”—confirma lo que realmente tienes.

Confirmar feature flags y soporte del SO destino

Si divides un pool en un host con características ZFS más nuevas activadas y luego intentas importar en un appliance más antiguo, puede que la importación sea rechazada. Este es el modo de fallo #1 “funcionó en laboratorio” que he visto en migraciones empresariales.

Confirmar manejo de claves de cifrado

El cifrado nativo de ZFS (a nivel dataset) se mueve con los datos en disco. El pool split contendrá datasets cifrados; importar no es lo mismo que montar. Asegúrate de que el host receptor tiene acceso a las claves y sabes si se cargan automáticamente o manualmente.

Confirmar IDs de dispositivo estables

En Linux, /dev/sdX es una sugerencia, no un contrato. Usa /dev/disk/by-id para mayor cordura. En el destino, la enumeración de dispositivos será diferente; ZFS suele encontrarlos, pero tu tiempo de resolución explota si no puedes mapear “este número de serie” a “este miembro vdev”.

Confirmar estrategia de puntos de montaje

Tras el split e import, los datasets pueden montarse automáticamente. Eso está bien hasta que se montan en el host equivocado con rutas equivocadas, y de repente tienes dos servidores escribiendo en copias distintas creyéndose autoritarias. Planifica tus mountpoints y la postura de canmount antes de importar.

Tareas prácticas: comandos y cómo leer la salida

Las siguientes tareas están escritas como si estuvieras en un host Linux con OpenZFS. Ajusta nombres de servicios y rutas según tu plataforma. Cada tarea es algo que he ejecutado en serio o que desearía haber ejecutado antes de que el pager se presentara.

Tarea 1: Inventariar el pool y confirmar mirrors

cr0x@server:~$ sudo zpool status -v tank
  pool: tank
 state: ONLINE
config:

        NAME                         STATE     READ WRITE CKSUM
        tank                         ONLINE       0     0     0
          mirror-0                   ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_AAA  ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_BBB  ONLINE       0     0     0
          mirror-1                   ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_CCC  ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_DDD  ONLINE       0     0     0

errors: No known data errors

Interpretación: Quieres que cada vdev de primer nivel sea mirror-N. Si ves raidz o discos individuales, el split será parcial o imposible. También revisa errores existentes; dividir un mirror degradado crea un nuevo pool que puede nacer enfermo.

Tarea 2: Comprobar la presión I/O actual antes de hacer algo disruptivo

cr0x@server:~$ iostat -x 2 3
Linux 6.8.0 (server)  12/25/2025  _x86_64_ (32 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           6.12    0.00    1.88    0.74    0.00   91.26

Device            r/s     w/s   rkB/s   wkB/s  await  svctm  %util
nvme0n1          5.0    40.0   640.0  5120.0   2.10   0.15   0.70

Interpretación: Un split es rápido, pero el riesgo operativo viene de lo que haces alrededor (scrubs, exports, imports). Si el pool ya está saturado (%util cerca de 100% y await alto), programa una ventana más tranquila.

Tarea 3: Confirmar feature flags y postura de compatibilidad

cr0x@server:~$ sudo zpool get all tank | egrep 'feature@|compatibility|version'
tank  compatibility  -          default
tank  feature@async_destroy  enabled  local
tank  feature@bookmarks      enabled  local
tank  feature@encryption     enabled  local
tank  feature@edonr          enabled  local

Interpretación: El pool split llevará estas features. Si el host destino no las soporta, la importación puede fallar. Trata “feature enabled” como un requisito estricto para la pila destino.

Tarea 4: Capturar la lista de datasets y propiedades críticas (mountpoints, canmount)

cr0x@server:~$ sudo zfs list -r -o name,used,avail,mountpoint,canmount,encryption,keylocation tank
NAME             USED  AVAIL  MOUNTPOINT     CANMOUNT  ENCRYPTION  KEYLOCATION
tank             220G   700G  /tank          on        off         -
tank/apps         80G   700G  /tank/apps     on        aes-256-gcm file:///root/keys/apps.key
tank/home         40G   700G  /tank/home     on        off         -
tank/vm          100G   700G  /tank/vm       on        aes-256-gcm prompt

Interpretación: Este es tu mapa de “qué se montará dónde”. En un host de DR, puede que quieras canmount=off hasta estar listo. También nota keylocation y si las claves son en fichero o por prompt.

Tarea 5: Crear un conjunto de “snapshots de seguridad” (opcional pero casi siempre sensato)

cr0x@server:~$ sudo zfs snapshot -r tank@pre-split-2025-12-25
cr0x@server:~$ sudo zfs list -t snapshot -r tank | tail -5
tank/apps@pre-split-2025-12-25  0B  -
tank/home@pre-split-2025-12-25  0B  -
tank/vm@pre-split-2025-12-25    0B  -

Interpretación: Un split no requiere snapshots, pero los snapshots te dan rollback y opciones de send/receive si el plan de “mover discos” se tuerce. Es un seguro barato.

Tarea 6: Aplacar escritores riesgosos (bases de datos, imágenes de VM) y verificar

cr0x@server:~$ sudo systemctl stop postgresql
cr0x@server:~$ sudo systemctl stop libvirtd
cr0x@server:~$ sudo lsof +D /tank/vm | head
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME

Interpretación: Para una migración/semilla DR quieres al menos consistencia por crash; para bases de datos quieres consistencia a nivel de aplicación si puedes. Si lsof todavía muestra ficheros ocupados bajo datasets críticos, no estás quiesced.

Tarea 7: Ejecutar una comprobación rápida de salud y considerar programar un scrub

cr0x@server:~$ sudo zpool status tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 00:21:33 with 0 errors on Sun Dec 22 02:14:01 2025
config:
...
errors: No known data errors

Interpretación: Si el último scrub es antiguo o hay errores, soluciona eso primero. Dividir un pool no es el momento para descubrir que un miembro del mirror ha estado lanzando errores de checksum silenciosamente.

Tarea 8: Realizar el split para crear un nuevo nombre de pool

cr0x@server:~$ sudo zpool split tank tank_dr
cr0x@server:~$ sudo zpool status -v tank
  pool: tank
 state: ONLINE
config:

        NAME                         STATE     READ WRITE CKSUM
        tank                         ONLINE       0     0     0
          mirror-0                   ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_AAA  ONLINE       0     0     0
          mirror-1                   ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_CCC  ONLINE       0     0     0

errors: No known data errors

cr0x@server:~$ sudo zpool status -v tank_dr
  pool: tank_dr
 state: ONLINE
config:

        NAME                         STATE     READ WRITE CKSUM
        tank_dr                      ONLINE       0     0     0
          ata-SAMSUNG_SSD_1TB_BBB    ONLINE       0     0     0
          ata-SAMSUNG_SSD_1TB_DDD    ONLINE       0     0     0

errors: No known data errors

Interpretación: En muchas configuraciones, el nuevo pool se crea a partir del “otro lado” de cada mirror. Nota que tank_dr aquí aparece ahora con vdevs de primer nivel de un solo disco (no mirrors) porque cada mirror contribuyó con un disco. Esta es la parte que la gente olvida: a menudo cambias redundancia por portabilidad. Si quieres que el pool split también sea mirror, necesitas discos adicionales para adjuntar después en el destino.

Tarea 9: Ajustar inmediatamente la postura de auto-mount en el pool split (recomendado)

cr0x@server:~$ sudo zfs set canmount=off tank_dr
cr0x@server:~$ sudo zfs set mountpoint=/tank_dr tank_dr
cr0x@server:~$ sudo zfs list -o name,mountpoint,canmount tank_dr
NAME     MOUNTPOINT  CANMOUNT
tank_dr  /tank_dr    off

Interpretación: Esto evita montajes accidentales en el host origen (o en un host destino que importe automáticamente). Puedes volver a habilitar montajes por dataset más tarde.

Tarea 10: Exportar el pool split para traslado físico

cr0x@server:~$ sudo zpool export tank_dr
cr0x@server:~$ sudo zpool list
NAME   SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tank  1.81T   220G  1.60T        -         -     3%    11%  1.00x  ONLINE  -

Interpretación: Exporta limpiamente para que la importación en destino no parezca un “pool robado” de un host todavía vivo. Esto reduce fricción de importación y previene conflictos accidentales de multi-import.

Tarea 11: En el destino, localizar discos por ID estable e importar primero en solo lectura

cr0x@drhost:~$ sudo ls -l /dev/disk/by-id/ | egrep 'SAMSUNG_SSD_1TB_(BBB|DDD)'
lrwxrwxrwx 1 root root  9 Dec 25 09:02 ata-SAMSUNG_SSD_1TB_BBB -> ../../sdb
lrwxrwxrwx 1 root root  9 Dec 25 09:02 ata-SAMSUNG_SSD_1TB_DDD -> ../../sdc

cr0x@drhost:~$ sudo zpool import
   pool: tank_dr
     id: 15277416958755799222
  state: ONLINE
 action: The pool can be imported using its name or numeric identifier.
 config:

        tank_dr                    ONLINE
          ata-SAMSUNG_SSD_1TB_BBB  ONLINE
          ata-SAMSUNG_SSD_1TB_DDD  ONLINE

cr0x@drhost:~$ sudo zpool import -o readonly=on -o cachefile=none tank_dr
cr0x@drhost:~$ sudo zpool get readonly tank_dr
NAME     PROPERTY  VALUE     SOURCE
tank_dr  readonly  on        local

Interpretación: La importación en solo lectura es un aterrizaje fantástico. Te permite inspeccionar datasets, validar la estructura y confirmar que no trajiste los discos equivocados—sin cambiar el estado en disco.

Tarea 12: Cargar claves de cifrado y montar deliberadamente

cr0x@drhost:~$ sudo zfs load-key -r tank_dr/apps
Enter passphrase for 'tank_dr/apps':
cr0x@drhost:~$ sudo zfs mount -a
cannot mount 'tank_dr': legacy mountpoint, use mount(8)

cr0x@drhost:~$ sudo zfs get -o name,property,value tank_dr | egrep 'mountpoint|canmount'
tank_dr  mountpoint  /tank_dr
tank_dr  canmount    off

Interpretación: Si pusiste canmount=off, un montaje masivo no montará el dataset superior. Eso es intencional. Monta los datasets hijos específicos que necesites, después de cargar claves y de confirmar que los puntos de montaje no colisionarán con rutas locales.

Tarea 13: Convertir el pool split de nuevo a mirrors en el destino (adjuntar discos nuevos)

cr0x@drhost:~$ sudo zpool status tank_dr
  pool: tank_dr
 state: ONLINE
config:

        NAME                         STATE     READ WRITE CKSUM
        tank_dr                      ONLINE       0     0     0
          ata-SAMSUNG_SSD_1TB_BBB    ONLINE       0     0     0
          ata-SAMSUNG_SSD_1TB_DDD    ONLINE       0     0     0

errors: No known data errors

cr0x@drhost:~$ sudo zpool attach tank_dr ata-SAMSUNG_SSD_1TB_BBB /dev/disk/by-id/ata-SAMSUNG_SSD_1TB_EEE
cr0x@drhost:~$ sudo zpool attach tank_dr ata-SAMSUNG_SSD_1TB_DDD /dev/disk/by-id/ata-SAMSUNG_SSD_1TB_FFF
cr0x@drhost:~$ sudo zpool status tank_dr
  pool: tank_dr
 state: ONLINE
  scan: resilver in progress since Thu Dec 25 09:24:11 2025
        52.1G scanned at 1.20G/s, 12.4G issued at 290M/s, 220G total
        12.4G resilvered, 5.64% done, 00:12:31 to go
config:

        NAME                              STATE     READ WRITE CKSUM
        tank_dr                           ONLINE       0     0     0
          mirror-0                        ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_BBB       ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_EEE       ONLINE       0     0     0
          mirror-1                        ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_DDD       ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_FFF       ONLINE       0     0     0

Interpretación: Así restauras redundancia tras enviar un pool split con un solo disco por vdev. Las tasas de resilver dependen de ashift, recordsize, comportamiento del disco y carga. Planifica el tiempo en consecuencia.

Tarea 14: Hacer el pool escribible y establecer cachefile para persistencia

cr0x@drhost:~$ sudo zpool export tank_dr
cr0x@drhost:~$ sudo zpool import -o readonly=off tank_dr
cr0x@drhost:~$ sudo zpool set cachefile=/etc/zfs/zpool.cache tank_dr
cr0x@drhost:~$ sudo zpool get cachefile tank_dr
NAME     PROPERTY  VALUE                 SOURCE
tank_dr  cachefile /etc/zfs/zpool.cache  local

Interpretación: La importación en solo lectura fue para validación; ahora pasas a operaciones normales. Establecer cachefile asegura que el pool sea recordado tras reinicios (dependiente de la plataforma).

Tarea 15: Validar integridad de datos con un scrub después de la importación

cr0x@drhost:~$ sudo zpool scrub tank_dr
cr0x@drhost:~$ sudo zpool status tank_dr
  pool: tank_dr
 state: ONLINE
  scan: scrub in progress since Thu Dec 25 10:02:18 2025
        88.3G scanned at 1.10G/s, 88.3G issued at 1.10G/s, 220G total
        0B repaired, 40.15% done, 00:01:52 to go
config:
...
errors: No known data errors

Interpretación: Un scrub tras la relocación es el movimiento de adulto. Detecta problemas de transporte, cables malos, HBAs marginales y “ese disco que solo falla cuando está frío”.

Listas de verificación / plan paso a paso

Checklist A: Semilla DR vía split (downtime mínimo, sorpresas mínimas)

  1. Confirmar que el pool usa solo mirrors: zpool status.
  2. Confirmar scrub reciente y limpio según tu apetito de riesgo.
  3. Registrar propiedades de datasets: mountpoints, canmount, estado de cifrado.
  4. Crear snapshots recursivos como respaldo y para incrementales futuros.
  5. Aplacar aplicaciones de alta actividad si necesitas consistencia a nivel de aplicación.
  6. Ejecutar zpool split para crear tank_dr.
  7. Poner canmount=off y/o ajustar mountpoints en tank_dr para evitar montajes accidentales.
  8. Exportar tank_dr.
  9. Mover discos, importar en solo lectura en destino, confirmar datasets y propiedades.
  10. Cargar claves de cifrado y montar selectivamente.
  11. Añadir discos nuevos y adjuntar para re-mirror, permitir que resilver termine.
  12. Scrub, luego pasar a replicación (sends incrementales) en adelante.

Checklist B: Migración a un nuevo host (manteniendo nombres de servicio y rutas sensatas)

  1. Decidir el momento de corte autoritativo: ¿cuándo el destino se vuelve escribible?
  2. Antes del split: poner canmount=off en datasets críticos si quieres montarlos manualmente tras la importación.
  3. Split y export del nuevo pool.
  4. En el host nuevo: importar con -o altroot=/mnt para inspección si quieres cero riesgo de montar en rutas de producción.
  5. Validar: zfs list, zpool status, comprobar que se puedan cargar claves de cifrado.
  6. Cuando estés listo: export/import normalmente, establecer mountpoints correctos, habilitar montajes.
  7. Iniciar servicios y validar salud a nivel aplicación.

Tres micro-historias del mundo corporativo (fallos y la que salvó el día)

1) Incidente causado por una suposición errónea: “El pool split es una copia de seguridad”

En una empresa mediana con un backend ZFS altamente espejado, un equipo creó una semilla DR separando un pool de producción y enviando los discos a un segundo sitio. Hicieron la mecánica correctamente: split, export, import, mount. Se sintieron bien. Demasiado bien.

Dos meses después, un desarrollador aplicó una migración de esquema que eliminó un conjunto de tablas de manera que la app no lo notó de inmediato. El daño fue silencioso: las escrituras siguieron y la monitorización miraba tasas de peticiones, no corrección de datos. Cuando descubrieron el problema, fueron a “la copia DR”. Tenía los mismos datos faltantes. Por supuesto: no estaban haciendo replicación basada en snapshots con retención; simplemente habían creado una segunda copia viva y periódicamente volvían a split como “actualización”.

La suposición errónea fue sutil: “Tenemos otro pool, por tanto tenemos recuperación.” Pero la recuperación requiere tiempo como dimensión—historial, puntos en el tiempo, retención—y el pool split no tenía nada de eso. Era un clon, no una copia de seguridad.

La corrección operativa fue sencilla pero dolorosa: implementaron snapshots disciplinados (con nombres y retención), y luego replicación incremental. Aún usaron split para sembrar rápidamente almacenamiento DR, pero solo como primer paso en una canalización real de DR.

La corrección cultural fue la mayor ganancia: dejaron de llamar al pool split “backup” en tickets y dashboards. Las palabras importan. Si lo nombras “backup”, alguien eventualmente apostará el negocio a ello.

2) Optimización que salió mal: “Hagamos el split en hora punta; es instantáneo”

Otra organización tenía un pool mirror que sustentaba un cluster de virtualización. Alguien propuso un plan inteligente: hacer el split durante horas de trabajo porque el split en sí es instantáneo, luego exportar y mover discos tras la ventana de cambios de la noche. Sonaba eficiente. La primera mitad era verdad. La segunda fue donde la realidad llegó con recibos.

Dividir el pool redujo inmediatamente el número de miembros de mirror en producción. El pool permaneció ONLINE, pero el perfil de rendimiento cambió. Algunas cargas que se beneficiaban de “paralelismo accidental” de lecturas desde los mirrors (y algo de calor de caché) se vieron compitiendo más agresivamente por IOPS. La latencia subió, no catastróficamente, pero lo suficiente como para disparar timeouts en un servicio interno muy parlanchín. El servicio empezó a fallar, los reintentos aumentaron y el amplificador de carga convirtió una pequeña subida de latencia en un incidente menor.

Aprendieron dos lecciones prácticas. Primero: en sistemas reales, las operaciones “instantáneas” pueden tener efectos de segundo orden. Quitar miembros del mirror puede cambiar la planificación y el comportamiento de colas de formas que tu benchmark feliz nunca ejercitó. Segundo: las migraciones no son solo operaciones de almacenamiento; son eventos de rendimiento. Si tu servicio está ajustado al límite, los cambios de topología se notan.

La remediación fue simple: hacer el split en una ventana tranquila, y si necesitas seguridad diurna, usar una semilla basada en snapshots para replicación. También añadieron una puerta de rendimiento pre-split: si la latencia al percentil 95 ya está elevada, no se hacen cambios de topología.

3) Práctica aburrida pero correcta que salvó el día: IDs de dispositivo estables y exports disciplinados

Una de las migraciones basadas en split más exitosas que he visto fue casi agresivamente poco interesante. El equipo tenía una regla: los pools se construyen usando rutas estables /dev/disk/by-id siempre, sin excepciones. También tenían la costumbre de exportar pools antes de cualquier movimiento físico—incluso si “solo vamos a reiniciar para nuevo firmware”.

Durante una migración de centro de datos, dividieron un pool mirror en un pool de migración, lo exportaron y movieron los discos a nuevos hosts. En el destino, la enumeración de dispositivos fue distinta, los HBAs eran diferentes y un par de discos acabaron en un backplane distinto al planeado. Nada de eso importó. zpool import encontró el pool por labels, y el naming by-id dejó claro qué números de serie faltaban cuando un cable no estaba bien conectado.

La práctica aburrida importó de nuevo cuando alguien intentó importar el pool en un host “staging” para inspeccionar datos mientras el host destino se montaba en rack. Como el pool había sido exportado limpiamente, no hubo confusión de “el pool estaba en uso antes”, ni import forzado, ni riesgo de que dos sistemas pensaran que lo poseían al mismo tiempo.

No pasó nada dramático, que es precisamente el punto. En producción, “no pasó nada dramático” es una característica que se gana con hábitos que parecen pedantes hasta que dejan de serlo.

Guía de diagnóstico rápido (qué comprobar primero, segundo, tercero)

Cuando una migración basada en split va lenta o extraña, no tienes tiempo para convertirte en filósofo. Este es el orden de triage rápido que uso para encontrar el cuello de botella y decidir si parar, continuar o retroceder.

Primero: ¿Es un problema de salud ZFS o del SO/hardware?

cr0x@server:~$ sudo zpool status -x
all pools are healthy

cr0x@server:~$ dmesg | tail -30
[...]
[ 8921.221] ata9.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
[ 8921.223] blk_update_request: I/O error, dev sdc, sector 12345678 op 0x0:(READ)

Decisión: Si dmesg muestra errores/timeout de I/O, para y estabiliza el hardware antes de culpar a ZFS. ZFS puede sobrevivir mucho, pero no puede negociar con un enlace SATA que está realizando danza interpretativa.

Segundo: ¿Un resilver/scrub domina el I/O?

cr0x@drhost:~$ sudo zpool status tank_dr
  pool: tank_dr
 state: ONLINE
  scan: resilver in progress since Thu Dec 25 09:24:11 2025
        180G scanned, 95G issued, 220G total
        95G resilvered, 43.18% done, 00:08:41 to go

Decisión: Si hay resilver activo, el rendimiento suele ser “funcionando como diseñado”. O esperas o ajustas expectativas. Si el negocio necesita rendimiento ya, considera posponer algunas cargas hasta que termine el resilver.

Tercero: ¿Estás limitado por CPU, ARC o disco?

cr0x@drhost:~$ sudo arcstat 2 5
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
09:40:01   812   121     14     0    0    31    4    90   11   42G   64G
09:40:03   905   188     20     0    0    45    5   143   15   42G   64G

Decisión: Tasas de miss altas durante pruebas de migración pueden parecer “almacenamiento lento” cuando en realidad es caché fría. Calienta las cargas o prueba con condiciones de caché realistas. Si la CPU está alta y usas cifrado/compresión, verifica si estás limitado por CPU.

Cuarto: ¿Los montajes y propiedades están haciendo algo sorprendente?

cr0x@drhost:~$ sudo zfs get -r -o name,property,value canmount,mountpoint tank_dr | head -20
NAME         PROPERTY    VALUE
tank_dr      canmount    off
tank_dr      mountpoint  /tank_dr
tank_dr/apps canmount    on
tank_dr/apps mountpoint  /tank/apps

Decisión: Si un dataset hijo aún apunta a un mountpoint de producción (como /tank/apps), puedes montar sobre directorios existentes en el host DR. Así es como terminas “probando DR” sobrescribiendo algo que te gustaba.

Errores comunes (con síntomas y correcciones)

Error 1: Dividir sin darse cuenta de que pierdes redundancia

Síntoma: Tras el split, el nuevo pool muestra vdevs de primer nivel de un solo disco; el pool antiguo ahora tiene menos miembros; cambia el rendimiento; cambia la postura de riesgo.

Corrección: Planea usar zpool attach nuevos discos en el destino para restaurar mirrors, o acepta explícitamente el riesgo para un pool de migración de corta vida. Documenta esto en el registro de cambios; tu yo futuro lo olvidará.

Error 2: Importar y auto-montar en rutas de producción

Síntoma: Tras la importación, los datasets se montan bajo rutas que colisionan con directorios existentes; servicios empiezan a leer/escribir en la copia equivocada.

Corrección: Importa con -o altroot=/mnt para inspeccionar, o establece canmount=off antes del export. Solo habilita montajes cuando estés listo.

Error 3: Olvidar flujos de trabajo de claves de cifrado en destino

Síntoma: El pool importa, pero los datasets no montan; las aplicaciones ven directorios vacíos; zfs mount falla por errores relacionados con claves.

Corrección: Confirma zfs get encryption,keylocation,keystatus. Mueve material de claves de forma segura, prueba zfs load-key y no asumas que “importar” equivale a “usable”.

Error 4: Mismatch de feature flags entre origen y destino

Síntoma: zpool import se niega con “unsupported feature(s)” o similar.

Corrección: Actualiza la pila ZFS en destino para soportar las feature flags del pool. Si debes soportar sistemas antiguos, tenías que planear eso antes de habilitar features en el origen—ZFS no hace “downgrade”.

Error 5: Usar nombres de dispositivo inestables y perder rastreo de discos

Síntoma: Importación confusa post-movimiento; no puedes mapear /dev/sdX a discos reales; operaciones erróneas sobre discos se vuelven probables.

Corrección: Construye y opera usando /dev/disk/by-id. Al depurar, usa números de serie como verdad fundamental.

Error 6: Dividir un pool con errores existentes o un mirror degradado

Síntoma: El pool split importa pero los scrubs muestran errores de checksum; los resilvers tardan una eternidad; un disco empieza a lanzar errores de I/O.

Corrección: Estabiliza primero: reemplaza discos fallando, limpia errores mencionados en zpool status -v, ejecuta un scrub y luego divide. Si debes dividir bajo presión, importa en solo lectura en destino y haz un scrub inmediatamente para evaluar el daño.

Error 7: Asumir que split te da un “punto en el tiempo” coherente entre aplicaciones

Síntoma: Bases de datos se recuperan pero con transacciones recientes faltantes o inconsistentes; sistemas de archivos de VM muestran replays de journal.

Corrección: Quiesce las apps o usa snapshots coordinados con hooks de aplicación. Split captura el estado del pool, no la coherencia de la aplicación.

Preguntas frecuentes

1) ¿Hace zpool split una copia de los datos?

No. Reasigna miembros del mirror para formar un nuevo pool. Es rápido porque no mueve bloques; cambia la propiedad de discos existentes.

2) ¿Puedo dividir un pool RAIDZ?

No, no en el sentido de “clonar el pool”. zpool split es para mirrors. Los vdevs RAIDZ no tienen miembros independientes que puedan convertirse en vdevs coherentes por sí mismos.

3) ¿El pool split tendrá los mismos datasets y snapshots?

Sí: los datasets, propiedades y snapshots presentes al momento del split viajan porque los datos en disco son los mismos. Pero recuerda: no es una copia de seguridad. Si el origen tenía corrupción lógica, ahora tienes dos copias de ella.

4) ¿Qué pasa con los GUIDs y nombres de pool?

El nuevo pool obtiene su propia identidad (nuevo nombre de pool, GUID distinto). Esto es bueno: reduce la confusión de “mismo pool importado dos veces”, pero aun así debes tener cuidado con mountpoints y automatizaciones del host.

5) ¿Puedo importar el pool split en otro host mientras el original sigue en funcionamiento?

Sí, a menudo ese es el objetivo. Pero debes exportar el pool split limpiamente y tratarlo como un sistema separado: evita montar en rutas compartidas y asegura que ninguna aplicación escriba en ambas copias a menos que eso esté diseñado explícitamente (normalmente no lo está).

6) ¿Cómo mantengo el pool DR actualizado después de la semilla inicial split?

Generalmente con incrementales basados en snapshots: toma snapshots en el origen y usa zfs send/zfs receive hacia el pool DR. Split es genial para la primera copia; la replicación es cómo la mantienes actualizada.

7) ¿Y el cifrado nativo—el split “lo rompe”?

No. Los metadatos de cifrado forman parte de los datasets. Pero operativamente necesitas las claves en el destino para montar datasets cifrados. Planifica la distribución de claves y prueba la carga de claves antes de declarar victoria.

8) ¿Es seguro ejecutar zpool split mientras el pool está online y en uso?

Se puede hacer en caliente, pero “seguro” depende de tu carga y tolerancia al riesgo. El split en sí es rápido, pero quitar miembros del mirror cambia la redundancia y puede alterar la latencia bajo carga. Para bases de datos e imágenes VM prefiero aplacar o hacerlo en una ventana de baja actividad.

9) ¿Puedo “deshacer” un split?

No hay un comando mágico de deshacer. Puedes volver a adjuntar discos y re-mirror, o destruir un pool y volver a adjuntar sus discos, pero debes tratarlo como un cambio de topología con consecuencias. Si necesitas reversibilidad, considera replicación por snapshots en su lugar.

10) ¿Por qué importar primero en solo lectura?

Porque es la forma más segura de confirmar que trajiste los discos correctos y que el pool está sano sin avanzar el estado en disco. Es una comprobación barata antes de dejar que los servicios se le acerquen.

Conclusión

zpool split es una de esas características de ZFS que se siente como hacer trampa la primera vez que la usas: clon instantáneo de pool, sin copia por red, sin espera. En producción es potente precisamente porque es contundente. No estás creando una “copia” en el sentido de backup—estás creando un segundo pool sacrificando miembros del mirror, y asumes la responsabilidad de la redundancia, comportamiento de montajes, compatibilidad de features y claves.

Si recuerdas tres cosas, recuerda estas: verifica que tienes mirrors, importa primero en solo lectura y controla los montajes como si tu fin de semana dependiera de ello (porque depende). Split es una gran manera de iniciar un plan de migración o DR. El resto del plan—el aburrido ritmo de snapshots, la disciplina de replicación, los scrubs y auditorías—es lo que convierte esa victoria rápida en un sistema en el que puedes confiar.

← Anterior
MariaDB vs Percona Server: cómo evitar la mentira «funciona en staging»
Siguiente →
PL1, PL2 y Tau explicados: Los tres números que lo deciden todo

Deja un comentario