Algunos incidentes no empiezan por una falla de disco o un kernel panic. Empiezan con un dataset llamado data2, un punto de montaje que “parecía correcto” y un administrador bienintencionado que asumió que estaba en el lugar correcto.
ZFS es inusualmente indulgente—hasta que no lo es. Los nombres son el pegamento en ZFS: conectan mountpoints, propiedades, snapshots, cuotas, delegación, replicación, monitorización y la memoria humana. Si nombras datasets como un cajón de trastos, depurarás como si estuvieras con los ojos vendados. Si los nombras como si gestionaras producción, ahorrarás horas cada mes y, ocasionalmente, evitarás una tarde muy cara.
Qué hacen realmente los nombres en ZFS
Un nombre de dataset ZFS parece una ruta, y no es casualidad. Es un espacio de nombres jerárquico: pool/app/prod/postgres. Las barras tienen semántica. Ese nombre también es una identidad usada por herramientas (zfs, zpool, trabajos de replicación, software de backups, monitorización, enrutamiento de alertas, delegación de acceso). No solo “etiquetas” un dataset; creas un identificador que el resto del sistema agarrará para siempre.
En la mayoría de las pilas de almacenamiento, nombrar es cosmético. En ZFS, el nombre influye en:
- Herencia de propiedades: compression, recordsize, atime, sync, xattr, acltype, cuotas/reservas. La jerarquía padre/hijo es cómo modelas comportamientos por defecto y excepciones.
- Comportamiento de montaje:
mountpoint,canmount,sharenfs/sharesmby el montaje implícito al arrancar. - Identidad de snapshot: los snapshots se dirigen como
dataset@snap. Tus decisiones de nombres determinan si la automatización puede encontrar y razonar sobre el conjunto correcto de snapshots. - Ámbito de replicación:
zfs send pool/app/prod@x | zfs receive backup/app/prodes una declaración sobre jerarquía y selección. El nombre afecta qué puedes replicar, excluir o redirigir de forma segura. - Delegación y multi-tenancy:
zfs allowfunciona sobre nombres de dataset. Los límites claros importan cuando delegas derechos de snapshot o montaje. - Velocidad de respuesta ante incidentes: bajo presión, los humanos reconocen patrones. Un nombre claro reduce “creo que este es el dataset” a “esto es obviamente el dataset”.
Los nombres son baratos. Renombrar no lo es. Claro, zfs rename existe y muchas veces es seguro. Pero el radio de impacto incluye mounts, exports, la goma tipo fstab, monitorización, objetivos de backup, bookmarks de replicación y lo que tu organización haya pegado a base de cinta adhesiva al nombre antiguo. El momento más barato para ser coherente es antes de que tu primer horario de snapshots de producción salga.
Regla opinada: nombra datasets para las operaciones, no para tu organigrama interno. Equipos y productos cambian. Los puntos de montaje y los contratos de replicación tienden a persistir como chicle en la suela.
Una convención de nombres aburrida que funciona
Aquí hay una convención que escala desde “una caja en un armario” hasta “replicación multisede con retención por cumplimiento”, sin convertirse en un hobby de taxonomía.
Formato
Usa esta forma:
<pool>/<scope>/<env>/<service>/<role>
Ejemplos:
tank/app/prod/postgres/datatank/app/prod/postgres/waltank/app/stage/api/logstank/shared/prod/hometank/infra/prod/monitoring/tsdb
Qué hace cada segmento:
- pool: un dominio de fallo físico. No intentes codificar “rápido/lento” en los nombres de datasets; usa pools o clases de vdev intencionalmente.
- scope: un límite operativo aproximado (comunes:
app,infra,shared,backup,scratch). Así previenes la enfermedad de “todo está bajodata”. - env:
prod,stage,dev, quizádr. Sí, incluso en sistemas de un solo host. Te obliga a poner los valores por defecto en el sitio correcto. - service: aquello por lo que te llaman. Manténlo estable.
- role: solo cuando sea necesario, para separar perfiles de propiedades (p. ej., WAL vs data, logs vs uploads, cache vs durable).
Reglas de caracteres (manténlo aburrido a propósito)
- ASCII en minúsculas. Números permitidos.
- Usa guiones entre palabras, no guiones bajos. Elige uno y apégate; yo elijo guiones porque es consistente con muchos esquemas de nombres operativos.
- Sin espacios. Sin puntuación creativa. Evita los puntos a menos que tengas una razón fuerte.
- Mantén los segmentos cortos pero significativos:
monitoringvence amoncuando lo revises dentro de seis meses.
¿Por qué no embeberlo todo? Porque acabarás codificando: unidad de negocio, código de proyecto, centro de coste, ID de ticket y las fases de la luna. Los nombres ZFS son identificadores operativos, no un esquema de base de datos. Pon metadatos en etiquetas en tu CMDB, en IaC, o al menos en propiedades de usuario como zfs set org:*—más sobre eso más adelante.
Una cita que debería vivir sobre tu terminal (idea parafraseada): Gene Kranz, director de vuelo: “Sé duro y competente.” Las convenciones de nombres son la parte de competencia.
Broma #1: Nombrar datasets es como usar hilo dental: todo el mundo está de acuerdo en que es bueno, y casi todos empiezan después del primer incidente doloroso.
Diseño de la jerarquía: crea límites donde cambian las propiedades
Una jerarquía de datasets no son “carpetas en ZFS.” Es un árbol de herencia con mounts asociados. La mejor jerarquía es aquella donde cada nodo representa un límite de políticas significativo: compresión, recordsize, cuota, reserva, comportamiento sync, horario de snapshots, retención, cifrado y objetivos de replicación.
Principio de diseño: un dataset por perfil de propiedades
Si dos rutas necesitan ajustes distintos, necesitan datasets distintos. Eso no significa miles de datasets; significa que dibujas límites donde los valores por defecto dejan de ser seguros.
Límites comunes que merecen datasets separados:
- Datos de base de datos vs WAL/journal: patrones de escritura distintos, a menudo distinto
recordsize, a veceslogbias. - Imágenes de VM: bloques grandes, snapshots frecuentes, posible
volblocksizepara zvols, cuidado con lacompression. - Logs: en muchas empresas no merece la pena snapshotearlos; usa un dataset separado para excluirlos de replicación y retención.
- Subidas de usuarios: límites de cuota, a menudo necesitan snapshots, la compresión suele ayudar.
- Caches: configura
com.sun:auto-snapshot=falseo banderas de propiedad de usuario similares para tu tooling.
Principio de diseño: los datasets padre son valores por defecto de política
Crea un dataset padre para cada paquete de políticas estable, pon propiedades allí, y deja que los hijos hereden. Por ejemplo:
tank/app/prod: compresión activada, atime desactivado, snapdir oculto, opciones de normalización.tank/app/prod/postgres: etiqueta de horario de snapshots, etiqueta de grupo de replicación.tank/app/prod/postgres/datay.../wal: recordsize/logbias ajustados por rol.
Por qué esto importa: durante un incidente quieres responder “¿qué política aplica aquí?” con un comando. Un árbol sensato hace la respuesta obvia. Un árbol desordenado lo convierte en arqueología.
Límites de cifrado: nómbralos para que los humanos no desencripten lo equivocado
Si usas cifrado nativo de ZFS, las raíces de cifrado separadas (datasets donde encryption=on y las claves residen) deberían ser obvias en el nombre. El ciclo de vida del material de claves es un límite operativo tan real como una VLAN.
Patrones que funcionan:
tank/secure/prod/hr/...dondetank/secure/prodes una raíz de cifrado.- O un sufijo:
.../encsolo si eres consistente y mapea a límites reales de claves.
Patrones que fallan:
- Datasets cifrados aleatoriamente esparcidos bajo padres no cifrados con nombres que no indican la ubicación o el límite de la clave.
El nombrado de datasets es cómo evitas que un momento de “simplemente móntalo” se convierta en “¿por qué aparece el prompt de clave en el host equivocado a las 2am?”.
Mountpoints, canmount y la trampa de “dónde están mis archivos”
Los mountpoints de ZFS son potentes porque son automáticos. También son peligrosos porque son automáticos.
Alinea los nombres de datasets con los mountpoints (la mayoría de las veces)
La configuración más limpia es:
- El nombre del dataset corresponde a la ruta del mountpoint con la misma jerarquía.
- Ejemplo:
tank/app/prod/postgres/datase monta en/srv/app/prod/postgres/data.
No es obligatorio, pero es amable a nivel operativo. Cuando el mountpoint coincide con el árbol de datasets, puedes inferir uno a partir del otro. Bajo estrés, eso vale oro.
Usa canmount=off para datasets “organizacionales”
Muchos datasets existen para llevar propiedades heredadas y no para montarse. Esos deberían ser no montables por defecto:
tank/app,tank/app/prod,tank/app/prod/postgresa menudo quierencanmount=offcon unmountpointque sea heredado o establecido pero no realmente montado.
Si no haces esto, acabarás montando un dataset padre sobre el árbol de mountpoints de un hijo, ocultando a los hijos y confundiendo a todos. Así es como “pierdes” datos que siguen en disco—simplemente no visibles en la ruta que crees.
Cuándo el nombre rompe el montaje
La mayoría de los errores de nombrado aparecen como errores de montaje:
- Datasets creados bajo el padre equivocado (política equivocada aplicada, mountpoint heredado incorrecto).
- Mountpoints configurados manualmente de forma improvisada que ya no coinciden con la jerarquía.
- Clones creados y montados en algún lugar “temporal” que se vuelve permanente.
Broma #2: ZFS montará felizmente tu dataset sobre el directorio con tus notas sobre cómo no hacer eso.
Snapshots y replicación: el nombre como API de automatización
En la práctica, el nombre de dataset se convierte en una API para tu automatización. Los trabajos de backup seleccionan datasets por prefijo. Las reglas de replicación mapean prefijos origen a prefijos destino. Las políticas de retención están ligadas a grupos de datasets. Si nombras inconsistentemente, tu automatización tendrá que volverse “inteligente.” La automatización inteligente es donde se esconden los bugs.
Naming de snapshots: mantenlos predecibles, ordenables y fáciles de grep
Los nombres de snapshot son por-dataset. La convención que mantiene tranquilos a humanos y scripts:
- Prefija por sistema:
auto-,replica-,pre-upgrade- - Incluye un timestamp tipo ISO:
YYYYMMDD-HHMM - Opcionalmente incluye clase de retención:
hourly,daily,weekly
Ejemplos de nombres de snapshot:
auto-hourly-20251226-0300auto-daily-20251226-0000pre-upgrade-20251226-1452
Qué evitar:
- Espacios y timestamps locales (
Dec-26,26-12-2025) - Nombres solo humanos (
before-change) sin timestamp - Semántica sobrecargada en los nombres de snapshot (“esto también es el ticket ID y el nombre del ingeniero”)
Mapeo de replicación: los nombres deben permitir transformaciones reversibles
Las mejores configuraciones de replicación son aquellas donde el nombre destino es una transformación determinista del nombre origen. Ejemplo:
- Origen:
tank/app/prod/postgres - Destino:
backup/app/prod/postgres
Esto te permite razonar sobre failover, probar restores y auditar con reglas sencillas. También evita el detectiveo de “¿de dónde vino este dataset?”.
Usa propiedades de usuario para la automatización, no hacks en el nombre
ZFS soporta propiedades de usuario (a menudo escritas como org:* o com.example:*). Heredan como las propiedades nativas. Son ideales para marcar datasets para horarios de snapshot, grupos de replicación y niveles de monitorización—sin codificarlo en el nombre.
Ejemplos:
org:backup=goldorg:owner=paymentsorg:rpo=15morg:pii=true
Los nombres te dicen “qué es”. Las propiedades te dicen “cómo lo tratamos”. No confundas ambos.
Hechos interesantes y contexto histórico (porque el nombrado no se volvió raro por accidente)
- Los nombres de datasets ZFS preceden al “tagging” moderno en la nube. En los primeros shops ZFS se confiaba en el nombrado porque las propiedades de usuario y las prácticas de metadatos externas no eran comunes en los flujos de trabajo ops.
- El espacio de nombres de datasets fue diseñado para comportarse como un árbol de sistema de ficheros, pero el modelo de herencia lo acerca más a un árbol de políticas que a un listado de directorios.
- Solaris ZFS popularizó la idea de “límites administrativos” vía datasets, mucho antes de que la mayoría de admins Linux tuvieran primitivas similares en sus toolkits por defecto.
- Los snapshots son de primera clase y baratos, lo que hace que los nombres se conviertan en el índice del historial. Si no encuentras el snapshot correcto rápido, “barato” se vuelve “caro”.
- ZFS send/receive empujó el nombrado hacia el diseño de backups, porque los objetivos de replicación se identifican por nombres de dataset en lugar de IDs opacos.
- La herencia de propiedades es la razón por la cual ZFS evita archivos de configuración global para muchos comportamientos. Eso desplaza la complejidad al árbol de datasets—tu nombrado es cómo la gestionas.
- Muchas herramientas de snapshot de terceros adoptaron convenciones de nombres como “auto-”, convirtiendo los nombres de snapshot en una superficie API de facto para retención y scripts de replicación.
- El auge de plataformas de contenedores hizo común el “dataset por inquilino”, lo que volvió la delegación (
zfs allow) y el nombrado limpio más valioso que nunca. - El cifrado nativo aumentó el coste de una jerarquía descuidada, porque los límites de claves son límites de dataset, y los límites de dataset se expresan en nombres.
Tres mini-historias corporativas desde las trincheras de nombres
1) Incidente causado por una suposición errónea: “Ese dataset es obviamente staging”
La empresa tenía un único pool llamado tank y un puñado de datasets: tank/db, tank/db2, tank/web, tank/tmp. Un administrador anterior se fue, como suelen hacer. Los nuevos ingenieros heredaron el sistema más un dashboard de monitorización que solo mostraba la capacidad del pool.
Una implementación salió mal y el on-call decidió revertir usando snapshots. Vieron tank/db y asumieron que era la base de datos de staging porque “era más pequeña”. Restauraron un snapshot a un clone, lo montaron temporalmente y copiaron archivos de vuelta. “Funcionó”, en el sentido de que la base de datos arrancó.
Entonces soporte comenzó a recibir tickets. Los datos parecían más antiguos de lo debido. La reversión se aplicó en producción, no en staging. La causa raíz no fue que ZFS fallara; hizo exactamente lo que se le indicó. La falla fue de identidad: el nombre del dataset no codificaba el entorno, y no había una etiqueta de propiedad fiable que les dijera qué estaban tocando.
La solución no fue heroica. Crearon una nueva jerarquía: tank/app/prod/postgres y tank/app/stage/postgres, migraron datos con downtime planificado y añadieron propiedades org:env y org:service. Después de eso, un humano podía mirar zfs list y no apostar con la realidad.
2) Optimización que salió mal: “Ahorramos tiempo de montaje aplanando todo”
Otra organización ejecutaba un clúster de virtualización y decidió que su árbol de datasets era “demasiado profundo”. Alguien argumentó que menos datasets significarían menos overhead y arranque más rápido. Colapsaron un árbol cuidado en un diseño plano: tank/vm-001, tank/vm-002, etc. También movieron logs, imágenes y espacio scratch dentro de cada dataset VM como directorios.
Al principio parecía ordenado. Luego las cuotas se convirtieron en un desastre. Algunas VMs necesitaban límites estrictos, otras reservas, y un par necesitaban distinto recordsize para cargas de base de datos. Intentaron parchearlo con disciplina por directorio, que ZFS no aplica. Lo único que lo hacía cumplir era “recordar comportarse”, lo cual no es un sistema de control.
El remate llegó durante el ajuste de replicación. Querían replicar solo los datos “durables”, no scratch. Con el modelo plano, scratch y durable vivían en el mismo dataset, así que o replicaban todo o nada. Terminaron replicando todo para cumplir RPO, lo que incrementó el uso de ancho de banda y alargó las ventanas de replicación. Luego la ventana chocó con la poda nocturna de retención de snapshots, y los sends empezaron a fallar intermitentemente.
No regresaron al árbol original; fueron a uno mejor. Las VMs se convirtieron en hijos bajo un scope de entorno y clúster, y scratch/logs obtuvieron sus propios datasets con banderas para excluir snapshots. La “optimización” no fue una ganancia de rendimiento; fue una falla de política disfrazada de simplificación.
3) Aburrido pero correcto que salvó el día: selección por prefijo y un límite limpio
Una firma financiera tenía una regla estricta de nombres: todo lo que afectaba al cliente vivía bajo tank/app/prod. Todo lo demás—artefactos de build, caches, restores de prueba—vivía bajo tank/scratch o tank/app/dev. La gente se quejaba de que era burocrático. Lo era. También era efectivo.
Durante un incidente de almacenamiento, la latencia subió y el pool se llenó más rápido de lo esperado. El equipo necesitaba liberar espacio sin jugar a la ruleta con borrados. Porque el árbol tenía límites limpios, pudieron dirigirse primero a los datasets de bajo valor: destruyeron clones y snapshots viejos bajo tank/scratch y confirmaron que tank/app/prod seguía intacto.
Luego auditaron el crecimiento de snapshots. El nombrado hizo trivial identificar qué servicio generaba más delta de snapshot porque estaba agrupado bajo tank/app/prod/<service>. Pudieron ralentizar al causante y mantener el sistema estable.
Nadie fue promovido por esto. Nadie escribió un postmortem titulado “Nuestra convención de nombres salvó producción.” Pero la ausencia de caos fue la idea. Aburrido funcionó.
Tareas prácticas: comandos, salidas, qué significa y la decisión que tomas
Estas son tareas reales que ejecutarás cuando construyas una convención de nombres, audites una existente o depures a las 02:17 con tu café guiando tus decisiones.
Task 1: Listar datasets con mountpoints para detectar deriva nombre→ruta
cr0x@server:~$ zfs list -o name,mountpoint,canmount -r tank/app/prod
NAME MOUNTPOINT CANMOUNT
tank/app/prod /srv/app/prod off
tank/app/prod/postgres /srv/app/prod/postgres off
tank/app/prod/postgres/data /srv/app/prod/postgres/data on
tank/app/prod/postgres/wal /srv/app/prod/postgres/wal on
Qué significa: Los padres llevan política (canmount=off), los hijos montan donde se espera y los mountpoints reflejan la jerarquía del dataset.
Decisión: Si ves un dataset montado en un lugar no relacionado (p. ej., /var/lib/postgresql mientras el nombre sugiere /srv), decide si realinear mountpoints o renombrar datasets para que los humanos dejen de adivinar mal.
Task 2: Mostrar propiedades heredadas para confirmar límites de política
cr0x@server:~$ zfs get -o name,property,value,source -r compression,atime,recordsize tank/app/prod/postgres
NAME PROPERTY VALUE SOURCE
tank/app/prod/postgres compression lz4 inherited from tank/app/prod
tank/app/prod/postgres atime off inherited from tank/app/prod
tank/app/prod/postgres recordsize 128K default
tank/app/prod/postgres/data recordsize 16K local
tank/app/prod/postgres/wal recordsize 128K default
Qué significa: Los valores por defecto vienen de tank/app/prod, y data está ajustado localmente. El nombrado te dice por qué data existe como dataset separado.
Decisión: Si encuentras muchas anulaciones local dispersas en datasets aleatorios, probablemente necesites introducir padres intermedios para llevar políticas compartidas—luego renombra u organiza en consecuencia.
Task 3: Encontrar “datasets misteriosos” que no encajan con la convención
cr0x@server:~$ zfs list -H -o name | egrep -v '^(tank/(app|infra|shared|backup|scratch)/)'
tank/data
tank/db2
tank/oldstuff
Qué significa: Esos datasets no están bajo ningún scope reconocido.
Decisión: Investiga cada uno: si es producción, migra/renombra a la convención; si es obsoleto, planifica su eliminación; si es desconocido, cuarenténalo poniendo readonly=on temporalmente mientras identificas propietarios.
Task 4: Mapear nombres de datasets a sistemas de ficheros montados reales
cr0x@server:~$ mount -t zfs | head
tank/app/prod/postgres/data on /srv/app/prod/postgres/data type zfs (rw,xattr,posixacl)
tank/app/prod/postgres/wal on /srv/app/prod/postgres/wal type zfs (rw,xattr,posixacl)
tank/shared/prod/home on /home type zfs (rw,xattr,posixacl)
Qué significa: Puedes ver rápidamente si algo está montado donde “no debería” (como montar un dataset en / o sobre /var sin querer).
Decisión: Si un dataset está montado sobre un directorio crítico inesperadamente, trátalo como un incidente: confirma si el directorio subyacente tiene contenido oculto y si un dataset padre fue montado por accidente.
Task 5: Confirmar que no estás ocultando hijos con un padre montado por accidente
cr0x@server:~$ zfs get -o name,property,value,source canmount,mountpoint tank/app/prod
NAME PROPERTY VALUE SOURCE
tank/app/prod canmount off local
tank/app/prod mountpoint /srv/app/prod local
Qué significa: canmount=off evita que este dataset se monte y eclipse a sus hijos.
Decisión: Si canmount=on en padres organizacionales, ponlo en off salvo que tengas una razón deliberada. Luego remonta y verifica la visibilidad.
Task 6: Auditar la proliferación de snapshots por prefijo de dataset (el nombrado paga aquí)
cr0x@server:~$ zfs list -t snapshot -o name,used,creation -s creation | tail -5
tank/app/prod/postgres/data@auto-hourly-20251226-0200 312M Fri Dec 26 02:00 2025
tank/app/prod/postgres/data@auto-hourly-20251226-0300 298M Fri Dec 26 03:00 2025
tank/app/prod/postgres/wal@auto-hourly-20251226-0200 28M Fri Dec 26 02:00 2025
tank/app/prod/postgres/wal@auto-hourly-20251226-0300 31M Fri Dec 26 03:00 2025
tank/app/prod/postgres/data@pre-upgrade-20251226-0322 1M Fri Dec 26 03:22 2025
Qué significa: Puedes ver deltas por dataset y si tu nombrado de snapshots es consistente. Los nombres de snapshots ordenan bien y señalan intención.
Decisión: Si ves deltas grandes inesperados bajo un dataset cuyo nombre sugiere “logs” o “cache”, sepáralo en datasets distintos y excluye los ruidosos de snapshots/replicación.
Task 7: Identificar datasets que no deben snapshotearse (y probarlo)
cr0x@server:~$ zfs get -r -o name,property,value org:auto-snapshot tank/app/prod
NAME PROPERTY VALUE SOURCE
tank/app/prod org:auto-snapshot true local
tank/app/prod/postgres org:auto-snapshot true inherited from tank/app/prod
tank/app/prod/postgres/data org:auto-snapshot true inherited from tank/app/prod
tank/app/prod/api/logs org:auto-snapshot false local
Qué significa: Usas propiedades de usuario para marcar elegibilidad de snapshot, y puedes anularlo en un dataset hoja limpiamente.
Decisión: Si estás codificando “nosnap” en el nombre del dataset, para. Usa propiedades de usuario para poder cambiar política sin renombrar activos.
Task 8: Encontrar los que consumen espacio por dataset y decidir si el nombre coincide con el valor
cr0x@server:~$ zfs list -o name,used,refer,compressratio -s used | tail
tank/app/prod/postgres/data 1.21T 1.19T 1.62x
tank/app/prod/vm/images 1.44T 1.40T 1.08x
tank/shared/prod/home 1.88T 1.75T 1.37x
Qué significa: Puedes ver qué datasets consumen espacio, y las ratios de compresión dan pistas sobre el contenido.
Decisión: Si vm/images es enorme y apenas se comprime, puede estar bien; si logs es enorme y tiene snapshots, es una señal de diseño—sepáralo y ajusta la política.
Task 9: Revisar cuotas y reservas (el nombre debería dejar esto obvio)
cr0x@server:~$ zfs get -o name,property,value,source quota,reservation tank/app/prod/api
NAME PROPERTY VALUE SOURCE
tank/app/prod/api quota 500G local
tank/app/prod/api reservation none default
Qué significa: Este dataset tiene un tope duro. Si se llena, el servicio falla—predecible.
Decisión: Si tienes cuotas, el nombre del dataset debería reflejar el límite (por servicio, por tenant, por rol). Si las cuotas están en un dataset ambiguo como tank/data, te estás buscando cortes inesperados.
Task 10: Averiguar quién “posee” un dataset (sin adivinar por el nombre)
cr0x@server:~$ zfs get -o name,property,value -s local,inherited -r org:owner,org:service,org:env tank/app/prod/postgres
NAME PROPERTY VALUE
tank/app/prod/postgres org:owner payments
tank/app/prod/postgres org:service postgres
tank/app/prod/postgres org:env prod
tank/app/prod/postgres/data org:owner payments
tank/app/prod/postgres/data org:service postgres
tank/app/prod/postgres/data org:env prod
Qué significa: Propiedad y entorno son metadatos explícitos, no conocimiento tribal.
Decisión: Si no puedes responder “a quién hago page por este dataset” a partir de las propiedades, arregla eso. Los nombres solos no son una estructura organizativa estable.
Task 11: Renombrar un dataset de forma segura (y verificar qué cambia)
cr0x@server:~$ sudo zfs rename tank/db2 tank/app/prod/postgres
cr0x@server:~$ zfs list -o name,mountpoint tank/app/prod/postgres
NAME MOUNTPOINT
tank/app/prod/postgres /srv/app/prod/postgres
Qué significa: La identidad del dataset cambió, y si los mountpoints se heredan o están establecidos con sentido, cae donde se espera.
Decisión: Antes de renombrar en producción, inventaría dependencias: scripts de backup, objetivos de replicación, reglas de monitorización, exports, configs de contenedores. Si no puedes inventariar, no estás listo para renombrar—crea un nuevo dataset y migra.
Task 12: Planear mapping de replicación usando nombres y confirmar presencia de snapshots
cr0x@server:~$ zfs list -t snapshot -o name -s creation -r tank/app/prod/postgres | tail -3
tank/app/prod/postgres/data@auto-hourly-20251226-0200
tank/app/prod/postgres/data@auto-hourly-20251226-0300
tank/app/prod/postgres/data@pre-upgrade-20251226-0322
cr0x@server:~$ sudo zfs send -R tank/app/prod/postgres@auto-hourly-20251226-0300 | sudo zfs receive -u backup/app/prod/postgres
Qué significa: -R replica el subtree. -u recibe sin montar inmediatamente (útil para cortes controlados).
Decisión: Si tu subtree incluye basura (logs, caches), no repiques todo. Separa datasets para que la replicación por subtree coincida con la intención del negocio. El nombrado hace obvia la separación y selección.
Task 13: Detectar mayúsculas inconsistentes y creatividad ilegal
cr0x@server:~$ zfs list -H -o name | egrep '[A-Z ]'
tank/App/Prod/API
Qué significa: Alguien creó un dataset con segmentos en mayúsculas, lo que suele romper convenciones y scripts que asumen minúsculas.
Decisión: Renombra a minúsculas ahora. Cuanto más esperes, más se solidifica la goma alrededor del error.
Task 14: Detectar “snowflakes” de mountpoint manual que morderán durante restores
cr0x@server:~$ zfs get -H -o name,value,source mountpoint -r tank | awk '$3 ~ /^local/ {print}'
tank/app/prod/postgres/data /var/lib/postgresql/data local
tank/shared/prod/home /home local
Qué significa: Estos datasets tienen overrides locales de mountpoint. Algunos están bien (/home es intencional); otros son sospechosos (postgres/data montando en /var mientras tu convención sugiere /srv).
Decisión: Decide si tu convención es “los nombres reflejan mountpoints” o “los nombres son lógicos, los mountpoints son legado.” Mezclar ambos sin documentación es cómo los restores montan en el lugar equivocado.
Guion de diagnóstico rápido: encontrar el cuello de botella pronto
Cuando el almacenamiento está “lento”, no tienes tiempo para admirar tu árbol de datasets. Necesitas una secuencia corta y brutal que te lleve a una hipótesis accionable. El nombrado importa aquí porque reduce el espacio de búsqueda.
Primero: ¿es capacidad a nivel de pool o presión por fragmentación?
cr0x@server:~$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 7.25T 6.91T 352G - - 52% 95% 1.00x ONLINE -
Interpretación: 95% lleno y 52% fragmentado es una fiesta de latencia a la que no te apuntaste.
Decisión: Libera espacio ahora (borra snapshots/clones en scopes de bajo valor como scratch), o añade capacidad. No ajustes recordsize mientras el pool se asfixia.
Segundo: ¿qué subtree de datasets está impulsando las escrituras y los deltas de snapshot?
cr0x@server:~$ zfs list -o name,used,refer -r tank/app/prod | tail
tank/app/prod/api 220G 180G
tank/app/prod/postgres 1.24T 1.20T
tank/app/prod/vm 1.50T 1.45T
Interpretación: Los pesos pesados están claros. Un buen nombrado te permite saber qué representan sin buscar en directorios.
Decisión: Centra la investigación en el(los) dataset(s) superior(es), no en todo el pool.
Tercero: ¿la carga está limitada por sync, por metadata o por fallos de caché de lectura?
cr0x@server:~$ zfs get -o name,property,value -r sync,recordsize,atime,primarycache tank/app/prod/postgres
NAME PROPERTY VALUE
tank/app/prod/postgres sync standard
tank/app/prod/postgres recordsize 128K
tank/app/prod/postgres atime off
tank/app/prod/postgres primarycache all
tank/app/prod/postgres/data recordsize 16K
Interpretación: Si el servicio es sensible a latencia de escritura y ves alta latencia en escrituras sync, mirarás SLOG, ajustes de sync y comportamiento de fsync de la aplicación. Si es latencia de lectura y hay muchos misses de caché, mirarás el tamaño del ARC y el working set.
Decisión: Decide si es un problema de propiedad (ajuste a nivel de dataset) o de hardware/pool. El nombrado ayuda porque roles como wal deberían tener su propio dataset, permitiendo ajustes dirigidos.
Cuarto: verifica la corrección de los mounts antes de culpar a los discos
cr0x@server:~$ zfs list -o name,mountpoint,canmount -r tank/app/prod/postgres
NAME MOUNTPOINT CANMOUNT
tank/app/prod/postgres /srv/app/prod/postgres off
tank/app/prod/postgres/data /srv/app/prod/postgres/data on
tank/app/prod/postgres/wal /srv/app/prod/postgres/wal on
Interpretación: Si algo está montado mal, puedes ver “problemas de rendimiento” que en realidad son “estás escribiendo en el filesystem raíz, no en ZFS” o “estás escribiendo en un directorio oculto bajo un mount”.
Decisión: Arregla mounts primero. Luego mide rendimiento otra vez. La mitad de los “incidentes” de almacenamiento son incidentes de identidad de ruta.
Errores comunes: síntoma → causa raíz → solución
1) Síntoma: “Mis archivos desaparecieron tras un reinicio”
Causa raíz: Un dataset padre montó sobre un directorio que antes contenía archivos (o sobre mountpoints de hijos), ocultando contenido. A menudo porque canmount=on en datasets organizacionales.
Solución: Pon canmount=off en padres, asegúrate de que los datasets hoja tengan los mountpoints correctos y busca archivos ocultos desmontando temporalmente e inspeccionando el directorio subyacente.
2) Síntoma: Los snapshots son masivos y las ventanas de replicación se retrasan
Causa raíz: Logs/cache/temp comparte dataset con datos durables, así que los snapshots capturan churn. El nombre suele revelarlo: tank/app/prod/api contiene logs/ y cache/ como directorios.
Solución: Sepáralo en .../data, .../logs, .../cache datasets. Excluye logs/cache de snapshots y replicación con propiedades de usuario.
3) Síntoma: La cuota afecta al equipo equivocado
Causa raíz: Cuotas colocadas en un dataset que no representa un límite de propiedad real (p. ej., tank/shared), o nombres ambiguos que fomentan uso mixto.
Solución: Reorganiza para que cada tenant/servicio tenga un dataset con un nombre claro y org:owner explícito. Aplica cuotas ahí, no en una capa shared desordenada.
4) Síntoma: Los backups fallan en cubrir un servicio después de un rename
Causa raíz: Selección de backup basada en nombres duros y los renombres se hicieron sin actualizar la canalización. O los backups usaban filtros por prefijo, pero el nuevo nombre quedó fuera del prefijo esperado.
Solución: Estandariza prefijos (tank/app/prod) y selecciona por prefijo más propiedades de usuario (p. ej., org:backup=gold). Trata los renombres de datasets como eventos gestionados con comprobaciones explícitas de dependencias.
5) Síntoma: La replicación llega a un árbol destino desordenado
Causa raíz: El nombrado destino no refleja el origen, así que los receives caen en rutas extrañas. Alguien hizo receives “rápidos” en backup/incoming y nunca normalizó.
Solución: Define una regla de mapeo determinista: tank/* a backup/* para scopes durables, y recibe en objetivos estables. Usa zfs receive -u y establece mountpoints intencionalmente.
6) Síntoma: “¿Por qué este dataset tiene propiedades raras?”
Causa raíz: Anulaciones de propiedades dispersas porque la jerarquía no incluye nodos intermedios de política. El nombrado típicamente lo muestra: profundidad inconsistente, agrupación de servicios ad-hoc.
Solución: Inserta datasets intermedios que representen conjuntos de políticas (p. ej., tank/app/prod, tank/app/prod/postgres). Mueve hijos bajo ellos y elimina anulaciones locales redundantes.
7) Síntoma: Monitorización y enrutamiento de alertas inconsistentes
Causa raíz: Los nombres de dataset no codifican una identidad de servicio estable, y no hay propiedades de usuario para mapear datasets a propietarios/entornos.
Solución: Aplica temprano en el nombre <scope>/<env>/<service> y añade org:owner, org:env, org:service en todos lados. La monitorización debería leer esas propiedades, no parsear cadenas aleatorias.
Listas de verificación / plan paso a paso
Paso a paso: establecer una convención de nombres sin romper producción
- Inventariar datasets actuales: lista nombres, mountpoints y propiedades clave. Identifica outliers y nombres ambiguos.
- Define tus scopes de primer nivel: elige 3–6 que encajen con la realidad operativa (
app,infra,shared,backup,scratch). - Define entornos: como mínimo
prodynonprod(ostage/devsi realmente los usas). - Elige nombres de servicio: identidades estables y “pageables”. Evita nombres de proyecto internos.
- Decide la base de mountpoint:
/srvvs/var/libvs legado. Escríbelo. La consistencia vence a la ideología. - Crea datasets padre con
canmount=off: estos serán tus portadores de política. - Establece valores por defecto de política al nivel correcto: compression, atime, acltype/xattr, snapdir y tus propiedades org.
- Migra un servicio a la vez: crea nuevos datasets, rsync/copia, corta el servicio al nuevo mount, verifica y retira los antiguos.
- Actualiza la automatización: horarios de snapshot, replicación, monitorización, reglas de selección de backup.
- Ciérralo: añade una comprobación previa en provisioning/IaC que rechace nombres no conformes.
Checklist: reglas de nombres para revisar
- Cada dataset de producción vive bajo
<pool>/app/prod(o tu equivalente). - Cada servicio tiene un subtree único:
.../<service>. - Existen datasets separados donde las propiedades difieren (DB data/WAL/logs/cache/uploads/VM images).
- Los padres que existen solo para agrupar tienen
canmount=off. - Los mountpoints están o bien alineados sistemáticamente con los nombres o son excepciones documentadas—nunca “lo que toque”.
- Existen propiedades de usuario para
org:owner,org:env,org:servicey niveles de backup/replicación. - Los nombres de snapshots siguen una convención consistente, timestamped y ordenable.
- Los destinos de replicación reflejan el origen con un mapeo determinista.
Checklist: cuando vas a renombrar un dataset
- Confirma que no hay referencias hardcodeadas en backups y trabajos de replicación.
- Confirma que la monitorización usa propiedades/prefijos que seguirán coincidiendo.
- Confirma que mountpoints y exports son correctos después del rename.
- Plan de rollback: si el rename causa problemas, ¿puedes renombrar de vuelta rápido?
- Comunica: los nombres de dataset son una API compartida; trátalo como un cambio de interfaz.
Preguntas frecuentes
1) ¿Los nombres de dataset tienen que coincidir con los mountpoints?
No. Pero si no lo hacen, debes ser consistente y deliberado. En producción, un mapeo predecible reduce errores humanos. Si heredas mountpoints legacy, mantén los nombres lógicos y registra el mapeo vía la propiedad mountpoint y documentación, no por corazonadas.
2) ¿Qué profundidad debería tener mi jerarquía de datasets?
Tan profunda como requieran tus límites de política, y no más. Si las propiedades no difieren, un dataset separado suele ser ruido. Si las propiedades difieren, no separarlo es deuda técnica con interés.
3) ¿Debería incluir región/host en el nombre del dataset?
Generalmente no. El pool ya vive en un host, y los objetivos de replicación deberían mapear nombres entre hosts. Región/host pertenece al inventario del sistema y al nombre del pool destino, no a cada ruta de dataset.
4) ¿Y en sistemas multi-tenant?
Usa un límite por tenant: tank/app/prod/<service>/tenants/<tenant-id> (o customers). Aplica cuotas y delegación en ese límite. No juntes múltiples tenants en un dataset a menos que compartan destino y política.
5) ¿Debería codificar la política de retención en el nombre del dataset?
No. Codifica la retención en propiedades de usuario (p. ej., org:backup=gold, org:retention=daily-30) o en la configuración de la herramienta de snapshots. Los nombres deben identificar la carga; las propiedades definen el tratamiento.
6) ¿Está bien tener datasets llamados “data”, “data2”, “misc”?
En un laboratorio, sí. En producción, es un incidente esperando a ocurrir. Si necesitas un cajón, llámalo scratch y trátalo como algo que se puede borrar sin disculpas.
7) ¿Puedo renombrar datasets de forma segura en producción?
A menudo sí, técnicamente. Operativamente, el riesgo es el ecosistema alrededor del nombre. Si scripts, monitorización, exports o backups refieren el nombre antiguo, los romperás. Renombra solo cuando puedas auditar dependencias, o migra creando nuevos datasets y moviendo datos.
8) ¿Cómo afectan los snapshots a la estrategia de nombres?
Los snapshots se dirigen como dataset@snap, así que nombres de dataset y nombres de snapshot forman un identificador combinado que humanos y herramientas consumen. Elige nombres legibles en esa forma combinada y ordenables por timestamp.
9) ¿Cuál es la ganancia rápida si ya tengo un nombrado desordenado?
Crea scopes limpios de primer nivel y empieza nuevas cargas bajo ellos. Luego migra gradualmente los peores. También añade org:owner y org:env en todos lados para que puedas enrutar alertas y decisiones sin parsear nombres.
10) ¿Debería usar un pool o varios pools para expresar “tiers”?
Si los tiers representan hardware distinto o dominios de fallo distintos, usa pools diferentes. Si los tiers son solo políticas distintas sobre el mismo hardware, los datasets bastan. No codifiques tiers en nombres cuando el almacenamiento subyacente no difiere realmente.
Conclusión: próximos pasos que perduran
Si tus nombres de datasets son actualmente un museo de decisiones pasadas, no intentes arreglarlo todo con un refactor de fin de semana. Arréglalo como un SRE: incrementalmente, con salvaguardas y teniendo en mente el próximo incidente.
- Elige una convención y documéntala en un sitio que la gente realmente vea durante provisioning y revisiones.
- Crea los datasets padre de política (
app/prod,app/stage,infra/prod,scratch) concanmount=off. - Añade propiedades de usuario para
org:owner,org:envyorg:service. Haz que la automatización las consuma en lugar de parsear nombres. - Separa un dataset de alto churn (logs/cache) de un dataset durable y observa cómo mejora inmediatamente el crecimiento de snapshots y el tiempo de replicación.
- Aplica cumplimiento en IaC o scripts de provisioning: rechaza datasets que no cumplan las reglas. Los humanos no recordarán; las herramientas sí.
Un buen nombrado no hará tus discos más rápidos. Hará tus decisiones más rápidas—y en producción, eso suele ser lo mismo.