ZFS copies=2/3: Redundancia extra sin un nuevo VDEV — ¿Inteligente o desperdicio?

¿Te fue útil?

ZFS tiene una propiedad llamada copies que parece un código de trucos: configúrala en 2 o 3 y tus datos obtienen redundancia adicional—no necesitas discos nuevos, ni nuevos vdevs, ni reconstruir el pool. Es tentador, especialmente cuando las compras están “viendo el tema” y tu registro de riesgos está “en llamas”.

En la práctica, copies no es ni magia ni inútil. Es una herramienta afilada que puede salvarte una semana de producción—o quemar silenciosamente una pila de capacidad y rendimiento mientras te da una falsa sensación de seguridad. Tratémosla como una función de adulto: entiende exactamente qué duplica, dónde coloca esos bloques, cómo interactúa con mirrors/RAIDZ/special vdevs y cómo operarla sin convertir tu pool en un proyecto científico lento y caro.

Tabla de contenidos

Qué hace realmente copies (y qué no hace)

La propiedad de dataset de ZFS copies controla cuántas copias ZFS almacena por cada bloque escrito en ese dataset: copies=1 (por defecto), copies=2 o copies=3.
Es por dataset, heredable, y se aplica a las escrituras nuevas (y a bloques reescritos), no a los bloques existentes a menos que los reescribas.

Lo que hace

Cuando escribes un bloque, ZFS asigna espacio y escribe ese bloque. Con copies=2, asigna dos ubicaciones de bloque distintas y escribe el mismo bloque dos veces. Con copies=3, tres ubicaciones.
Las lecturas pueden provenir de cualquier copia válida; si una copia falla la validación por checksum, ZFS probará otra.

Lo que no hace

copies no convierte un pool de un solo disco en un pool seguro. No te protege de la pérdida de un vdev. No sobrevive a que “el disco desaparezca” a menos que la redundancia de los vdev(s) todavía pueda proporcionar al menos una copia válida.
Tampoco reemplaza las copias de seguridad. Sigue siendo el mismo pool, el mismo dominio administrativo y el mismo radio de explosión por “ups, lo borré”.

Un modelo mental útil: la redundancia de vdev (mirror/RAIDZ) te protege de fallos de dispositivo. copies te protege de algunos escenarios de pérdida/corrupción a nivel de bloque dentro de la topología sobreviviente, y puede mejorar la recuperabilidad cuando ya estás degradado o tienes sectores defectuosos intermitentes.

Broma #1: Poner copies=3 en todo tu pool es como triple-embolsar las compras—genial hasta que te das cuenta de que no puedes llevar nada más y aún olvidaste los huevos.

Datos rápidos y contexto histórico

Aquí hay algunos puntos concretos de contexto que moldean cómo debe entenderse copies en 2025:

  1. ZFS se construyó alrededor de checksums de extremo a extremo: la corrupción se detecta en tiempo de lectura, no se adivina por el “éxito” del disco. Eso hace que las copias múltiples sean significativas porque ZFS puede elegir una copia conocida como buena.
  2. Las primeras implementaciones de ZFS impulsaban “scrub o lamenta”: los scrubs periódicos convertían errores latentes de sector en eventos detectados y reparados—mucho antes de que el almacenamiento de consumo admitiera problemas con gusto.
  3. copies es anterior a muchas carreras profesionales en ZFS: no es un complemento de moda; ha existido por años como un control de redundancia específico.
  4. RAIDZ no es “solo RAID”: la paridad de ZFS está integrada con checksums y lecturas autocurativas, pero la paridad sigue teniendo dominios de fallo (pérdida de todo un vdev, dispositivos faltantes) que las copias extra no pueden cruzar mágicamente.
  5. Los special vdev cambiaron lo que significa “seguridad de metadatos”: mover metadatos (y opcionalmente bloques pequeños) a un special vdev es una ganancia de rendimiento—y una trampa de fiabilidad si ese vdev está con redundancia insuficiente. Las copias extra pueden ser parte de la historia de mitigación, pero no lo solucionan todo.
  6. Los discos modernos mienten educadamente: una lectura “exitosa” aún puede entregar bits malos. Los checksums lo detectan; la redundancia lo corrige. Las copias extra pueden ofrecer otra oportunidad cuando la reconstrucción por paridad es dolorosa o imposible.
  7. La compresión se volvió mainstream: con compression=lz4, el impuesto de capacidad de copies=2 a veces es menos catastrófico de lo que asumirías—en datasets compresibles.
  8. Los tamaños de registro crecieron, los archivos pequeños se volvieron raros: bases de datos, imágenes de VM y stores de objetos estresan patrones de bloque diferentes; copies interactúa con eso de formas que no son intuitivas a partir de “el doble de datos, el doble del coste”.

Bajo el capó: colocación de bloques, checksums y modos de fallo

Las copias son asignaciones separadas de bloques, no “RAID dentro de RAID”

ZFS no almacena un “bloque primario” más un “mirror interno”. Almacena múltiples punteros de bloque independientes en los metadatos que apuntan a cargas útiles equivalentes.
En la escritura, ZFS elige múltiples destinos de asignación. En la lectura, ZFS puede escoger entre ellos.

La matización importante: esas asignaciones normalmente terminan en la misma clase de vdev (vdevs de datos normales, o special vdevs si el bloque se clasifica para ir allí), y dentro del mismo pool.
Eso significa que las copias extra no son independientes de la forma en que lo es un segundo pool, un segundo chasis o un segundo sitio.

Los checksums son el árbitro

ZFS calcula checksums de cada bloque y almacena checksums en los bloques padres (no junto a los datos que protege). Cuando lees un bloque, ZFS lo valida. Si el checksum falla y existe redundancia, ZFS puede intentar:

  • otra copia (con copies>1),
  • el otro lado de un mirror (en un vdev mirror),
  • reconstrucción por paridad (en RAIDZ),
  • o cualquier combinación de lo anterior.

¿Qué fallos ayuda a mitigar copies?

En el mundo real, los fallos que importan rara vez son “disco muerto, reemplazado limpio”. Usualmente son:

  • Errores latentes de sector que aparecen durante un scrub/resilver.
  • Dispositivos con fallos parciales que devuelven errores de lectura intermitentes.
  • Glitches de firmware/transporte que causan timeouts y errores de I/O bajo carga.
  • Bloques malos en un pool degradado, donde la reconstrucción por paridad o las alternativas del mirror ya están constreñidas.

Las copias extra pueden ayudar cuando el pool tiene redundancia para mantener al menos una copia accesible, pero bloques individuales se vuelven ilegibles en una ubicación.
Si el vdev en sí se pierde (por ejemplo, demasiados discos perdidos en un RAIDZ, o ambos lados de un mirror de dos vías muertos), todas las copias almacenadas en ese vdev son irrelevantes.

¿A dónde van las copias?

La respuesta práctica: van donde el asignador encuentra espacio, sujeto al comportamiento de asignación de bloques y metaslabs de ZFS.
La verdad incómoda: no debes asumir que las copias aterrizan en discos físicos separados de manera que imiten un mirror.
Pueden terminar en el mismo disco dentro de un vdev RAIDZ (aún en offsets distintos), porque RAIDZ distribuye datos a través de todos los discos y la paridad, y la “copia” es otro bloque lógico que será distribuido por el mapeo RAIDZ. Esto sigue siendo útil: es una segunda asignación independiente que puede sobrevivir a corrupción localizada o regiones ilegibles, pero no es un segundo dominio de fallo independiente.

Interacción con mirrors frente a RAIDZ

En un vdev mirror, ya tienes dos (o más) copias físicas a través de discos. Poner copies=2 encima de un mirror de dos vías significa que ahora tienes copias lógicas dobles, cada una de las cuales está en mirror—efectivamente cuatro instancias físicas en dos discos. Eso puede ayudar con ciertos casos límite de corrupción/reparación, pero es mucha amplificación de escritura por una ganancia marginal.

En RAIDZ, copies puede ser más racional para datos pequeños y de alto valor donde la reconstrucción por paridad durante periodos degradados es arriesgada o lenta. Estás pagando asignaciones extras, pero compras más “oportunidades” para que un bloque sea legible sin una recuperación heroica.

Special vdevs: el lugar donde copies se vuelve político

Si usas un special vdev para almacenar metadatos y (opcionalmente) bloques pequeños, la disponibilidad de ese vdev se vuelve existencial para el pool.
Si el special vdev muere y no tienes redundancia allí, puedes perder el pool incluso si tus discos grandes RAIDZ están bien.
Las copias extra pueden reducir la probabilidad de que un bloque de metadatos específico se vuelva ilegible por errores de medio, pero no arreglan la “pérdida del special vdev”.

¿Inteligente o desperdicio? Un marco de decisión

La pregunta correcta no es “¿es bueno copies=2?” La pregunta correcta es: “¿Qué fallo intento sobrevivir y cuánto estoy dispuesto a pagar para sobrevivirlo?”

Cuándo copies=2 es inteligente

  • Datasets pequeños y críticos para el negocio: configuraciones, exportaciones de vaults de secretos, pequeñas bases de datos, claves de licencia, artefactos de CI que deben existir.
  • Árboles con muchos metadatos: millones de archivos pequeños, donde un camino de metadatos ilegible puede ser una pesadilla durante una restauración.
  • Ventanas de riesgo degradado: entornos donde esperas operar degradado (sitios remotos, manos lentas para hardware), y quieres margen extra frente a UREs durante scrub/resilver.
  • Entornos de arranque y datasets del S.O.: donde “no arranca” es costoso operativamente incluso si los datos están intactos en otro lugar.
  • Datasets que usan special vdev: algunos equipos ponen copies=2 en datasets con mucho metadato cuando la capacidad del special vdev lo permite, como doble seguridad contra errores de medio localizados.

Cuándo es desperdicio (o peor)

  • Medios masivos, backups y archivos fríos: si puedes regenerar, las copias extra suelen ser desperdicio; usa replicación a otro pool/sitio en su lugar.
  • Bases de datos con alta tasa de escrituras: la amplificación de escritura duele doble: latencia y resistencia de SSD (o IOPS de HDD). Lo notarás y lo pagarás.
  • Configurar todo el pool con copies=2 “por si acaso”: esto es el equivalente en almacenamiento a poner a toda la compañía en un chat grupal porque una persona se pierde mensajes.
  • Intentar compensar un diseño de topología pobre: si tu diseño es “single RAIDZ1 de discos enormes”, copies no es la solución. La solución es el diseño de vdev, repuestos, monitorización y un plan de resilver realista.

Un rubrica práctica de decisión

Uso tres preguntas en producción:

  1. ¿Cuál es la ruta de recuperación si algunos bloques son ilegibles? Si la respuesta es “restaurar desde backup en horas” o “reconstruir el objeto”, probablemente no necesitas copies.
  2. ¿Cuál es el perfil de escritura? Si es escritura aleatoria de alta rotación, copies puede convertir un sistema estable en un generador de quejas por latencia.
  3. ¿Puedo limitar el radio de explosión? Si puedes aislar datos críticos en un dataset y configurar copies allí, la función se vuelve viable. El uso masivo es como terminar explicando las matemáticas de almacenamiento a finanzas.

Costes de rendimiento y capacidad (las partes que realmente notas)

Capacidad: usualmente casi lineal, a veces no

La expectativa ingenua es correcta la mayoría de las veces: copies=2 duplica aproximadamente el espacio referenciado para ese dataset; copies=3 lo triplica aproximadamente.
La compresión y el tamaño de registro pueden reducir los números absolutos, pero el efecto multiplicador permanece: cada bloque que mantienes, lo mantienes varias veces.

Donde la gente se sorprende no es por el multiplicador; es por la interacción con snapshots y patrones de reescritura. ZFS es copy-on-write. Si tienes snapshots y reescribes bloques, ahora tienes:

  • bloques antiguos retenidos por snapshots (con la configuración de copies que existía cuando se escribieron),
  • bloques nuevos escritos con la configuración actual de copies,
  • y potencialmente múltiples generaciones de datos duplicados si el dataset churnea.

Amplificación de escritura: la etiqueta de precio real

Cada copia extra es asignación extra, I/O extra, trabajo de checksum extra y actualizaciones de metadatos extra. En HDD RAIDZ, el dolor a menudo se muestra como:

  • mayor latencia de escritura y tiempos de txg sync más largos,
  • más fragmentación (más asignaciones por escritura lógica),
  • peor IOPS para escrituras pequeñas.

En pools SSD/NVMe, aún puede afectar, pero el síntoma suele ser resistencia y comportamiento de recolección de basura, además de picos de latencia ocasionales cuando el sistema está bajo presión de memoria.

Comportamiento de lectura: a veces mejor, a veces peor

Las lecturas pueden beneficiarse si una copia es lenta o falla intermitentemente; ZFS puede elegir otra. Pero también puedes empeorar las lecturas creando diseños más fragmentados y más sobrecarga de metadatos con el tiempo.
En condiciones limpias, las lecturas por lo general no se vuelven mágicamente más rápidas con copies.

Broma #2: copies=3 es un poco como llevar tres paraguas para evitar la lluvia—igual te mojas si se cae el techo, y ahora tienes tres paraguas para secar.

Patrones prácticos: donde copies brilla

Patrón 1: dataset “pequeño pero aterrador”

Un dataset pequeño que contiene cosas como exportes de estado de Terraform, activos de bootstrap de clúster o autoridades certificadoras puede ser existencial.
Almacenarlo con copies=2 te compra margen extra frente a errores de medio localizados sin rediseñar todo el pool.

Patrón 2: árboles con muchos metadatos

Millones de archivos pequeños significan que el grafo de metadatos es el sistema. Perder un bloque de directorio o un bloque indirecto no es “un archivo perdido”; puede ser “todo este subtree es ahora una escena del crimen”.
copies=2 puede reducir la probabilidad de que un solo bloque malo se convierta en una expedición de recuperación.

Patrón 3: el sitio edge donde “degradado es normal”

Si operas sitios remotos donde reemplazar un disco toma días, no horas, pasas tiempo real en modo degradado.
Las copias extra pueden mejorar tus probabilidades durante esa ventana—especialmente en RAIDZ—cuando scrubs/resilvers tienen más probabilidad de encontrar errores de lectura en otros sitios.

Patrón 4: protección de special vdev, cuidadosamente acotada

Si usas un special vdev, mantenlo redundante primero. Luego considera copias extra en datasets que coloquen muchos bloques pequeños allí, pero solo si la capacidad es amplia y has medido el comportamiento de txg.
El objetivo no es “hacer seguro al special vdev”. El objetivo es reducir la probabilidad de que unos pocos bloques desagradables arruinen tu semana.

Tres mini-historias del mundo corporativo (dolor incluido)

Mini-historia #1: Un incidente causado por una suposición errónea

Una empresa mediana ejecutaba un único pool para “todo”, construido sobre un gran RAIDZ2. Un líder de equipo leyó sobre copies=2 y decidió habilitarlo en el dataset que contenía imágenes de disco de VM, razonando: “RAIDZ2 más copies=2 equivale básicamente a RAIDZ4, ¿no?” Este cambio pasó porque sonaba como seguridad gratis.

Dos meses después, un parche rutinario al hipervisor provocó una ráfaga de escrituras: snapshots de VM, actualizaciones de paquetes y churn de logs. La latencia se disparó. Los gráficos de almacenamiento parecían un sismógrafo. La primera reacción fue culpar a la red, luego a los hipervisores, luego “tal vez el kernel nuevo”. Nadie sospechó del sistema de archivos porque, en teoría, “era solo redundancia”.

El postmortem fue humillante: el dataset tenía una carga de trabajo de alta escritura y copies=2 duplicó la presión de asignación y el trabajo de sync. El pool no se quedó sin espacio, pero se quedó sin paciencia—los tiempos de txg sync crecieron y las escrituras sincrónicas (y cualquier cosa que fingiera ser síncrona) empezaron a encolarse detrás de la realidad.

La suposición equivocada no fue que ZFS pudiera almacenar múltiples copias. La suposición equivocada fue que la redundancia es gratis si no compras discos. Revirtieron copies para las imágenes de VM, crearon un pequeño dataset “config crítica” con copies=2, y llevaron el resto de la discusión de redundancia a donde pertenecía: diseño de vdev, repuestos y replicación.

Mini-historia #2: Una optimización que salió mal

Otra organización decidió “optimizar” el uso de su special vdev. Tenían NVMe como special vdev para metadatos y bloques pequeños, y alguien quería máximo rendimiento para una caché de build monorepo: muchos archivos pequeños, muchos metadatos, muy caliente.
Ajustaron special_small_blocks a un valor grande para que más datos aterrizaran en el special vdev, y luego añadieron copies=2 “para estar seguros”.

Al principio el rendimiento se veía genial. Las builds fueron más rápidas, las operaciones intensivas en inodos volaron y todos felicitaron al equipo de almacenamiento por ser “innovadores”. Luego el special vdev empezó a llenarse más rápido de lo esperado. Porque ahora alojaba no solo metadatos sino una enorme cantidad de datos pequeños, copies=2 duplicó el consumo allí. El pool en su conjunto tenía espacio; el special vdev no.

Una vez que el special vdev cruzó la frontera de incomodidad, las asignaciones se volvieron más lentas, la fragmentación aumentó y el sistema desarrolló un nuevo pasatiempo: picos de latencia en los peores momentos posibles (días de release, por supuesto). La “optimización” había movido una restricción de capacidad al camino más caliente.

La resolución no fue declarar que los special vdevs son “malos”. Fue tratarlos como una capa separada con su propia planificación de capacidad. Redujeron special_small_blocks, mantuvieron el special vdev redundante y usaron copies=2 solo en un dataset muy pequeño que realmente lo merecía. La caché de build recibió afinamiento de rendimiento por otras vías—porque el almacenamiento no sustituye eliminar caches antiguas.

Mini-historia #3: Una práctica aburrida pero correcta que salvó el día

Un equipo de servicios financieros tenía una costumbre que parecía dolorosamente conservadora: ventanas de scrub mensuales, alertas en errores de checksum, y una política de que cualquier dataset que contuviera “keys, auth, bootstrap” recibía copies=2—pero solo esos datasets, y solo después de chequear capacidad.
Nadie presumía de esto. No era glamuroso. Era papeleo con comandos CLI.

Durante un scrub rutinario, ZFS reportó un pequeño número de errores de checksum en un disco. El disco no superó umbrales SMART; no se cayó. Simplemente empezó a devolver basura ocasionalmente. El scrub detectó bloques malos, ZFS los sanó usando redundancia, y se enviaron alertas. El equipo reemplazó el disco durante horario laboral sin drama.

Una semana después, enfrentaron un segundo problema: un dispositivo separado tenía algunos sectores ilegibles. Esta vez, el dataset afectado era uno de los datasets de “keys y bootstrap”. Como tenía copies=2, ZFS pudo leer desde una copia alterna sin depender exclusivamente de la reconstrucción por paridad bajo estrés.

Nada explotó. No hubo war room. No “restaurar desde cinta”. Solo un par de tickets y un swap de hardware. La práctica aburrida no fue que usaran copies; fue que lo usaron con moderación, vigilaron sus pools como adultos y corrieron scrubs a tiempo incluso cuando no había fuego. Lo aburrido está subestimado en almacenamiento.

Tareas prácticas: comandos, salidas e interpretación

Los comandos abajo asumen herramientas estilo OpenZFS en Linux. Ajusta nombres de pool/dataset. El objetivo no es memorizar flags; es crear memoria muscular para verificar el comportamiento antes y después de tocar copies.

Tarea 1: Inspeccionar ajustes actuales de copies e herencia

cr0x@server:~$ zfs get -r copies tank
NAME              PROPERTY  VALUE    SOURCE
tank              copies    1        default
tank/critical      copies    2        local
tank/critical/ca   copies    2        inherited from tank/critical
tank/vm           copies    1        inherited from tank

Interpretación: quieres ver SOURCE como local solo donde lo pretendías. La herencia accidental es cómo “una pequeña medida de seguridad” se convierte en “¿por qué está lleno el pool?”

Tarea 2: Cambiar copies para un solo dataset

cr0x@server:~$ sudo zfs set copies=2 tank/critical

Interpretación: esto afecta escrituras nuevas (bloques nuevos). Los bloques existentes permanecen como estaban hasta que se reescriban.

Tarea 3: Confirmar si los datos existentes se reescriben (no lo harán)

cr0x@server:~$ zfs get copies tank/critical
NAME           PROPERTY  VALUE  SOURCE
tank/critical  copies    2      local

Interpretación: la propiedad está establecida, pero eso por sí solo no duplica retroactivamente los bloques existentes.

Tarea 4: Forzar una reescritura para que los bloques adopten la nueva política

cr0x@server:~$ sudo rsync -a --inplace --checksum /tank/critical/ /tank/critical/.rewrite-pass/

Interpretación: reescribir puede ser caro y crea nuevos datos. En la práctica harías una reescritura controlada (a veces vía un dataset temporal) y verificarías primero la holgura de espacio. Ten cuidado: “retrofit copies” no es una operación gratis.

Tarea 5: Rastrear espacio referenciado y espacio lógico usado

cr0x@server:~$ zfs list -o name,used,refer,logicalused,logicalrefer,compressratio tank/critical
NAME           USED  REFER  LUSED  LREFER  RATIO
tank/critical  18G   18G    11G    11G     1.60x

Interpretación: logical* muestra el tamaño lógico previo a la compresión; USED/REFER están en disco. Con copies=2, esperas que lo on-disk suba relativo a lo lógico—a menos que la compresión lo compense.

Tarea 6: Vigilar la salud del pool y los contadores de error

cr0x@server:~$ zpool status -v tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 02:11:19 with 0 errors on Sun Dec 22 03:10:05 2025
config:

        NAME                         STATE     READ WRITE CKSUM
        tank                         ONLINE       0     0     0
          raidz2-0                   ONLINE       0     0     0
            sda                      ONLINE       0     0     0
            sdb                      ONLINE       0     0     0
            sdc                      ONLINE       0     0     0
            sdd                      ONLINE       0     0     0
            sde                      ONLINE       0     0     0
            sdf                      ONLINE       0     0     0

errors: No known data errors

Interpretación: los errores CKSUM son los que te dicen “el disco devolvió datos malos”. Ahí es donde la redundancia y las copias extra importan.

Tarea 7: Ejecutar un scrub (y saber a qué te apuntas)

cr0x@server:~$ sudo zpool scrub tank
cr0x@server:~$ zpool status tank
  pool: tank
 state: ONLINE
  scan: scrub in progress since Mon Dec 23 02:00:02 2025
        1.02T scanned at 1.40G/s, 210G issued at 290M/s, 6.20T total
        0B repaired, 3.39% done, 06:40:12 to go

Interpretación: los scrubs son cómo encuentras errores latentes mientras aún tienes redundancia. Si copies es tu red de seguridad, los scrubs son cómo confirmas que la red existe.

Tarea 8: Medir el comportamiento de txg sync (un proxy para “las escrituras están sufriendo”)

cr0x@server:~$ sudo zpool get -H -o name,property,value,source autotrim,ashift,autoreplace tank
tank	autotrim	off	default
tank	ashift	12	local
tank	autoreplace	off	default

Interpretación: aún no es txg, pero estás validando fundamentos. Errores de ashift y ajustes de trim pueden dominar el rendimiento, y la gente culpa a copies cuando el problema real es desalineación o comportamiento del dispositivo.

Tarea 9: Observar I/O en tiempo real por pool y vdev

cr0x@server:~$ zpool iostat -v tank 2
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        5.20T  1.00T    120    980  12.3M  210M
  raidz2-0                  5.20T  1.00T    120    980  12.3M  210M
    sda                         -      -     20    170  2.1M   35.0M
    sdb                         -      -     21    165  2.1M   34.1M
    sdc                         -      -     18    162  2.0M   33.8M
    sdd                         -      -     19    161  2.1M   34.6M
    sde                         -      -     21    160  2.0M   35.2M
    sdf                         -      -     21    162  2.0M   36.1M
--------------------------  -----  -----  -----  -----  -----  -----

Interpretación: después de habilitar copies=2 en un dataset con muchas escrituras, a menudo verás aumentar las operaciones de escritura y el ancho de banda por la misma capacidad a nivel de aplicación. Eso es la amplificación de escritura manifestándose.

Tarea 10: Verificar propiedades a nivel de dataset que interactúan con copies

cr0x@server:~$ zfs get -o name,property,value -s local,inherited,default recordsize,compression,sync,copies,logbias tank/critical
NAME           PROPERTY     VALUE     SOURCE
tank/critical  recordsize   128K      default
tank/critical  compression  lz4       inherited from tank
tank/critical  sync         standard  default
tank/critical  copies       2         local
tank/critical  logbias      latency   default

Interpretación: sync, recordsize y compression a menudo determinan si copies es tolerable. Una carga de trabajo sync con recordsize pequeño y copias extras es la receta para crear una cola de soporte de almacenamiento.

Tarea 11: Comprobar la huella de snapshots antes de cambiar la política

cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -s creation tank/critical | tail -n 5
tank/critical@auto-2025-12-23-0100   220M   18G  Mon Dec 23 01:00 2025
tank/critical@auto-2025-12-23-0200   110M   18G  Mon Dec 23 02:00 2025
tank/critical@auto-2025-12-23-0300   190M   18G  Mon Dec 23 03:00 2025
tank/critical@auto-2025-12-23-0400   140M   18G  Mon Dec 23 04:00 2025
tank/critical@auto-2025-12-23-0500   160M   18G  Mon Dec 23 05:00 2025

Interpretación: los snapshots fijan bloques antiguos. Si cambias a copies=2 y luego churneas datos, puedes terminar pagando por la historia de una copia simple y el futuro de doble copia hasta que los snapshots expiren.

Tarea 12: Validar presencia y salud del special vdev (si se usa)

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

        NAME                               STATE     READ WRITE CKSUM
        tank                               ONLINE       0     0     0
          raidz2-0                         ONLINE       0     0     0
            sda                            ONLINE       0     0     0
            sdb                            ONLINE       0     0     0
            sdc                            ONLINE       0     0     0
            sdd                            ONLINE       0     0     0
            sde                            ONLINE       0     0     0
            sdf                            ONLINE       0     0     0
          special
            mirror-1                       ONLINE       0     0     0
              nvme0n1p1                    ONLINE       0     0     0
              nvme1n1p1                    ONLINE       0     0     0

Interpretación: si tienes un special vdev, trátalo como un ciudadano de primera clase. Las copias extra no salvarán un diseño de special vdev sin redundancia.

Tarea 13: Detectar presión de fragmentación a nivel de pool

cr0x@server:~$ zpool get fragmentation tank
NAME  PROPERTY       VALUE  SOURCE
tank  fragmentation  38%    -

Interpretación: las copias extra aumentan la actividad de asignación. En pools de larga vida, eso puede incrementar la fragmentación y dañar la latencia. Esto no significa “nunca uses copies”, significa “no lo uses a ciegas y para siempre”.

Tarea 14: Confirmar que no cambiaste accidentalmente la configuración a nivel de pool

cr0x@server:~$ zfs get copies tank
NAME  PROPERTY  VALUE  SOURCE
tank  copies    1      default

Interpretación: si esto muestra local en la raíz del pool, probablemente acabas de duplicar el coste de cada dataset a menos que se anule. Ese es el tipo de descubrimiento que quieres a las 10:00, no a las 02:00.

Guía de diagnóstico rápido

Cuando alguien dice “el almacenamiento está lento” y tocaste recientemente copies, no empieces debatiendo filosofía. Empieza a estrechar el cuello de botella en minutos.

Paso 1: ¿El pool está sano o estamos enmascarando un fallo?

  • Revisa zpool status -v por errores de lectura/escritura/checksum, vdevs degradados o un resilver/scrub en curso.
  • Si ves errores de checksum, asume que tienes un problema de dispositivo o de camino primero. Las copias extra pueden estar ayudándote a capear el temporal, pero no son la causa raíz.

Paso 2: ¿Es presión de capacidad o presión en el special vdev?

  • Revisa zfs list y zpool list por espacio libre; a ZFS no le gusta estar muy lleno.
  • Si usas un special vdev, verifica su asignación y que no esté cercano a lleno. Un pool “bien” con un special vdev “medio lleno” aún puede comportarse mal.

Paso 3: ¿Es amplificación de escritura y contención de txg?

  • Observa zpool iostat -v 2 durante la degradación. Si las operaciones de escritura y el ancho de banda suben pero el rendimiento de la app está plano, estás pagando un impuesto por amplificación.
  • Revisa los datasets implicados: zfs get copies,sync,recordsize,compression. Un dataset heavy en sync con copies=2 es un sospechoso principal.

Paso 4: ¿Es un disco malo (o lento) arrastrando el vdev?

  • En mirrors, un lado lento puede crear patrones de latencia extraños dependiendo de la política de lectura y el encolamiento.
  • En RAIDZ, un disco enfermo puede estrangular reconstrucciones y scrubs/resilvers brutalmente.

Paso 5: Confirma que no expandiste accidentalmente el radio de explosión

  • zfs get -r copies tank y busca herencias inesperadas.
  • Verifica si un dataset “temporal” con copies=3 se convirtió en padre de todo porque a alguien le gustan los atajos.

Errores comunes: síntomas y soluciones

Error 1: Poner copies=2 en la raíz del pool

Síntoma: el uso del pool sube inesperadamente rápido; la latencia de escritura aumenta en muchas cargas de trabajo.

Solución: restablécelo en la raíz y configúralo explícitamente solo en los datasets previstos.

cr0x@server:~$ sudo zfs inherit copies tank
cr0x@server:~$ sudo zfs set copies=2 tank/critical

Error 2: Esperar protección retroactiva sin reescribir los datos

Síntoma: configuraste copies=2, pero los scrubs siguen reportando errores irrecuperables en bloques antiguos (o no ves el incremento de capacidad esperado).

Solución: planifica una reescritura/migración del dataset específico si realmente necesitas duplicar los bloques antiguos. Hazlo con espacio libre verificado y conciencia de la política de snapshots.

Error 3: Usar copies para “arreglar” un diseño de vdev arriesgado

Síntoma: aún no toleras la pérdida de un segundo disco en RAIDZ1; un resilver degradado sigue siendo aterrador.

Solución: rediseña con paridad/mirrors apropiados, añade hot spares y usa replicación. copies no sustituye la ingeniería de dominios de fallo.

Error 4: Habilitar copies=2 en datasets de VM o bases de datos con muchas escrituras

Síntoma: picos de latencia repentinos tras la “mejora de seguridad”, mayores tiempos de txg sync, más IO wait y propietarios de aplicaciones enfadados.

Solución: reverte a copies=1 para esos datasets; usa redundancia adecuada y considera SLOG/ajustes de sync solo si entiendes completamente los requisitos de durabilidad.

cr0x@server:~$ sudo zfs set copies=1 tank/vm

Error 5: Llenar el espacio del special vdev por accidente

Síntoma: el pool tiene espacio libre, pero las operaciones de metadatos se ralentizan; la asignación en el special vdev es alta; aparecen picos de latencia durante builds o tormentas de archivos.

Solución: reduce la carga del special vdev (ajusta políticas de colocación de datasets, poda datasets de archivos pequeños), y asegura que la capacidad del special vdev esté dimensionada a largo plazo. Evita duplicarlo con copies a menos que lo hayas presupuestado.

Error 6: Tratar copies como un plan de respaldo

Síntoma: ransomware, borrado accidental o una automatización mala destruye datos en todas las copias instantáneamente.

Solución: usa snapshots, inmutabilidad donde esté disponible y replicación/copias fuera del sitio. Las copias extra siguen dentro del mismo radio de explosión.

Listas de verificación / plan paso a paso

Checklist A: Antes de habilitar copies=2

  1. Delimita el dataset: confirma que puedes aislar los datos críticos en su propio dataset (o un pequeño subtree).
  2. Mide la línea base: captura zpool iostat -v, zpool status y used/refer/logicalused del dataset.
  3. Confirma holgura de espacio: no lo hagas en un pool ya cercano a la plenitud; el estrés del asignador ocultará tus resultados reales.
  4. Revisa la retención de snapshots: entiende cuánto tiempo permanecerán los bloques antiguos de una sola copia si churneas datos.
  5. Confirma salud de vdev: si ya hay errores de checksum, arregla hardware primero; no lo tapes con copias extras.

Checklist B: Habilitar y validar de forma segura

  1. Configura copies=2 solo en el dataset.
  2. Escribe una pequeña carga de prueba y verifica comportamiento mediante deltas de contabilidad de espacio (espera más crecimiento on-disk por escritura lógica).
  3. Monitorea latencia y síntomas de txg durante tu pico normal de carga.
  4. Ejecuta un scrub en tu ciclo de mantenimiento normal y verifica que siga mostrando “0 errors”.

Checklist C: Si necesitas duplicar datos existentes

  1. Planifica espacio: puede que necesites espacio extra temporal para reescribir.
  2. Elige un método de reescritura: copia controlada a un nuevo dataset (preferido), o reescritura in-place (más riesgosa).
  3. Valida con checksums: usa ZFS send/receive donde corresponda para forzar semántica de reescritura preservando snapshots, pero solo si encaja en tu modelo operativo.
  4. Expira snapshots: asegura que los bloques viejos eventualmente desaparezcan, o pagarás por ambos mundos indefinidamente.

Preguntas frecuentes

1) ¿Significa copies=2 que puedo sobrevivir dos fallos de disco?

No. La supervivencia frente a fallos de disco la determina el layout de tus vdevs (nivel de mirror/RAIDZ). copies añade instancias adicionales de bloque dentro de ese layout; no crea un nuevo dominio de fallo independiente.

2) ¿Protege copies contra la corrupción silenciosa de datos?

ZFS usa checksums para detectar corrupción silenciosa. La redundancia la repara. Las copias extra añaden fuentes adicionales válidas para la reparación cuando una ubicación está mala. Mejora probabilidades para ciertos patrones de corrupción, pero no reemplaza la redundancia adecuada y los scrubs.

3) ¿Es útil copies=2 en un pool mirror?

A veces, para datasets pequeños y críticos. Pero los mirrors ya proveen múltiples copias físicas. En cargas activas sobre mirrors, copies puede ser una forma cara de comprar una pequeña mejora de fiabilidad.

4) ¿Es útil copies=2 en RAIDZ?

Más a menudo que en mirrors—cuando se usa de forma acotada. La paridad RAIDZ puede reconstruir, pero los periodos degradados y las UREs son donde copias asignadas independientemente pueden mejorar la recuperabilidad para datos de alto valor.

5) ¿Duplicará automáticamente los datos existentes al poner copies=2?

No. Afecta a escrituras nuevas. Para aplicar a bloques existentes debes reescribir/migrar los datos.

6) ¿Cómo interactúa copies con la compresión?

La compresión ocurre por bloque. ZFS almacena el bloque comprimido múltiples veces. Si los datos se comprimen bien, el coste absoluto de espacio de las copias extra es menor—pero el multiplicador permanece.

7) ¿Será copies=3 alguna vez la respuesta correcta?

Raramente, pero sí: datasets minúsculos que son existenciales y rara vez escritos (por ejemplo, un árbol de bootstrap mínimo), donde el coste de capacidad es despreciable y quieres margen máximo contra bloques ilegibles localizados. Si lo estás considerando para terabytes, para y relee la pregunta.

8) ¿Es copies mejor que la replicación?

Son herramientas diferentes. copies mejora la supervivencia dentro de un pool contra algunos problemas a nivel de bloque. La replicación crea una copia independiente en otro pool/sistema, que ayuda frente a desastres, errores de operador y fallos de sitio. Si solo puedes pagar uno, la replicación suele ganar.

9) ¿Puedo establecer copies solo para metadatos?

No directamente como un toggle “solo metadatos” por dataset. Puedes, sin embargo, dirigir datasets que son ricos en metadatos, y diseñar con special vdevs y opciones de recordsize para influir en lo que se considera “pequeño”. Pero no confundas influencia con garantías.

10) ¿Cuál es el mayor riesgo operativo de habilitar copies?

La expansión accidental del alcance y la regresión de rendimiento. Los fallos que he visto no fueron “ZFS se rompió”; fueron “alguien duplicó las escrituras en el dataset más ocupado y no midió”.

Conclusión

copies=2 y copies=3 no son gimmicks, ni son una mejora universal. Son palancas de redundancia dirigidas que funcionan mejor cuando puedes señalar un dataset pequeño y decir: “Si esto sufre un bloque malo en el momento equivocado, perdemos un día (o la empresa)”.

Usa copies como usas la supresión de incendios: concentrada donde el riesgo es alto, probada periódicamente (scrubs) y nunca confundida con “el edificio no puede incendiarse”. Si quieres mejora real de dominios de fallo, constrúyelo con diseño de vdev y replicación. Si quieres margen extra para unos pocos bloques críticos sin reconstruir el mundo, copies puede ser inteligente—solo no lo pagues en todas partes.

← Anterior
Modales solo con CSS que no te traicionan: :target, fondos y patrones de cierre
Siguiente →
Guerras de ‘cartuchos no originales’: décadas de drama con la tinta

Deja un comentario