Introducción a zdb de ZFS: la herramienta que temes hasta que la necesitas

¿Te fue útil?

Todo va bien hasta que el pool deja de hacerlo. Un día estás ejecutando un zfs send rutinario; al día siguiente alguien te manda por Slack una captura con checksum error como si fuera su horóscopo. Ejecutas zpool status, señala vagamente “corrupted data” y tu confianza recibe un pequeño pero medible golpe en IOPS.

Ahí es cuando aparece zdb. Es el depurador de ZFS: una linterna que también funciona como láser. Puede decirte qué es lo que ZFS realmente cree que está en disco, no lo que las herramientas de alto nivel informan amablemente. También es la herramienta que la gente evita hasta que la necesita—porque es afilada, poco documentada en sitios y no tiene reparos en mostrarte verdades incómodas.

Qué es zdb (y qué no es)

zdb es la herramienta de introspección de ZFS. Si zpool es el panel de flota y zfs es la interfaz de producto, zdb es la consola del ingeniero con la tapa trasera quitada. Lee las estructuras en disco y puede imprimir metadatos internos: punteros de bloque, conjuntos de objetos, datasets, metaslabs, el MOS (Meta Object Set), feature flags, DDT (tablas de deduplicación), contabilidad de spacemap y más. No es “una herramienta de reparación” en el sentido en que la gente espera. Es una herramienta de la verdad. Las reparaciones suelen ser scrubs, resilvers, reemplazo de hardware o restaurar desde copias conocidas buenas.

El temor alrededor de zdb no es irracional. Es un “debugger” en el sentido literal: te muestra la fontanería, incluidas las partes donde la fontanería puede explotar. Y tiene opciones que pueden ser costosas o disruptivas si las ejecutas casualmente en una caja de producción durante el tráfico pico. La mayoría de las veces lo usarás de forma sólo lectura y no destructiva. Preguntarás: “¿Qué está viendo ZFS?” no “¿Puedo pinchar esto hasta que cambie?”

En qué destaca zdb

  • Confirmar la contabilidad del espacio: por qué df difiere de zfs list, por qué el “used” no suma y a dónde fueron los bytes.
  • Explicar el rendimiento: fragmentación de metaslab, comportamiento de recordsize, ratios de compresión, bloques indirectos y por qué un vdev está chillando.
  • Investigar corrupción: enlazar errores reportados con datasets y a veces con objetos/bloques, especialmente combinado con zpool status -v y salida de scrub.
  • Entender features: verificar qué está habilitado, activo o requerido en un pool.
  • Forense: a veces identificar objetos asociados a rutas y, a veces, entender qué cambió entre snapshots.

Qué no es zdb

  • No es una herramienta de monitorización rutinaria: no lo uses en cronjobs que corran cada hora en todos los pools. No normalices ejecutar escaneos de depuración profunda como “observabilidad”.
  • No es un botón mágico de “deshacer”: ZFS es copy-on-write; los snapshots son tu deshacer. Si no los tienes, zdb puede ayudar con la forense pero rara vez con milagros.
  • No sustituye a los scrubs: zpool scrub es cómo validas y reparas checksums. zdb puede señalar y explicar; scrub puede corregir (si existe redundancia).

Una mentalidad útil: zdb es un microscopio, no un desfibrilador. Si intentas “recuperar el pool”, tus herramientas reales son el reemplazo de hardware, las opciones de import/recovery, las copias de seguridad y la calma.

Datos históricos interesantes que realmente importan

Un poco de contexto hace que zdb sea menos místico y más… mecánico. Aquí hay algunos puntos concretos que influyen en cómo deberías pensar sobre él.

  1. ZFS nació en Sun Microsystems como un sistema de archivos + gestor de volúmenes con integridad de datos de extremo a extremo, y zdb forma parte de esa cultura de “confiar, pero verificar” incorporada en las herramientas.
  2. zdb existe porque los metadatos de ZFS son ricos: conjuntos de objetos, dnodes, punteros de bloque, checksums y mapas de espacio son ciudadanos de primera clase. La herramienta es básicamente un impresor de metadatos con opiniones.
  3. Las implementaciones modernas de ZFS divergieron (Illumos, OpenZFS, ports de proveedores). La salida y los flags de zdb pueden diferir entre plataformas y versiones—trata los ejemplos en línea como bosquejos, no como evangelio.
  4. Los feature flags reemplazaron los números de versión en la evolución del formato en disco del pool. zdb es una de las formas más claras de ver qué features están habilitados y activos en un pool.
  5. El copy-on-write cambia las narrativas de “corrupción”: los bloques antiguos no se sobrescriben in situ. Eso es bueno para la consistencia y los snapshots, pero cambia cómo razonas sobre “el archivo que se corrompió ayer”.
  6. Las semánticas de scrub/resilver importan: ZFS puede reparar desde la redundancia si sabe qué copia es correcta (vía checksums). zdb te ayuda a entender dónde y por qué scrub se quejó.
  7. La deduplicación siempre ha sido un cuchillo afilado: la DDT es pesada en metadatos y puede convertirse en cuello de botella de rendimiento. zdb expone estadísticas de DDT que explican “por qué todo está lento” mejor que la mayoría de los dashboards.
  8. La fragmentación de metaslabs es real y se manifiesta como dolor del asignador. zdb te da visibilidad al nivel del asignador cuando “los discos no están llenos pero las escrituras son lentas”.
  9. Históricamente zdb se etiquetó como “para desarrolladores” en el tono, no en la capacidad. En producción, también es para SREs—cuando se usa de forma intencional y moderada.

Y sí: zdb puede sentirse como leer un volcado hex con aspiraciones. Pero está estructurado, es consistente y, una vez que aprendes un puñado de salidas, se vuelve una herramienta práctica—no encantada.

Reglas de seguridad: cómo no convertir la depuración en un incidente

Regla cero: no ejecutes comandos zdb intensivos en un pool que ya esté cojeando a menos que entiendas el coste. Cuando la latencia está en llamas, tu “chequeo rápido” puede ser la gota que colme el vaso.

Guardarraíles operativos

  • Prefiere operaciones de solo lectura y evita opciones que recorran cada bloque a menos que sea fuera de hora o en una réplica.
  • Captura contexto primero: zpool status, zpool get, zfs get, arcstat (si está disponible) y estadísticas I/O a nivel de SO. zdb no es la primera herramienta; es la herramienta de “muéstrame los internos”.
  • Fija tus expectativas de versión: los flags de zdb difieren. Ejecuta zdb -? y confía más en la ayuda local que en la memoria muscular.
  • No “optimices” solo con base en zdb: muestra internos, no la experiencia del usuario. Siempre correlaciona con latencia de la aplicación, profundidades de cola y logs de error.
  • Nunca pruebes flags de recuperación en la única copia: si intentas opciones de import/recovery del pool, practica en un clon o en una réplica respaldada por snapshots primero.

Chiste #1: zdb es como abrir el capó mientras conduces—técnicamente posible, socialmente mal visto.

Una cita de confiabilidad que deberías tener cerca

La esperanza no es una estrategia. — General Gordon R. Sullivan

zdb es lo que usas cuando dejas de esperar y empiezas a probar.

Modelo mental: qué puede ver zdb que zfs/zpool no te mostrará

ZFS está en capas. Cuando escribes zfs list, le preguntas a una biblioteca amigable: “¿Qué datasets conoces?” Cuando escribes zdb, preguntas: “¿Qué está escrito en disco, en el MOS, en los conjuntos de objetos, en los árboles de bloques?” Esa diferencia importa cuando los metadatos son inconsistentes, cuando el pool está parcialmente importado o cuando haces forense.

Los pocos sustantivos internos que necesitas

  • Pool / SPA: el asignador del pool—lógica de nivel superior del pool.
  • MOS (Meta Object Set): el “sistema de archivos” de metadatos del pool. Si el MOS está disgustado, todo está disgustado.
  • Dataset: la noción de ZFS de filesystem/volumen/snapshot, con propiedades y referencias a bloques.
  • Conjunto de objetos: la colección de objetos (dnodes) de un dataset.
  • Dnode: metadatos que describen un objeto (archivo, directorio, ZVOL, etc.).
  • Puntero de bloque (blkptr): una referencia a un bloque, incluyendo tamaño, checksum, birth txg y DVAs físicos (dónde vive).
  • TXG: transaction group. Una secuencia de cambios comprometidos juntos en el tiempo.
  • Metaslab: unidad de asignación de espacio por vdev. Aquí vive la fragmentación y el espacio libre.

La mayoría del uso de zdb en producción cae en dos categorías: (1) “dime por qué el espacio/rendimiento parece incorrecto” y (2) “dime qué bloque/objeto está roto y cuán grave es”. Si mantienes esa separación en la cabeza, elegirás mejores comandos y dejarás de explorar por deporte.

Guion de diagnóstico rápido (comprobar primero/segundo/tercero)

Esta es la versión para on-call. Puedes estar cansado, pero no puedes ser aleatorio.

Primero: establece si tienes un problema de fiabilidad o de rendimiento

  • Señales de fiabilidad: checksum errors, I/O errors, vdevs degraded/faulted, scrub errors, errores de lectura/escritura inesperados.
  • Señales de rendimiento: alta latencia con pool “healthy”, escrituras lentas, lecturas lentas, espacio casi lleno, comportamiento extraño del espacio libre, ARC misses, thrash del asignador.

Segundo: decide si necesitas zdb

  • Si zpool status apunta claramente a un disco y la redundancia puede sanar, haz eso primero (reemplazar, resilver, scrub). zdb es útil pero no obligatorio.
  • Si el síntoma es “el espacio no suma”, “metaslabs están fragmentados”, “qué dataset consume espacio” o “qué features están activas”, zdb suele ser el camino más rápido.
  • Si el pool no se importa, zdb puede decirte si las etiquetas/MOS parecen sanas antes de empezar opciones de recuperación.

Tercero: ejecuta las consultas zdb más baratas que respondan la pregunta

  1. Configuración del pool y feature flags: confirma con qué estás tratando y si un desajuste de import es probable.
  2. Contabilidad del espacio: verifica “dónde fue mi espacio” sin recorrer cada bloque.
  3. Estadísticas de metaslab: comprueba fragmentación y comportamiento de asignación.
  4. Inspección de objetos dirigida: solo cuando ya tienes un dataset/objeto sospechoso.

Si buscas un cuello de botella rápidamente: determina si estás constreñido por (a) la latencia de un único vdev, (b) asignación/fragmentación, (c) dedup/DDT, (d) escrituras pequeñas, (e) comportamiento de escrituras sync/dispositivo de log, o (f) simples errores de hardware. zdb ayuda más con (b) y (c), y con explicar (a) a posteriori.

Tareas prácticas: comandos, significado de la salida y la decisión a tomar

Estas son cosas reales que puedes hacer en producción sin convertir tu caja de almacenamiento en un proyecto científico. Cada tarea incluye un comando, un ejemplo del tipo de salida que verás, qué significa y la decisión operativa que tomas a partir de ello.

Tarea 1: Confirma la vista en disco del pool y pistas de salud de alto nivel

cr0x@server:~$ sudo zdb -C tank
MOS Configuration:
        vdev_tree:
            type: 'root'
            id: 0
            guid: 12345678901234567890
            children[0]:
                type: 'raidz'
                id: 0
                guid: 9876543210987654321
                ashift: 12
                nparity: 2
                children[0]:
                    type: 'disk'
                    path: '/dev/disk/by-id/ata-SAMSUNG_SSD_1'
                    guid: 1111
                children[1]:
                    type: 'disk'
                    path: '/dev/disk/by-id/ata-SAMSUNG_SSD_2'
                    guid: 2222
features_for_read:
        com.delphix:hole_birth
        org.openzfs:embedded_data
        org.openzfs:project_quota

Qué significa: Esto imprime la configuración del MOS: topología de vdev, ashift, GUIDs y las features requeridas para lectura. Es la fuente de verdad “qué dice el disco que es el pool”.

Decisión: Si las rutas de dispositivos del SO cambiaron, los GUIDs aún coinciden—bien. Si features_for_read incluye algo que el host destino no soporta, la importación en otro host fallará. Planea actualizaciones en consecuencia.

Tarea 2: Lista datasets y espacio a nivel de contabilidad interna del pool

cr0x@server:~$ sudo zdb -Lbbbs tank
Dataset tank [ZPL], ID 50, cr_txg 4, 1.23G used, 7.88T available
Dataset tank/home [ZPL], ID 54, cr_txg 120, 310G used, 7.55T available
Dataset tank/vm [ZVOL], ID 61, cr_txg 2201, 2.10T used, 5.75T available

Qué significa: zdb está resumiendo el uso de datasets desde las estructuras internas de ZFS, no desde df. Puede resaltar datasets que olvidaste que existían (especialmente zvols).

Decisión: Si un dataset te sorprende, deja de adivinar. Confirma con zfs list -o space y decide si necesitas cuotas, reservas o limpieza de snapshots.

Tarea 3: Inspeccionar feature flags y si están activas

cr0x@server:~$ sudo zdb -S tank
Storage pool tank:
        version: 5000
        features:
                async_destroy
                        enabled
                        active
                embedded_data
                        enabled
                        active
                spacemap_histogram
                        enabled
                        active

Qué significa: El pool usa feature flags; “enabled” significa que el pool lo soporta, “active” significa que se ha usado y ahora es requerido para compatibilidad total.

Decisión: Si planeas migrar el pool a un appliance/host más antiguo, las features “active” son bloqueos de compatibilidad. No lo descubras a mitad de la migración.

Tarea 4: Validar etiquetas vdev y GUIDs (sanidad de identidad de disco)

cr0x@server:~$ sudo zdb -l /dev/disk/by-id/ata-SAMSUNG_SSD_2
------------------------------------
LABEL 0
------------------------------------
version: 5000
name: 'tank'
state: 0
txg: 902341
pool_guid: 12345678901234567890
vdev_guid: 2222
top_guid: 9876543210987654321

Qué significa: Esto lee la etiqueta ZFS en disco. Es cómo pruebas “este disco pertenece a este pool”, independiente del nombre de Linux.

Decisión: Cuando alguien cambió cables o un controlador renumeró discos, esto evita reemplazar el disco equivocado. Si la etiqueta del disco apunta a otro pool, detente e investiga antes de hacer algo destructivo.

Tarea 5: Revisar fragmentación de metaslab y salud de asignación

cr0x@server:~$ sudo zdb -mm tank
Metaslab statistics for pool 'tank':
  vdev 0: raidz
    metaslabs: 512
    free space: 5.75T
    fragmentation: 62%
    largest free segment: 128M

Qué significa: La fragmentación aquí es fragmentación del asignador, no “fragmentación de archivos”. Alta fragmentación con un largest-free-segment pequeño significa que las asignaciones son caras, especialmente para bloques grandes.

Decisión: Si la fragmentación es alta y las escrituras son lentas, puedes (a) liberar espacio (borrar + zpool trim si son SSDs, según la configuración), (b) añadir vdevs para aumentar capacidad libre y reducir presión del asignador, o (c) planear una reescritura/migración. No intentes “desfragmentar” ZFS; no funciona así.

Tarea 6: Ver mapas de espacio e histogramas (¿es extraña la contabilidad del espacio?)

cr0x@server:~$ sudo zdb -DD tank
DDT-sha256-zap-duplicate: 1248 entries, size 1.10M on disk, 2.40M in core
DDT-sha256-zap-unique:  98122 entries, size 86.0M on disk, 210M in core

Qué significa: Esto es información de la tabla de deduplicación. “In core” indica presión de memoria cuando dedup está habilitado y en uso activo.

Decisión: Si dedup está activado y tu ARC/memoria está justa, espera degradación de rendimiento bajo carga. Si dedup no es crítico, planea migrar lejos de él en lugar de esperar que se porte bien.

Tarea 7: Identificar qué número de objeto corresponde a una ruta de archivo (forense dirigida)

cr0x@server:~$ sudo zdb -vvv tank/home 2>/dev/null | head -n 20
Dataset tank/home [ZPL], ID 54, cr_txg 120, 310G used, 7.55T available
Object  Number  Type
    1    1      ZFS plain file
    2    2      ZFS directory
    3    3      ZFS plain file

Qué significa: Volcar listados completos de objetos es costoso; incluso muestrear muestra el modelo de objetos. En muchos sistemas usarás enfoques más dirigidos (como encontrar un inode primero) en lugar de volcar todo.

Decisión: Si investigas un archivo conocido, no fuerces todo. Usa el mapeo inode/objeto (tarea siguiente) para inspeccionar sólo lo que importa.

Tarea 8: Mapear un inode de Linux a un objeto ZFS e inspeccionar sus bloques

cr0x@server:~$ stat -c 'inode=%i path=%n' /tank/home/app/logs/badfile.log
inode=914227 path=/tank/home/app/logs/badfile.log
cr0x@server:~$ sudo zdb -dddd tank/home 914227 | sed -n '1,25p'
Object  lvl   iblk   dblk  dsize  dnsize  bonus  type
914227   1   128K    16K   512K    512    320   ZFS plain file
        path    /app/logs/badfile.log
        gen     7241
        size    501760
        parent  912000
Indirect blocks:
        0 L1 0:10000:20000 20000L/10000P F=1 B=81234/81234 cksum=on

Qué significa: En muchas plataformas, los números de objeto de ZFS corresponden a los inodos. zdb -dddd imprime el dnode y el árbol de bloques. Los campos tipo DVA muestran dónde viven los bloques; ajustes de checksum y niveles muestran la estructura.

Decisión: Si zpool status -v referencia un archivo y puedes mapearlo a un objeto, puedes determinar si es un objeto pequeño e aislado o parte de un daño de metadatos más amplio. Si está aislado y tienes redundancia, scrub/resilver probablemente lo arregle; si no, restaura ese archivo desde snapshot/backup.

Tarea 9: Comprobar contabilidad de espacio del pool a nivel MOS (por qué “used” no suma)

cr0x@server:~$ sudo zdb -b tank | sed -n '1,40p'
Traversing all blocks...
blocks = 14723918
leaked = 0
compressed = 1.82T, uncompressed = 2.61T, ratio = 1.43x
bp logical = 2.61T, bp physical = 1.82T

Qué significa: Esto es un recorrido completo de bloques. Puede ser costoso. “leaked=0” es bueno: no se detectaron bloques asignados pero inalcanzables por la traversía.

Decisión: Usa esto cuando sospeches leaks o inconsistencias severas de contabilidad y puedas permitirte el escaneo. Si es un pool ocupado, prográmalo fuera de hora o ejecútalo en una réplica.

Tarea 10: Entender la eficacia de la compresión por dataset

cr0x@server:~$ sudo zdb -DDDDD tank/vm | sed -n '1,25p'
Dataset tank/vm [ZVOL], ID 61, cr_txg 2201
bp logical = 2.40T, bp physical = 2.33T, ratio = 1.03x
compression: lz4

Qué significa: La compresión está habilitada pero apenas hace efecto. En imágenes de VM es común según el sistema de archivos del invitado y la entropía de datos.

Decisión: No deshabilites la compresión reflexivamente; lz4 es barato y aún puede ayudar con metadatos y bloques de ceros. Pero deja de esperar que la compresión “salve” espacio en datos ya comprimidos. Planea capacidad con sentido.

Tarea 11: Inspeccionar un puntero de bloque específico (trabajo profundo de corrupción)

cr0x@server:~$ sudo zdb -bbbb tank 0:10000:20000
Block 0:10000:20000
        size=131072L/65536P compression=lz4
        birth=81234 fill=1
        cksum=sha256 2f3a...9c1d
        DVA[0]=<0:10000:20000>

Qué significa: Estás viendo un puntero de bloque por DVA. Esto es “cirugía”, usado normalmente al correlacionar errores de checksum reportados con ubicaciones físicas.

Decisión: Si la inspección del puntero indica un único DVA en un único dispositivo fallando repetidamente, eso respalda el caso para reemplazo de dispositivo o investigación de la ruta del controlador. Si múltiples DVAs están afectadas, podrías estar ante una corrupción más amplia o problemas sistémicos de I/O.

Tarea 12: Imprimir hints del ZIL y del intent log (dolor por escrituras sync)

cr0x@server:~$ sudo zdb -iv tank | sed -n '1,60p'
ZFS_DBGMSG(zil): zil_claim: txg 902340 replayed 0 blocks
ZFS_DBGMSG(zil): zil_itxg_clean: cleaned up log blocks

Qué significa: En algunos sistemas, zdb puede emitir información relacionada con ZIL. Esto ayuda a confirmar si se reprodujo el log y si el pool cree que está limpio.

Decisión: Si una aplicación se queja de escrituras sync recientes faltantes tras un crash, confirma si ocurrió la reproducción del ZIL. Si no, investigas semánticas de import y si el pool se importó read-only o con flags de recuperación.

Tarea 13: Detectar un ashift demasiado pequeño a posteriori (rendimiento y desgaste)

cr0x@server:~$ sudo zdb -C tank | grep -n 'ashift'
18:                ashift: 9

Qué significa: ashift es el tamaño de sector que ZFS usa para alineación. ashift: 9 significa sectores de 512B. En SSDs modernos y muchos HDDs, la elección sensata es 4K (ashift 12).

Decisión: Si ashift es demasiado pequeño, no puedes cambiarlo in situ. Planea migración o reconstrucción. Si el rendimiento es aceptable ahora, igual planéalo—porque la amplificación de desgaste es un incidente lento.

Tarea 14: Comprobar si pagas la “tasa de special vdev” o disfrutas del beneficio

cr0x@server:~$ sudo zdb -C tank | sed -n '1,120p' | grep -n "special" -n
74:            children[1]:
75:                type: 'special'
76:                id: 1
77:                guid: 3333

Qué significa: Un special vdev puede almacenar metadatos (y opcionalmente bloques pequeños). Puede ser una ganancia de rendimiento, o un desastre si es pequeño o no es redundante.

Decisión: Si tienes un special vdev, trátalo como almacenamiento tier-0 con redundancia y monitorización. Si falla y no es redundante, tu pool puede volverse inutilizable. No es un dispositivo “agradable de tener”; es estructural.

Tarea 15: Confirmar cómo ZFS ve el historial de uberblocks del pool (paranoia de import)

cr0x@server:~$ sudo zdb -u tank | head -n 20
Uberblock[0]
        magic = 0000000000bab10c
        version = 5000
        txg = 902341
        guid_sum = 2222222222222222
        timestamp = 2025-12-26 12:41:03
Uberblock[1]
        txg = 902340
        timestamp = 2025-12-26 12:40:52

Qué significa: Los uberblocks son los “puntos de control” usados para importar el pool. Ver múltiples uberblocks recientes con txg monotónico es tranquilizador.

Decisión: Si el uberblock más reciente está lejos de lo esperado o las marcas de tiempo son erróneas, sospechas escrituras incompletas, problemas de cache del controlador o un disco que no persiste realmente datos. Eso cambia tu plan de recuperación: dejas de confiar en “debería estar ahí”.

Chiste #2: La salida de zdb es lo más cercano que tienen los ingenieros de almacenamiento a la poesía—principalmente porque nadie más la puede leer.

Tres microhistorias corporativas del reino del “parecía razonable”

1) El incidente causado por una suposición equivocada: “Si se importa, está bien”

Una empresa mediana ejecutaba una plataforma de VM respaldada por ZFS en un par de servidores de almacenamiento. Tras un evento de corte de energía, un nodo volvió, importó el pool y se vio “lo suficientemente sano”. El admin no vio vdevs degradados. El clúster de hypervisor comenzó a lanzar VMs otra vez. Todos exhalaron.

Dos días después, un puñado de VMs empezó a registrar errores de sistema de archivos. Luego una base de datos en una VM falló con quejas de checksum dentro del invitado. ZFS reportó una lista creciente de checksum errors, pero solo durante ciertos patrones de lectura. El equipo asumió “bit rot”, lanzó un scrub y volvió a las reuniones.

El scrub no avanzó realmente. Caminó y ocasionalmente se atascó. Mientras tanto, picos de latencia afectaban a las VMs en horas laborales. Reemplazaron un disco que parecía “lento”, pero los errores persistieron. Fue entonces cuando alguien finalmente ejecutó zdb -u y zdb -l contra los dispositivos sospechosos.

Las etiquetas mostraron algo feo: una ruta de controlador presentaba intermitentemente datos obsoletos. El pool se importó porque los metadatos eran lo bastante consistentes, pero los uberblocks “más recientes” no eran tan recientes como el equipo asumía. zdb -u reveló una brecha sospechosa en la progresión de txg tras el evento de energía. Combinado con logs del kernel, apuntó a un problema de cache/escritura—el almacenamiento reconocía escrituras que nunca llegaron a medio estable.

La solución no fue una oración del sistema de archivos. Fue hardware y política: reemplazar el controlador, validar ajustes de cache y ejecutar scrubs con aislamiento de I/O. Restauraron un conjunto pequeño de discos de VM afectados desde snapshots replicados al otro nodo. La lección: el éxito de import no es éxito de integridad. zdb no “arregló” nada; probó que la línea de tiempo mentía.

2) La optimización que salió mal: dedup como milagro para ahorrar costos

Un gran equipo interno recibió la orden: “Reducir la huella de almacenamiento.” Notaron muchas plantillas de VM y capas de contenedores duplicadas. Alguien propuso activar dedup de ZFS en el pool principal. Una prueba corta se vio prometedora: el uso de espacio bajó en un dataset pequeño, y todos se chocaron las manos en silencio.

Habilitaron dedup más ampliamente. Al principio parecía bien. Luego llegó el lunes. La latencia subió, y luego volvió a subir. Los nodos de almacenamiento empezaron a hacer swap bajo carga. Las escrituras se ralentizaron. Las lecturas comenzaron a encolar. No fue catastrófico; fue peor: un tipo de caída a cámara lenta donde todos siguen añadiendo dashboards hasta que los dashboards también empiezan a fallar.

Ejecutaron zdb -DD y vieron los tamaños de la DDT y las estimaciones en memoria. No fue sutil. El pool pagaba un impuesto de metadatos que no cabía en RAM, así que cada I/O se convirtió en una búsqueda entre metadatos fríos. Las tasas de acierto del ARC cayeron; la CPU estaba ocupada en trabajo legítimo que nadie quería.

Desactivar dedup no elimina los bloques ya deduplicados. Ahora estaban comprometidos con la elección a nivel en disco. El plan de salida se convirtió en un plan de migración: replicar datasets a un nuevo pool con dedup desactivado, validar, cortar y eventualmente destruir el pool antiguo. Tomó tiempo, gestión de cambios y paciencia.

La optimización que salió mal no fue “dedup es malo”. El verdadero modo de fallo fue activarlo sin modelar memoria, carga de trabajo y costo operacional de salida. zdb hizo visible el costo. No hizo la decisión reversible.

3) La práctica aburrida pero correcta que salvó el día: etiquetas, spares y ensayos de import

Un equipo empresarial gestionaba varios pools ZFS en múltiples racks. Nada sofisticado. Hicieron tres cosas consistentemente: (1) cada disco tenía rutas by-id estables registradas en inventario, (2) cada pool tenía hot spares y procedimientos claros de reemplazo, y (3) trimestralmente, ensayaban import y recuperación del pool en un host de staging usando snapshots replicados.

Una noche un nodo de almacenamiento falló por completo. El equipo de hardware reemplazó un backplane, y de repente el SO enumeró los discos de forma diferente. El admin junior hizo lo correcto y aburrido: antes de reemplazar nada, ejecutó zdb -C en el pool y zdb -l en algunos dispositivos para verificar pertenencia y GUIDs.

Descubrieron que dos discos estaban presentes pero detrás de una ruta diferente, y un disco “faltante” estaba allí—solo renombrado. Sin esa comprobación, podrían haber puesto offline el disco equivocado y empujado al pool a un estado degradado durante la importación.

El pool se importó limpio. Se programó un scrub. El rendimiento se mantuvo estable. Nadie escribió un postmortem porque nada se rompió. La verdadera victoria fue el procedimiento: inventario + verificación de etiquetas + ensayo. zdb fue el actor secundario silencioso que hizo posible “hacerlo bien y con calma”.

Errores comunes (síntoma → causa raíz → solución)

1) Síntoma: “zfs list dice una cosa, df otra”

Causa raíz: Estás mezclando puntos de vista: espacio lógico del dataset vs espacio físico del pool, snapshots, refreservation y el hecho de que df muestra la vista del sistema de archivos después de propiedades como refquota.

Solución: Usa zfs list -o space como primer paso, luego confirma con zdb -Lbbbs pool para la vista interna. Si un dataset tiene refreservation o uso grande por snapshots, ajusta cuotas/reservas e implementa políticas de retención de snapshots.

2) Síntoma: Pool está “ONLINE” pero el scrub encuentra checksum errors repetidamente

Causa raíz: Un dispositivo/ruta de controlador devuelve datos erróneos intermitentemente, o tienes sectores latentes que la redundancia a veces corrige pero no siempre.

Solución: Reemplaza el disco o el controlador sospechoso, no sólo “haz scrub más fuerte”. Usa zdb -l para confirmar identidad del disco y correlaciona ubicaciones de error. Ejecuta scrub tras la remediación de hardware.

3) Síntoma: Las escrituras se ralentizan dramáticamente cuando el pool está ~80–90% lleno

Causa raíz: Presión del asignador y fragmentación de metaslab; existe espacio libre pero no en segmentos útiles.

Solución: Revisa estadísticas de metaslab con zdb -mm. Libera espacio (borra datos y snapshots) para bajar utilización, o añade capacidad de vdev. A largo plazo: no operes pools tan llenos si te importa la latencia.

4) Síntoma: Tras habilitar dedup, todo va muy lento

Causa raíz: Los metadatos de la DDT no caben en RAM, provocando misses constantes de caché e I/O aleatorio intenso.

Solución: Usa zdb -DD para cuantificar. Si ya está activo, planifica migrar fuera de dedup. Si no, no habilites dedup sin un modelo de memoria y un plan de salida.

5) Síntoma: Import del pool falla en otro host “aunque sean los mismos discos”

Causa raíz: Los feature flags requeridos para lectura no son soportados por la versión de ZFS del host destino.

Solución: Usa zdb -C pool y zdb -S pool para ver features requeridas/activas. Actualiza el host destino o elige una estrategia de compatibilidad antes de mover discos.

6) Síntoma: Escritas aleatorias pequeñas son terribles, cargas con mucho sync se atascan

Causa raíz: SLOG ausente/mal configurado, o problemas de latencia del dispositivo; también mismatch de recordsize/volblocksize para la carga.

Solución: Valida el comportamiento del intent log y la latencia de dispositivos. zdb puede dar pistas, pero normalmente decidirás basándote en la carga. Para zvols, fija volblocksize correctamente al crear; para filesystems, ajusta recordsize y patrones de I/O de la app.

7) Síntoma: Reemplazar un disco no reduce errores; se sacó el “disco equivocado”

Causa raíz: Dependencia de nombres de dispositivo del SO como /dev/sdX en lugar de IDs estables y etiquetas en disco.

Solución: Identifica siempre discos vía /dev/disk/by-id y verifica con zdb -l antes de poner offline/reemplazar.

Listas de verificación / plan paso a paso

Checklist A: Antes de ejecutar zdb en producción

  1. Escribe la pregunta que intentas responder (¿espacio? ¿rendimiento? ¿corrupción? ¿import?).
  2. Captura la línea base: zpool status, zpool get all pool, zfs get all dataset (o al menos propiedades relevantes).
  3. Revisa la carga: si la latencia ya está alta, evita comandos que recorran bloques.
  4. Confirma plataforma/versión: ejecuta zdb -? y verifica que los flags existen como esperas.
  5. Prefiere comandos dirigidos (-C, -S, -mm, -l) antes de recorridos completos.
  6. Registra salidas en un ticket o documento de incidente. La salida de zdb es evidencia.

Checklist B: Misterio de espacio (“el pool está lleno pero no veo los datos”)

  1. Revisa uso de snapshots y clones a nivel de dataset (alto nivel primero).
  2. Usa zdb -Lbbbs pool para confirmar uso interno de datasets y encontrar sorpresas (zvols, datasets ocultos).
  3. Si sospechas leaks/inconsistencia de contabilidad y puedes permitirlo, ejecuta zdb -b pool fuera de hora.
  4. Punto de decisión: si el espacio lo retienen snapshots, arregla retención y automatiza el recorte; si es presión por fragmentación, añade capacidad o migra.

Checklist C: Investigación de corrupción (“checksum errors”)

  1. Desde zpool status -v, identifica archivos/datasets afectados si aparecen listados.
  2. Confirma el estado de redundancia: ¿degraded? ¿faulted? ¿cuántos errores?
  3. Verifica la identidad del disco sospechoso con zdb -l antes de reemplazar nada.
  4. Si puedes mapear a un archivo, mapea inode a objeto e inspecciona con zdb -dddd dataset object.
  5. Punto de decisión: si hay redundancia, realiza scrub tras la remediación de hardware; si no, restaura objetos afectados desde snapshot/backup.
  6. Después: programa un scrub y revisa logs de cabling/controlador. ZFS a menudo te dice que algo está mal; no sustituye la disciplina de root-cause.

Checklist D: Regresión de rendimiento (“iba rápido la semana pasada”)

  1. Confirma llenado del pool y fragmentación vía zdb -mm y estadísticas normales del pool.
  2. Revisa si dedup está en juego y cómo luce la DDT (zdb -DD).
  3. Confirma ashift y diseño de vdev vía zdb -C.
  4. Punto de decisión: si la fragmentación es alta, reduce utilización/añade vdev; si dedup presiona la memoria, migra; si el layout de vdev es incorrecto, planea reconstrucción.

Preguntas frecuentes

¿Es seguro ejecutar zdb en un pool de producción en vivo?

Mayormente, si te limitas a resúmenes de configuración/etiquetas/metaslab. Evita recorridos completos (como block walking) durante carga pico. Trátalo como un diagnóstico que consume I/O y CPU.

¿zdb reparará la corrupción?

No. Diagnostica. Las reparaciones vienen de la redundancia (scrub/resilver) o de restaurar desde snapshots/backups. zdb te ayuda a entender el alcance y la causa probable.

¿Por qué la salida de zdb difiere entre servidores?

Las implementaciones y versiones de ZFS difieren. Los flags y formatos de salida pueden cambiar. Siempre ejecuta zdb -? en el host que usas y no asumas que un fragmento de blog coincide con tu plataforma.

¿Cuándo debo usar zdb en lugar de zpool/zfs?

Cuando necesitas la verdad interna: feature flags, etiquetas, fragmentación de metaslab, estadísticas de DDT, historial de uberblock o detalles de objetos/bloques que las herramientas de alto nivel abstraen.

¿zdb puede ayudar a encontrar qué retiene espacio después de borrar archivos?

Indirectamente. zdb puede validar uso de datasets y a veces revelar que snapshots/clones retienen bloques. La “solución” suele ser la política de retención de snapshots, no más zdb.

¿zdb ayuda a recuperar archivos borrados?

A veces para forense, pero operativamente la respuesta correcta son los snapshots. Si no tienes snapshots, zdb puede identificar objetos, pero la recuperación es poco fiable y consume tiempo.

¿Cuál es el comando zdb más útil para memorizar?

zdb -C pool. Te dice qué es el pool: diseño de vdev, ashift y requisitos de features. Evita errores tontos durante reemplazos y migraciones.

¿Cómo sé si dedup me está perjudicando?

Si dedup está activo y las necesidades de DDT en memoria exceden la memoria disponible, verás misses de caché y amplificación de I/O. zdb -DD pool da pistas de dimensionamiento de DDT que correlacionan fuertemente con el dolor.

¿zdb puede explicar por qué mi pool está lento aunque no esté lleno?

Sí, mediante fragmentación de metaslab y estadísticas de asignación (zdb -mm). “No está lleno” no es lo mismo que “fácil de asignar”. La fragmentación puede hacer que un pool medio vacío se comporte como un parking lleno.

Conclusión: qué hacer la próxima vez antes de entrar en pánico

zdb no da miedo porque sea peligroso. Da miedo porque es honesto. Te mostrará sin rodeos que tu pool es compatible con menos hosts de los que pensabas, que tu ashift fue una mala decisión de vida, o que tu plan de “ahorro de espacio” es en realidad una fábrica de metadatos.

Pasos prácticos siguientes que dan resultado:

  • Practica en un pool no crítico: ejecuta zdb -C, zdb -S, zdb -mm y zdb -l hasta que las salidas te resulten familiares.
  • Estandariza la identificación de discos usando rutas by-id y verificaciones de etiquetas antes de reemplazos. Hazlo política, no heroísmo.
  • Escribe tu secuencia de “diagnóstico rápido” y ponla en el runbook de on-call. zdb es más eficaz cuando responde una pregunta específica.
  • Presupuesta tiempo para las decisiones irreversibles: dedup, special vdevs, ashift y diseño de vdev son arquitectura. zdb te mostrará las consecuencias; no puede deshacerlas.

Cuando el pool se comporta mal, no necesitas más misterio. Necesitas evidencia. zdb es evidencia—entregada en un dialecto que recompensa la paciencia y castiga la improvisación.

← Anterior
Conectores derretidos: cuando un “estándar” se convierte en escándalo
Siguiente →
Fundamentos de zpool iostat: convertir números en un cuello de botella

Deja un comentario