Esta pagina se ve mejor con JavaScript habilitado

FreeBSD ZFS Vol0 Conceptos básicos

 ·  🎃 kr0m

ZFS es un sistema de ficheros avanzado con un diseño que solventa la mayoría de los problemas presentes en los sistemas de ficheros actuales, originalmente fué desarrollado por Sun Microsystems pero actualmente es mantenido por la comunidad open source bajo el nombre OpenZFS . Los roles de gestor de volúmenes y sistema de ficheros han sido unificados permitiendo compartir el espacio de almacenamiento del pool entre varios sistemas de ficheros/datasets y unificando de forma mas coherente la visión del almacenamiento.

ZFS tiene tres objetivos principales:

  • Integridad de los datos: Cuando se escriben datos en el sistema de ficheros se calcula y almacena un checksum, cuando los datos son leídos este checksum es recalculado y comprobado con el que se almacenó en la escritura, si el checksum no coincide se ha detectado un error en los datos, si los datos dañados tienen redundancia se corregirá el problema de forma automática, en caso contrario solo será posible la detección del error, la redundancia depende del tipo de pool y del parámetro copies del dataset.

  • Pooled storage: Los dispositivos de almacenamiento son asignados a un pool, el espacio utilizado por nuestros datos será obtenido de este pool compartido, el pool puede crecer de tamaño tan solo añadiendo mas dispositivos de almacenamiento a este.

  • Rendimiento lecturas: Mediante caché de los ficheros mas utilizados ZFS logra un rendimiento superior en operaciones de lectura, la caché se compone de dos niveles.

    • ARC: Caché en RAM de los ficheros mas utilizados
    • L2ARC: Caché de segundo nivel en disco
  • Rendimiento escrituras: Por otro lado para aumentar el rendimiento en las escrituras tenemos el ZIL/SLOG.

    • ZIL: Parte del pool utilizado cuando el SO realiza una petición de escritura síncrona, es decir desea que el dato sea escrito de forma inmediata al disco y no en RAM, los datos son escritos al ZIL y estos serán volcados al pool cuando ZFS lo considere oportuno. Si el equipo se apagase de forma abrupta se leería el ZIL y se transferirían los datos al pool, en ningún caso hay pérdida de datos, la mayoría de aplicaciones no se verán beneficiadas por el ZIL, solo las que trabajen con datos síncronos como bases de datos, sistemas de almacenamiento remotos VMWare o NFS. El acceso al ZIL resulta mas rápido que el acceso al propio pool porque en esta zona del disco no se debe consultar ninguna tabla de inodos, ni buscar espacio suficiente para que quepan los datos ni reescribir estructuras internas de ZFS ni nada por el estilo, tan solo se escriben los datos de forma secuencial para luego ser volcados al pool donde si que se tienen en cuenta todos estos factores. Todos los pools tienen ZIL.
    • SLOG: Es exactamente lo mismo que el ZIL solo que se ha externalizado a un dispositivo externo para liberar de esta carga al pool y distribuir así los IOPs. Suele tratarse de un dispositivo mas rápido aunque si no lo es también se vería una ligera mejora ya que en todos los casos la carga de IOPs se está distribuyendo, debemos tener en cuenta que si asignamos mas dispositivos SLOG a un mismo pool los IOPs todavía se balancearán mas. Los SLOGs deben ser espejados ya que si no lo hacemos y coincide un apagado inesperado con el fallo del disco de SLOG habremos perdido datos. Como norma general se suele dimensionar el SLOG con 16GB por cada 64Gb de datos pero en servidores con muchas escrituras se suele aplicar la fórmula: max amount of write traffic per second x 15.

Los tipos de vdev son:

Tipo de RAID Descripción Discos necesarios Discos de paridad Tolerancia a fallos
Normal(Stripe con 1 disco) Equivale a tener un único disco pero con las capacidades de ZFS y la posibilidad de expandirlo a mirror. 1 0 0
Striping Equivalente a RAID0, se escribe de forma simultanea en todos los discos parte de los datos, la información queda repartida entre todos los discos, en las lecturas se lee en paralelo de todos ellos. 2+ 0 0
Mirroring Equivalente a RAID1, la totalidad de los datos son escritos en todos los discos, en las lecturas se lee en paralelo de todos ellos. 2+ 0 N-1
Pool de 2vdevs Mirror Equivalente a RAID10, se trata de un dispositivo que utiliza por debajo dos RAID1. 2+ 0 N-1
RAID-Z1 Equivalente a RAID5, se emplean N-1 discos para datos y uno de ellos para paridad, en todos los discos de datos hay parte de los datos, se escribe y se lee entre los discos de forma paralela. 3+ 1 1
RAID-Z2 Equivalente a RAID6, exactamente igual que RAID-Z1 pero la paridad se escribe por duplicado. 4+ 2 2
RAID-Z3 Equivalente a RAID7, exactamente igual que RAID-Z2 pero la paridad se escribe por triplicado. 5+ 3 3

Cuando un pool entra en modo degradado la información del pool sigue estando disponible pero el rendimiento se verá reducido(exceptuando los mirrors) ya que la información faltante debe ser recalculada desde los datos de redundancia, cuando se haga una sustitución del disco defectuoso este será llenado(resilvered) con los datos faltantes recalculándolos desde los datos de redundancia, hasta que el resilver no termine el rendimiento seguirá viéndose afectado.

No es recomendable montar un RAID-Z1 porque cuando un disco averiado es sustituido se inicia el proceso de resilvering, en este momento los otros discos (que seguramente tendrán la misma antiguedad que el disco averiado) empiezan a ser estresados con una probabilidad aproximada del 8% de fallo, si se diese el caso de fallo se perderían los datos de forma irremediable, por lo tanto siempre hay que elegir un raid con una tolerancia de fallo de mas de un disco.

Antes de empezar a configurar algún pool ZFS debemos aclarar alguna terminología y funcionalidades de ZFS:

Término Descripción
Vdev Cada disco/partición/RAID creado mediante ZFS es un vdev, por ejemplo podría tener un disco standalone, una partición de un disco y un RAID1 con otro par de discos, pongamos que el disco sea de 10Gb, la partición de 5Gb y los del mirror 20Gb cada uno, uniendo estos vdevs en un pool obtendríamos 35Gb de almacenamiento.
Pool Los pools son la unión de vdevs para formar una unidad de almacenamiento, el pool luego es utilizado para crear sistemas de ficheros(datasets) o dispositivos de bloque(volúmenes), todos los datasets o volúmenes comparten el espacio entre ellos, las capacidades de los datasets/volúmenes son determinadas por la versión ZFS del pool donde fueron creados.
Copy-On-Write Cuando se actualiza un fichero bajo ZFS, los datos antiguos del fichero no son sobreescritos, si no que se escriben los nuevos en otra localización del disco para acto seguido actualizar la metainformación del sistema de ficheros, de este modo en caso de crash del sistema o apagado abrupto del equipo el fichero original sigue existiendo, como la metainformación no llegó a actualizarse y sigue apuntando a la posición original ZFS no necesita realizar fscks, simplemente se perderán los datos nuevos.
Dataset Término genérico para referirse a un sistema de ficheros, volumen, snapshot o clon, cada dataset posee un nombre único del estilo poolname/path@snapshot. Los datasets hijos son nombrados de forma jerárquica, además los hijos heredarán las propiedades de los padres, si el nivel de jerarquía es de varios niveles las propiedades se van acumulando.
Sistema de ficheros La mayoría de datasets se emplean como sistemas de ficheros, estos pueden ser montados y contienen ficheros y directorios con sus permisos, flags y metainformación.
Volumen Se trata de dispositivos de bloques, estos pueden resultar útiles para emplear otros sistemas de ficheros como UFS sobre ZFS o como dispositivos de almacenamiento en sistemas de virtualización.
Snapshot Al tratarse de un sistema de ficheros COW no requieren de espacio adicional y son instantáneos, se puede revertir a un snapshot en concreto o montarlo como RO para recuperar un fichero determinado. También se permite realizar snapshots sobre volúmenes pero no es posible montarlos solo clonarlos o volver al estado anterior del snapshot.
Clon Un clon es una versión escribible de un snapshot permitiendo un fork del sistema de ficheros, un clon no ocupa espacio adicional mientras no se realicen cambios en él, el snapshot no puede ser eliminado mientras tenga clones que dependan de él, el snapshot es el padre y el clon su hijo, pero esta relación puede ser intercambiada promoviendo el clon, de este modo será el snapshot quien dependa del clon pudiendo eliminar el snapshot si así lo deseamos. Los clones resultan muy útiles para dar acceso a datos comunes a dos equipos que necesitan realizar cambios sobre estos, al ser clones los datos comunes se comparten sin necesitar el doble de espacio.
Checksum ZFS soporta varios algoritmos de checksum, fletcher2, fletcher4 y sha256, en todos cabe la posibilidad de colisión pero sha256 es el mas fiable a costa de una mayor carga computacional.
Compresión La compresión además de la disminución del espacio necesario para almacenar ficheros también aporta otro beneficio derivado que es la reducción de I/O ya que para leer o escribir un fichero hay que hacerlo sobre un número menor de bloques. Cada dataset tiene su propia compresión, los algoritmos disponibles son:
LZ4: Es el algoritmo recomendado en ZFS,  comparándolo con LZJB comprime un 50% mas rápido datos comprimibles y es 3X mas rápido con datos no comprimibles, descomprimiendo es un 80% mas rápido.
LZJB: Ofrece una buena compresión sin consumir tanta CPU como GZIP.
GZIP: La mayor ventaja de GZIP es la posibilidad de configurar su nivel de compresión de este modo el administrador de sistemas es capaz de ajustar los recursos de CPU que quiere asignar a la tarea de compresión.
ZLE: Algoritmo que solo comprime secuencias de 0s, solo es útil si nuestro dataset va a contener grandes secuencias de 0s.
Copias Es posible inidicar el número de copias que queremos hacer de los datos, de este modo incluso con un disco se pueden recuperar datos dañados ya que los datos están en varias zonas del disco.
Deduplicación La deduplicación funciona almacenando el hash de todos los bloques existentes en RAM, cuando se escribe un bloque se comprueba contra esta tabla, si ya existe el fichero se genera una referencia a este, si no se escribe como un fichero mas, hay dos modos de comprobar la deduplicación:
on: Se comprueba el hash que hay almacenado en RAM, en estos casos puede darse el caso de colisión.
verify: Se comprueba el hash que hay almacenado en RAM y además se lee el fichero byte por byte para compararlo con el nuevo.
La deduplicación precisa de una considerable cantidad de RAM, unos 5-6GB de RAM por terabyte de datos, si no disponemos de suficiente RAM podemos utilizar L2ARC para intentar paliar el problema pero seguramente sea mejor utilizar compresión y no deduplicación ya que la compresión no consume RAM y también ahorra espacio. La deduplicación solo resulta útil en ficheros de texto planos idénticos (TXT,HTML,PDF,DOC), si cambia lo mas mínimo un fichero de otro ya no se deduplica. Para temas de virtualización seguramente solo resulte útil si utilizamos jails, si utilizamos Bhyve consumiremos una gran cantidad de RAM sin ningún beneficio.
Scrub Es posible realizar una verificación manual de los checksums de todos los bloques, de este modo se repararán los que tengan redundancia.
Cuota ZFS permite definir quotas sobre datasets, usuarios o grupos del sistema pero no sobre volúmenes ya que estos ya están limitados por su propia naturaleza.
Reservation Mediante la reserva de espacio podemos asegurarnos de que un dataset en concreto siempre tenga un % del espacio reservado para él, esto puede resultar muy útil para los logs del sistema o cualquier servicio crítico del equipo.
Resilver Se trata del proceso de llenado de un disco nuevo que ha reemplazado uno anterior fallido.
Estado de vdevs/pools Online: El vdev está conectado y completamente operativo.
Offline: El vdev fué deshabilitado por el administrador para realizar alguna tarea de mantenimiento o reemplazo de este.
Degraded: El pool tiene algún vdev fallando o offline, es preciso su reemplazo o reincorporación, el pool sigue funcionando pero en modo degradado.
Faulted: El pool queda inoperativo seguramente por el fallo de mas de un vdev.

Podemos ver una lista mas minuciosa en el siguiente enlace:  https://www.freebsd.org/doc/handbook/zfs-term.html#zfs-term-dataset

Debemos tener en cuenta que en FreeBSD no existe penalización en cuanto a la utilización de discos enteros o particiones para los pools, esto difiere sobre las recomendaciones realizadas por la documentación de Solaris. En FreeBSD NO debemos utilizar discos enteros en ningún caso, si el SO arranca desde dicho pool al no tener particiones no hay lugar donde almacenar el boot code dejándolo inarrancable, por otro lado si es un pool de datos también puede ocasionar problemas ya que es imposible determinar de forma confiable el tamaño de un disco no particionado.

En cuanto al uso de RAM se suele recomendar 1Gb por cada terabyte de datos, en caso de activar la deduplicación 5-6Gb por terabytes, si no disponemos de suficiente RAM podemos utilizar L2ARC para intentar paliar el problema pero seguramente sea mejor utilizar compresión y no deduplicación ya que la compresión no consume RAM y también ahorra espacio.

Si te ha gustado el artículo puedes invitarme a un RedBull aquí