Problema

En entornos de virtualización con Proxmox, es frecuente encontrarse con un número de FSYNC por segundo extremadamente bajo cuando el pool de ZFS está configurado sobre discos mecánicos o SSD de consumo. Un benchmark como pveperf muestra valores de 5‑10 FSYNC/s, lo que se traduce en latencias de escritura de varios cientos de milisegundos. La consecuencia directa son máquinas virtuales y contenedores que tardan mucho en iniciar, bases de datos que se cuelgan y cualquier carga que dependa de escrituras sincronizadas. El síntoma no es exclusivo de un modelo de servidor; cualquier combinación de ZFS + Proxmox que no tenga en cuenta la alineación de discos, la caché de escritura y los parámetros de sync puede presentar este comportamiento.

Causa

1. Falta de SLOG (Separate Log) rápido

ZFS escribe cada operación fsync en el Intent Log (ZIL). Si el pool no tiene un dispositivo de log dedicado (SLOG) y la única caché disponible es la RAM, cada fsync se fuerza a disco. En discos mecánicos de 10 K RPM el tiempo de rotación y seek hacen que el ZIL sea el cuello de botella.

2. Configuración de sync=standard en datasets críticos

El modo por defecto de ZFS (sync=standard) obliga a que cada fsync espere a que el ZIL sea persistido. En workloads con alta frecuencia de fsync (bases de datos, VM disks) esto degrada el rendimiento.

3. Uso de RAID‑Z2 con 10 K SAS y sin caché de escritura (L2ARC)

RAID‑Z2 protege contra dos fallos, pero cada escritura implica cálculos de paridad y escrituras en varios discos. Sin una capa de escritura en caché, la latencia se multiplica.

4. Parámetros del kernel y del controlador de discos

vm.swappiness, dirty_ratio, dirty_background_ratio y el scheduler del disco (deadline vs mq-deadline) pueden forzar que los buffers se vacíen antes de que el ZIL tenga oportunidad de agrupar escrituras.

5. SSD de consumo sin TRIM ni over‑provisioning

Los SSD baratos pierden rendimiento cuando el nivel de ocupación supera el 70 %. Un fsync que escribe en bloques ya saturados genera latencias inesperadas.

Solución

A. Añadir un SLOG de baja latencia

Instalar una NVMe o una SSD de alta resistencia (Enterprise, con endurance > 1 DWPD) como dispositivo de log dedicado. El SLOG solo almacena el ZIL, por lo que su capacidad puede ser pequeña (10‑40 GB) siempre que tenga suficiente endurance.

zpool add rpool log /dev/nvme0n1p1

B. Cambiar el modo de sincronización en datasets críticos

Para máquinas virtuales, contenedores y bases de datos, establecer sync=disabled o sync=always según el nivel de riesgo aceptable. sync=disabled permite que ZFS agrupe fsync y mejore el throughput, pero depende de la integridad del SLOG.

zfs set sync=disabled rpool/vmdata
zfs set sync=disabled rpool/containers

Si no se dispone de SLOG, usar sync=always mantiene la consistencia a costa de rendimiento, pero evita pérdidas de datos en caso de caída de energía.

C. Habilitar L2ARC opcional

Una SSD de gran capacidad como caché de lectura (L2ARC) reduce la carga de los discos mecánicos en lecturas aleatorias, liberando ancho de banda para el ZIL.

zpool add rpool cache /dev/sdb1

D. Ajustar tunables del kernel

Reducir los ratios de dirty pages permite que el kernel libere buffers antes de que el ZIL se saturé.

sysctl -w vm.dirty_ratio=10
sysctl -w vm.dirty_background_ratio=5

Persistir en /etc/sysctl.d/99-zfs-performance.conf.

E. Revisar el scheduler de los discos mecánicos

Cambiar a mq-deadline o bfq suele mejorar la latencia de escritura en discos SAS.

echo mq-deadline > /sys/block/sdX/queue/scheduler

F. Evaluar alternativas de RAID para VMs

Si la carga de VM es alta, migrar los discos de VM a un pool LVM‑Thin sobre un RAID‑10 hardware (por ejemplo, HP H730P) puede ofrecer latencias de < 2 ms. Mantener los datos estáticos en ZFS con RAID‑Z2 sigue siendo válido para backups y archivos.

Cuándo aplicar esta solución

  • Síntomas: pveperf muestra < 10 FSYNC/s, latencias de escritura > 50 ms, bases de datos con “slow commit”, VM que tardan > 30 s en iniciar.
  • Entorno: Proxmox 7+ con ZFS como root o como datastore, discos mecánicos SAS y/o SSD de consumo.
  • Requisitos: Disponibilidad de al menos una NVMe/SSD de alta endurance para SLOG; tolerancia a un pequeño riesgo de pérdida de datos si se usa sync=disabled sin SLOG.
  • No aplicar: Sistemas críticos sin alimentación ininterrumpida (UPS) y sin SLOG, donde la integridad de cada fsync es obligatoria. En esos casos mantenga sync=standard y considere hardware RAID con caché de escritura.

Código

# 1. Añadir SLOG (NVMe)
zpool add rpool log /dev/nvme0n1p1

# 2. Desactivar sync en datasets de VM y contenedores
zfs set sync=disabled rpool/vmdata
zfs set sync=disabled rpool/containers

# 3. Opcional: añadir L2ARC
zpool add rpool cache /dev/sdb1

# 4. Ajustes de kernel
cat <<EOF > /etc/sysctl.d/99-zfs-performance.conf
vm.dirty_ratio=10
vm.dirty_background_ratio=5
EOF
sysctl -p /etc/sysctl.d/99-zfs-performance.conf

# 5. Cambiar scheduler a mq-deadline
for dev in /sys/block/sd*; do
  echo mq-deadline > "$dev/queue/scheduler"
done

Verificación

  1. Ejecutar nuevamente pveperf. Un valor de FSYNC/s superior a 200 indica que el ZIL está siendo servido por el SLOG.
  2. Medir latencia de escritura con dd if=/dev/zero of=/rpool/vmdata/testfile bs=1M count=100 oflag=direct.
  3. Revisar zpool status -v para confirmar que el log está “ONLINE” y sin errores.
  4. En una VM con MySQL, observar la reducción del tiempo de COMMIT en SHOW GLOBAL STATUS LIKE 'Innodb_log_waits'.

Notas adicionales

  • Endurance del SLOG: Un SLOG con poca resistencia puede fallar rápidamente bajo carga constante. Monitoree el recuento de escrituras con smartctl -a.
  • UPS: Si usa sync=disabled sin SLOG, una caída de energía puede corromper el pool. Una UPS de al menos 10 minutos brinda margen para un apagado limpio.
  • Migración parcial: No es necesario recrear todo el pool. Puede crear un pool secundario con SLOG y mover los datasets de VM mediante zfs send/receive.
  • Compatibilidad: Los cambios de sync son retrocompatibles; los datasets heredarán la propiedad a menos que se sobrescriba explícitamente.
  • Monitorización: Añada alertas en zfs events para detectar errores de log o saturación de caché.

Con estos ajustes, la mayoría de los entornos Proxmox + ZFS recuperan un rendimiento de escritura que permite ejecutar bases de datos, entornos de escritorio y contenedores sin los cuellos de botella que provocan los bajos valores de FSYNC.