El rendimiento de SSD/NVMe en Ubuntu 24.04 empeora con el tiempo: demuestra que es TRIM/GC y arréglalo

¿Te fue útil?

Reinicias la máquina y vuelve a estar rápida. Dos semanas después, vuelve a pasar: las escrituras se atascan, la latencia explota, las bases de datos empiezan a “fallar” por timeout y los paneles parecen un sismógrafo. El disco está “sano”, la CPU está aburrida y el equipo de aplicaciones cree que cambiaste algo. No lo hiciste. Lo hizo el SSD.

Este modo de fallo es común en servidores Ubuntu 24.04: el rendimiento de SSD/NVMe se degrada lentamente a medida que el mapa de espacio libre del disco se ensucia, la recolección de basura (GC) hace más trabajo y TRIM/discard no ocurre o no llega al dispositivo físico. La buena noticia: puedes probarlo con datos sólidos y corregirlo de formas que puedas verificar.

Cómo se observa la ralentización en sistemas reales

No todos los informes de “NVMe lento” son por TRIM/GC. Pero el patrón “empeora con el tiempo” es un indicio claro. Esto es lo que suele ocurrir cuando discard/TRIM no es efectivo:

  • La latencia de escritura aumenta gradualmente bajo cargas constantes, especialmente escrituras aleatorias y cargas mixtas lectura/escritura.
  • Picos periódicos de latencia (cientos de milisegundos a segundos) incluso cuando la aplicación no está saturando el ancho de banda.
  • Reiniciar o un largo periodo de inactividad mejora temporalmente el rendimiento. (Algunos discos realizan GC en segundo plano más agresivamente cuando están inactivos; un reinicio también puede cambiar patrones y dar tiempo ocioso.)
  • El espacio libre en el sistema de archivos parece correcto, pero el dispositivo se comporta como si estuviera lleno. Ese es el punto: la noción de “libre” del SSD no coincide con la del sistema de archivos salvo que TRIM lo informe.
  • iowait no tiene por qué ser alto. Pueden estar bloqueadas unas pocas hilos en almacenamiento y aun así romper tus SLO.

La mayoría de los equipos descubren esto igual: un sistema en producción que “iba bien” al inicio se convierte en generador de incidentes a cámara lenta. Tu instinto inicial es culpar la base de datos, luego el kernel, luego la nube, luego al becario. No lo hagas. Empieza por verificar si al SSD se le está informando qué bloques ya no se usan.

Hechos interesantes y contexto histórico (lo breve y útil)

  1. Los SSDs de consumo tempranos podían perder rendimiento drásticamente tras llenarse una vez, porque tenían poca sobreprovisión y una GC rudimentaria.
  2. TRIM se introdujo para alinear la visión del sistema de archivos sobre el espacio libre con la del SSD. Sin él, el SSD debe asumir que cada bloque escrito sigue siendo relevante.
  3. La “recolección de basura” no es opcional en flash: las páginas se leen y escriben, pero el borrado ocurre en bloques mayores, por lo que reescribir implica mover datos.
  4. La amplificación de escritura es el enemigo que no ves: una pequeña escritura del host puede provocar muchas escrituras internas cuando el SSD debe consolidar páginas válidas.
  5. NVMe mejoró latencia y paralelismo, pero no abolió la física. La GC sigue existiendo; solo sucede a IOPS más altos y a veces con caídas más pronunciadas.
  6. Linux soporta TRIM desde hace tiempo, pero “soportar” no significa “habilitado de extremo a extremo”. LUKS, LVM, dm-crypt, capas device-mapper y almacenamiento virtualizado pueden bloquear discards si no están configurados.
  7. Montar con discard continuo fue históricamente controvertido porque puede añadir sobrecarga y fragmentación; fstrim periódico se volvió el comportamiento efectivo por defecto en muchas distribuciones.
  8. Algunos arrays y dispositivos en la nube ignoran los discards o los traducen de forma que no liberan realmente espacio físico. El huésped cree que ayudó; el backend se encoge de hombros.

Guía de diagnóstico rápido (primero/segundo/tercero)

Esta es la versión para cuando te está tocando alguien. El objetivo no es un análisis perfecto; es encontrar el cuello de botella en minutos y decidir si persigues TRIM/GC o otra cosa.

Primero: confirma que es latencia de almacenamiento, no CPU/memoria

  • Revisa iostat por latencia de dispositivo (await) y utilización.
  • Revisa IO por proceso con pidstat o métricas de la aplicación.
  • Busca un patrón: latencia que sube durante días/semanas, no un cambio brusco tras un despliegue.

Segundo: confirma que la ruta TRIM existe de extremo a extremo

  • ¿Está fstrim.timer habilitado y exitoso?
  • ¿El sistema de archivos soporta discard? ¿La capa de bloques acepta discards?
  • ¿Estás en LUKS/LVM/MD RAID donde los discards pueden estar deshabilitados o bloqueados?

Tercero: reproduce y mide con una carga controlada

  • Usa fio para ejecutar una prueba consistente de escrituras aleatorias (con cuidado, en un objetivo no productivo o una partición de repuesto).
  • Ejecuta fstrim, luego repite la prueba y compara la distribución de latencias, no solo la media de MB/s.

Si la ejecución post-TRIM mejora materialmente la latencia p95/p99 o mantiene IOPS más tiempo antes de caer, tienes al culpable: el disco estaba falto de bloques limpios.

Demostrar que es TRIM/GC: mediciones que resisten discusiones

Los debates sobre TRIM y GC suelen atraer gestos vagos. No participes. Produce evidencia que responda a una pregunta: ¿informar al dispositivo sobre bloques liberados reduce los síntomas de amplificación de escritura y la latencia?

Dos cosas importan:

  • Distribución de latencias (p95/p99/p99.9), no solo el rendimiento medio. El dolor de la GC suele aparecer como picos.
  • Antes/después de un evento de discard (fstrim manual o carga controlada con discard), usando el mismo perfil de trabajo.

También recuerda qué no es TRIM:

  • No es una “desfragmentación” mágica para SSDs.
  • No borra celdas instantáneamente; marca páginas como inválidas para que el SSD pueda borrar bloques después de forma eficiente.
  • No arregla un disco que está muriendo, un controlador saturado o una configuración de colas rota.

Una cita útil para tener en la pared, porque refleja la postura operativa necesaria aquí:

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

Ahora manos a la obra: tareas concretas con comandos, salidas y la decisión a tomar a continuación.

Tareas prácticas: comandos, salida esperada y qué decisión tomar

Están ordenadas más o menos como las ejecutaría en un servidor Ubuntu 24.04 con sospecha de “SSD que se vuelve más lento con el tiempo”. Los comandos son reales y ejecutables. Las salidas son representativas; los nombres de dispositivo serán diferentes en tu entorno.

Tarea 1: Identificar el/los dispositivo(s) de bloque reales

cr0x@server:~$ lsblk -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINTS,MODEL,ROTA,DISC-MAX,DISC-GRAN
NAME        TYPE  SIZE FSTYPE MOUNTPOINTS MODEL               ROTA DISC-MAX DISC-GRAN
nvme0n1     disk  1.8T        /dev/nvme0n1                     0    2G       4K
├─nvme0n1p1 part  512M vfat   /boot/efi
└─nvme0n1p2 part  1.8T crypto
  └─vg0-root lvm   300G ext4  /

Qué significa: Estás en NVMe (ROTA=0), y la pila incluye cifrado LUKS + LVM. Ese es exactamente el sitio donde los discards suelen morir sin hacer ruido.

Decisión: Debes verificar el soporte de discard a través de dm-crypt y LVM, no solo en el sistema de archivos.

Tarea 2: Comprobar tipo de sistema de archivos y opciones de montaje (discard vs periódico)

cr0x@server:~$ findmnt -no SOURCE,FSTYPE,OPTIONS /
/dev/mapper/vg0-root ext4 rw,relatime,errors=remount-ro

Qué significa: No hay la opción discard en el montaje. Eso no es automáticamente incorrecto; Ubuntu suele confiar en fstrim periódico.

Decisión: No añadas discard a la ligera. Primero verifica si TRIM periódico está habilitado y funcionando.

Tarea 3: ¿Está habilitado el temporizador TRIM semanal?

cr0x@server:~$ systemctl status fstrim.timer
● fstrim.timer - Discard unused blocks once a week
     Loaded: loaded (/usr/lib/systemd/system/fstrim.timer; enabled; preset: enabled)
     Active: active (waiting) since Mon 2025-12-22 00:12:01 UTC; 1 weeks 1 days ago
    Trigger: Mon 2025-12-29 00:28:14 UTC; 1 days ago
   Triggers: ● fstrim.service

Qué significa: El temporizador está habilitado y programado. Eso es necesario, pero no suficiente.

Decisión: Comprueba el resultado de la última ejecución. Un temporizador puede estar habilitado y aun así fallar cada vez.

Tarea 4: ¿fstrim tuvo éxito en la última ejecución?

cr0x@server:~$ journalctl -u fstrim.service -n 50 --no-pager
Dec 29 00:28:14 server systemd[1]: Starting fstrim.service - Discard unused blocks on filesystems from /etc/fstab...
Dec 29 00:28:14 server fstrim[32107]: /: 0 B (0 bytes) trimmed on /dev/mapper/vg0-root
Dec 29 00:28:14 server systemd[1]: fstrim.service: Deactivated successfully.
Dec 29 00:28:14 server systemd[1]: Finished fstrim.service - Discard unused blocks on filesystems from /etc/fstab.

Qué significa: Se recortaron 0 B. Eso puede significar “nada que recortar” o “discard no pasa”, o “el sistema de archivos cree que no hay nada libre”, o “estás sobre un dispositivo virtual que lo ignora”. En un sistema activo, 0 B semana tras semana es sospechoso.

Decisión: Valida el soporte de discard en la capa de bloques y a través de dm-crypt/LVM. Además ejecuta un recorte manual y mira si reporta algo.

Tarea 5: Verificar que el dispositivo informe capacidad de discard

cr0x@server:~$ cat /sys/block/nvme0n1/queue/discard_max_bytes
2147483648

Qué significa: El NVMe crudo acepta discards de hasta 2 GiB por comando. Bien.

Decisión: Si no estás recortando, no es porque el NVMe no pueda. Es porque tu pila de software no está emitiendo discards o no los está pasando hacia abajo.

Tarea 6: Comprobar si el dispositivo mapeado soporta discard (capa dm)

cr0x@server:~$ cat /sys/block/dm-0/queue/discard_max_bytes
0

Qué significa: Tu dispositivo dm (probablemente un LV LVM o mapeo dm-crypt) no anuncia discard. Por eso fstrim reporta 0 bytes: el discard está bloqueado por encima del NVMe.

Decisión: Inspecciona la configuración de dm-crypt y LVM. Probablemente necesites habilitar discards para LUKS (allow-discards) y asegurarte de que LVM no lo impida.

Tarea 7: Confirmar la opción de dm-crypt para discards

cr0x@server:~$ sudo cryptsetup status nvme0n1p2
/dev/mapper/nvme0n1p2 is active and is in use.
  type:    LUKS2
  cipher:  aes-xts-plain64
  keysize: 512 bits
  key location: keyring
  device:  /dev/nvme0n1p2
  sector size:  512
  offset:  32768 sectors
  size:    3906250000 sectors
  mode:    read/write
  flags:   

Qué significa: No se muestran flags. Si allow-discards estuviera habilitado, normalmente lo verías en flags.

Decisión: Planifica un cambio controlado para habilitar discards en crypttab (o volver a abrir el mapeo con discards) y valida que dm anuncie discard después.

Tarea 8: Comprobar la configuración de /etc/crypttab

cr0x@server:~$ sudo cat /etc/crypttab
nvme0n1p2 UUID=9f3d7b2a-2c42-4e47-b2c6-7d92a4e5a8a1 none luks,discard

Qué significa: Este ejemplo muestra discard ya establecido. Si el tuyo no lo tiene, los discards están bloqueados por dm-crypt por diseño.

Decisión: Si falta, añade discard (o allow-discards dependiendo de la herramienta) y programa un reinicio o mantenimiento para reabrir el mapeo de forma segura.

Tarea 9: Validar que LVM no sea el cuello de botella de discard

cr0x@server:~$ sudo lvs -o lv_name,vg_name,lv_attr,segtype,devices
  LV   VG  Attr       Type   Devices
  root vg0 -wi-ao---- linear /dev/mapper/nvme0n1p2(0)

Qué significa: Un LV lineal está bien. Los thin pools y snapshots complican la semántica de discard.

Decisión: Si ves thin-pool o uso intenso de snapshots, debes verificar el soporte de discard/trim en esa disposición y considerar ejecutar fstrim periódico dentro del huésped además de asegurar el paso de discards en el host.

Tarea 10: Ejecutar un fstrim manual e interpretarlo

cr0x@server:~$ sudo fstrim -av
/boot/efi: 256.4 MiB (268783616 bytes) trimmed on /dev/nvme0n1p1
/: 112.7 GiB (121011388416 bytes) trimmed on /dev/mapper/vg0-root

Qué significa: Así es como luce un trim “funcionando”: bytes recortados distintos de cero, especialmente en el sistema raíz. Si tu journal anterior mostró 0 B y ahora ves recortes grandes, acabas de encontrar un programador roto o una ruta previamente bloqueada que arreglaste.

Decisión: Si trim ahora funciona, sigue a probar la mejora de rendimiento (fio + iostat). Si fstrim sigue mostrando 0 B pero sabes que borras datos, sigue investigando: la ruta de discard sigue rota o tu carga no libera bloques de una forma visible por trim.

Tarea 11: Observar latencia y utilización durante un periodo lento

cr0x@server:~$ iostat -x 1 10
Linux 6.8.0-41-generic (server)  12/30/2025  _x86_64_  (16 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           3.12    0.00    1.45    2.10    0.00   93.33

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz  aqu-sz  %util
nvme0n1          5.00    220.0     0.00   0.00    2.40    44.00   310.00  18432.0   120.00  27.91   38.50    59.46   12.40  98.00

Qué significa: %util cerca de 98% con w_await ~38 ms indica que el dispositivo está saturado y las escrituras esperan. Si esto crece con el tiempo bajo la misma carga, la presión de GC es una sospecha fuerte.

Decisión: Captura esta línea base “mala” y compárala inmediatamente después de un fstrim exitoso y una breve ventana de inactividad.

Tarea 12: Comprobar NVMe SMART / estado para descartar fallos obvios

cr0x@server:~$ sudo nvme smart-log /dev/nvme0n1
Smart Log for NVME device:nvme0n1 namespace-id:ffffffff
critical_warning                    : 0x00
temperature                         : 43 C
available_spare                     : 100%
available_spare_threshold           : 10%
percentage_used                     : 3%
data_units_read                     : 123,456,789
data_units_written                  : 98,765,432
host_read_commands                  : 3,210,987,654
host_write_commands                 : 2,109,876,543
controller_busy_time                : 9,812
power_cycles                        : 27
power_on_hours                      : 2,144
unsafe_shutdowns                    : 1
media_errors                        : 0
num_err_log_entries                 : 0

Qué significa: Sin advertencias críticas, bajo desgaste (percentage_used). Esto apoya la idea de que el disco no está fallando; sufre de mantenimiento interno bajo carga.

Decisión: Si ves errores de medios, advertencias críticas o porcentaje alto de uso, trátalo primero como un problema de fiabilidad de hardware. TRIM no salvará un SSD que está muriendo.

Tarea 13: Medir rendimiento con un trabajo controlado de fio (antes de TRIM)

Haz esto solo en un objetivo seguro (un LV de prueba, una partición de repuesto o un archivo dedicado en un sistema no crítico). Si apuntas fio a datos productivos sin pensar, no eres SRE; eres una historia de advertencia.

cr0x@server:~$ sudo fio --name=randwrite --filename=/var/tmp/fio.test --size=8G --direct=1 --ioengine=libaio --bs=4k --rw=randwrite --iodepth=32 --numjobs=1 --runtime=60 --time_based --group_reporting
randwrite: (groupid=0, jobs=1): err= 0: pid=4123: Tue Dec 30 11:12:01 2025
  write: IOPS=18.2k, BW=71.2MiB/s (74.7MB/s)(4272MiB/60001msec); 0 zone resets
    slat (nsec): min=1500, max=180512, avg=6210.3, stdev=3341.2
    clat (usec): min=80, max=215000, avg=1732.4, stdev=8200.7
     lat (usec): min=90, max=215020, avg=1738.8, stdev=8201.1
    clat percentiles (usec):
     |  1.00th=[  120],  5.00th=[  150], 10.00th=[  170], 50.00th=[  320],
     | 90.00th=[ 1400], 95.00th=[ 3800], 99.00th=[20000], 99.90th=[120000]
  cpu          : usr=3.10%, sys=12.40%, ctx=1123456, majf=0, minf=12
  IO depths    : 1=0.1%, 2=0.2%, 4=0.5%, 8=1.2%, 16=7.0%, 32=91.0%, >=64=0.0%

Qué significa: La latencia media parece “aceptable”, pero p99 y p99.9 son feas. Esas colas largas son las que dañan bases de datos y SLOs de API. Este patrón es consistente con paros por GC.

Decisión: Ejecuta fstrim (si es posible), opcionalmente deja inactivo unos minutos y vuelve a ejecutar el mismo trabajo fio para comparar percentiles.

Tarea 14: Recortar, luego volver a ejecutar fio (después de TRIM)

cr0x@server:~$ sudo fstrim -v /
/: 112.7 GiB (121011388416 bytes) trimmed on /dev/mapper/vg0-root
cr0x@server:~$ sudo fio --name=randwrite --filename=/var/tmp/fio.test --size=8G --direct=1 --ioengine=libaio --bs=4k --rw=randwrite --iodepth=32 --numjobs=1 --runtime=60 --time_based --group_reporting
randwrite: (groupid=0, jobs=1): err= 0: pid=4188: Tue Dec 30 11:16:01 2025
  write: IOPS=28.9k, BW=113MiB/s (118MB/s)(6780MiB/60001msec); 0 zone resets
    slat (nsec): min=1500, max=110220, avg=5901.1, stdev=2987.4
    clat (usec): min=70, max=42000, avg=980.2, stdev=1400.3
     lat (usec): min=78, max=42012, avg=986.1, stdev=1400.5
    clat percentiles (usec):
     |  1.00th=[  110],  5.00th=[  140], 10.00th=[  160], 50.00th=[  280],
     | 90.00th=[  980], 95.00th=[ 1700], 99.00th=[ 5200], 99.90th=[16000]

Qué significa: La latencia de cola mejoró muchísimo. El disco dedica menos tiempo a mover páginas válidas durante las escrituras porque tiene más bloques pre-borrados con los que trabajar.

Decisión: Has “probado” la hipótesis: el estado TRIM/GC afecta al rendimiento. Procede a soluciones permanentes: asegúrate de que los discards ocurran de forma fiable y considera prácticas operativas que eviten que los discos vivan al 95% de ocupación.

Tarea 15: Confirmar que no está habilitado el discard continuo (y decidir si lo quieres)

cr0x@server:~$ mount | grep ' on / '
/dev/mapper/vg0-root on / type ext4 (rw,relatime,errors=remount-ro)

Qué significa: No hay la opción discard en el montaje. Eso está bien si el recorte periódico funciona.

Decisión: Prefiere fstrim periódico para servidores de propósito general. Usa discard continuo solo para cargas concretas donde hayas medido beneficio y la sobrecarga sea aceptable.

Tarea 16: Comprobar espacio libre y riesgo de sobrellenado

cr0x@server:~$ df -hT /
Filesystem              Type  Size  Used Avail Use% Mounted on
/dev/mapper/vg0-root    ext4  295G  271G   10G  97% /

Qué significa: 97% lleno. Esta es una zona de caída de rendimiento para muchos SSDs, incluso con TRIM, porque el disco tiene menos espacio para wear leveling y GC.

Decisión: El espacio libre es una característica de rendimiento. Apunta a 70–85% de utilización en sistemas con muchas escrituras, o añade capacidad. Si finanzas se quejan, llámalo “seguro contra latencia”.

Broma #1: Ejecutar SSDs al 97% de ocupación es como hacer el simulacro de incendio durante un incendio real: técnicamente un ejercicio, prácticamente un mal día.

Soluciones que funcionan (y por qué)

Hay tres categorías de soluciones, y normalmente necesitas al menos dos:

  1. Haz que TRIM ocurra realmente (periódico o continuo), de extremo a extremo a través de la pila.
  2. Dale al SSD espacio para respirar (evita vivir cerca del 100% de uso; reduce churn en volúmenes “calientes”).
  3. Deja de complicar la GC (elecciones de workload y sistema de archivos, sensatez en colas, evitar capas patológicas).

Solución 1: Habilitar y verificar fstrim periódico (el predeterminado que deberías querer)

En Ubuntu 24.04, TRIM periódico suele habilitarse vía fstrim.timer. Quieres que esté habilitado y que reporte trims distintos de cero a lo largo del tiempo en sistemas que borran/sobrescriben datos.

cr0x@server:~$ sudo systemctl enable --now fstrim.timer
Created symlink /etc/systemd/system/timers.target.wants/fstrim.timer → /usr/lib/systemd/system/fstrim.timer.

Verifícalo:

cr0x@server:~$ systemctl list-timers --all | grep fstrim
Mon 2026-01-05 00:28:14 UTC  5 days left Mon 2025-12-29 00:28:14 UTC  1 day ago fstrim.timer  fstrim.service

Luego verifica la salida:

cr0x@server:~$ sudo journalctl -u fstrim.service --since "14 days ago" --no-pager | tail -n 20
Dec 29 00:28:14 server fstrim[32107]: /: 112.7 GiB (121011388416 bytes) trimmed on /dev/mapper/vg0-root

Si siempre recorta 0 B, no te felicites. Estás recortando aire.

Solución 2: Asegurar que los discards pasen por dm-crypt (LUKS) si usas cifrado

dm-crypt bloquea discards por defecto por buenas razones: los discards pueden filtrar información sobre qué bloques están en uso. Muchos entornos de producción aceptan ese intercambio porque el rendimiento y la latencia predecible importan más que ocultar patrones de asignación.

Qué hacer: Añade discard en /etc/crypttab (o asegúrate de que esté presente) y luego reinicia o vuelve a abrir los mapeos durante una ventana de mantenimiento. Después, confirma que /sys/block/dm-*/queue/discard_max_bytes es distinto de cero.

La verificación es innegociable: si dm sigue anunciando 0, el SSD todavía no te oye.

Solución 3: Preferir fstrim periódico sobre la opción de montaje discard (la mayoría de las veces)

La opción de montaje discard emite discards continuamente cuando se liberan bloques. Puede ser útil en algunas cargas con churn constante, pero también puede añadir sobrecarga, especialmente en sistemas de archivos con muchas pequeñas eliminaciones, y puede interactuar mal con ciertas implementaciones de dispositivo.

Mi valor por defecto con opinión:

  • Usa fstrim periódico para ext4/xfs en servidores.
  • Considera discard continuo solo si:
    • has medido que fstrim periódico no es suficiente, y
    • tu carga tiene churn constante y SLOs de latencia estrictos, y
    • has validado la sobrecarga en carga.

Solución 4: Dejar de operar SSDs “casi llenos”

Esto suena a un problema de presupuesto, pero es un problema de ingeniería con disfraz de presupuesto.

  • En volúmenes con muchas escrituras, apunta a 15–30% de espacio libre como buffer operativo.
  • Evita volúmenes raíz monolíticos que lo contienen todo. Separa rutas de escritura “calientes” en volúmenes dedicados donde puedas gestionar espacio y comportamiento de trim.
  • Si usas thin provisioning, monitoriza la utilización del pool como si fuera rotación de pager: porque lo es.

Solución 5: Permitir que el disco tenga inactividad ocasionalmente (sí, en serio)

Muchos SSDs realizan GC en segundo plano más eficazmente cuando tienen tiempo ocioso. Esto no sustituye a TRIM, pero puede reducir la severidad de los picos de latencia.

Si tu servidor está al máximo 24/7 con escrituras constantes, fuerzas a la GC a ocurrir en primer plano. Puedes mitigar suavizando ráfagas de escritura (agregación en la aplicación, colas) o escalando para que cada disco tenga tiempo de respirar.

Solución 6: Alinear sistemas de archivos y pilas con la semántica de discard

Algunas configuraciones complican el discard:

  • Thin pools de LVM: los discards pueden necesitar soporte explícito. La provisión fina más churn intenso es un clásico “parece bien hasta que no”.
  • Snapshots por todas partes: los snapshots retienen bloques antiguos, lo que significa que tus eliminaciones no liberan espacio desde la perspectiva de la capa inferior. Trim puede no reflejar el espacio realmente recuperable.
  • Discos virtualizados: los discards podrían ser ignorados o retrasados. Tu huésped puede hacer todo bien y aun así no influir en el medio físico.

Broma #2: Las pilas de almacenamiento son como lasañas—cada capa extra las hace más sabrosas hasta que te das cuenta de que estás depurando queso.

Tres mini-historias corporativas (anonimizadas, plausibles y técnicamente precisas)

Mini-historia 1: El incidente provocado por una suposición equivocada

Migraron una flota de servidores Ubuntu de SSDs SATA a NVMe relucientes. La migración fue suave y las primeras semanas fueron gloriosas. La latencia bajó, los paneles estaban tranquilos y todos se felicitaron en el canal de chat exclusivo para felicitaciones.

Seis semanas después empezaron las alertas: la p99 de latencia de escritura de la base de datos se disparaba en horas pico. El on-call hizo la danza habitual—miró CPU, memoria, red, culpó al ORM y luego miró iostat esperando una confesión. Los NVMe mostraban alta utilización y largas esperas de escritura, pero nada “roto”. SMART estaba limpio. Así que escalaron instancias. Mejoró por un tiempo, luego volvió.

La suposición equivocada fue sutil: “NVMe es rápido, así que el housekeeping no importará”. No se dieron cuenta de que la nueva imagen usaba cifrado LUKS con ajustes por defecto y los discards estaban bloqueados. fstrim corría semanalmente y reportaba éxito, pero recortaba 0 bytes cada vez. Nadie lo notó porque “Finished successfully” es una línea que los humanos están entrenados a malinterpretar.

Cuando habilitaron discards a través de dm-crypt y verificaron que /sys/block/dm-*/queue/discard_max_bytes era distinto de cero, el trim semanal empezó a recortar espacio real. El siguiente periodo pico aún tuvo carga, pero la caída de latencia desapareció. El postmortem no fue “comprar discos más rápidos”. Fue “probar discard end-to-end en la imagen dorada”.

Mini-historia 2: La optimización que salió mal

Otra organización tenía una canalización de ingestión de logs que escribía continuamente: archivos pequeños, eliminaciones constantes, mucho churn de metadatos. Leyeron en algún sitio que montar con discard mantiene los SSDs felices. Así que empujaron un cambio para montar el volumen de logs con discard continuo. No lo midieron porque, y cito el tono, “es solo discard”.

En días, el rendimiento de ingestión bajó y el tiempo de sistema de CPU subió. El disco no parecía saturado por ancho de banda, pero la latencia se volvió más ruidosa. Habían movido efectivamente el trabajo de discard al camino caliente: discards diminutos constantes, comandos extra al dispositivo constantes y más sobrecarga por eliminación. El SSD era informado miles de veces por segundo sobre espacio libre, como un compañero que narra cada pulsación de tecla.

Revirtieron a fstrim periódico y planificaron el recorte fuera de pico. El rendimiento volvió, la CPU se calmó y el SSD seguía recibiendo la información necesaria—solo en lotes donde la sobrecarga se amortizaba.

La lección: discard continuo no es malvado, pero depende de la carga. Si lo activas por política en todas partes, no estás afinando; estás esperando.

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

Un equipo de pagos tenía una costumbre poco glamurosa: cada cambio relacionado con almacenamiento requería una lista de verificación de “demuéstralo”. No un documento para auditores, sino un ritual de ingeniería real. Medían la latencia de escritura p95/p99 con un perfil sintético de fio que reproducía su patrón de base de datos. Lo registraban antes de los cambios, después y de nuevo dos semanas más tarde.

Cuando pasaron a Ubuntu 24.04, los números estaban bien el día uno. Dos semanas después, el benchmark programado mostró que la latencia de cola aumentaba. Aún no era catastrófico, pero la tendencia era mala. Porque esto se detectó por medición rutinaria, tuvieron tiempo para investigar sin un incidente activo.

Descubrieron que se había usado un nuevo diseño LVM thin-provisioned por conveniencia. Los discards desde el sistema de archivos no reclamaban espacio en el thin pool como se esperaba y el pool se estaba calentando. Ajustaron el diseño (lo simplificaron para el volumen de base de datos), aseguraron que fstrim periódico funcionara y aplicaron un presupuesto de espacio libre. Sin heroicidades ni páginas a medianoche.

Nada de esa historia es emocionante. Ese es el punto. La práctica aburrida—medir ahora, medir después—los salvó de un tipo emocionante de problema de almacenamiento.

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

Esta sección es la cicatriz acumulada. Empareja tu síntoma con una causa probable y luego verifica con las tareas anteriores.

1) fstrim se ejecuta “con éxito” pero siempre recorta 0 bytes

  • Síntoma: el journal muestra /: 0 B trimmed semana tras semana.
  • Causa raíz: Discards bloqueados por dm-crypt, LVM, ajustes de thin pool, o el dispositivo backend los ignora.
  • Solución: Revisa /sys/block/*/queue/discard_max_bytes para el dispositivo fuente real. Habilita discards en crypttab, confirma que dm anuncia discard, vuelve a ejecutar fstrim -av.

2) El rendimiento mejora tras reiniciar, luego decae

  • Síntoma: folklore de “reiniciar lo arregla”, repitiéndose cada pocas semanas.
  • Causa raíz: El disco tuvo tiempo ocioso o las condiciones de cola cambiaron; el problema subyacente es falta de TRIM o estado crónico casi lleno causando GC en carga.
  • Solución: Prueba con fio antes/después de un trim manual; habilita trim periódico; mantiene espacio libre.

3) NVMe parece sano, pero la p99 de escritura es terrible

  • Síntoma: SMART bien, sin errores de medios, pero picos de latencia en cola.
  • Causa raíz: GC en primer plano por insuficientes bloques limpios; amplificación de escritura; dispositivo en alta utilización con carga mixta.
  • Solución: Asegura TRIM efectivo; reduce el nivel de llenado; considera separar cargas (logs vs DB); verifica colas y ajustes del scheduler.

4) Discard continuo habilitado y el rendimiento empeoró

  • Síntoma: Aumenta tiempo de sistema de CPU, baja el throughput, latencia más ruidosa en cargas con muchas eliminaciones.
  • Causa raíz: Sobrecarga de discard en el camino caliente; demasiados discards pequeños.
  • Solución: Quita la opción de montaje discard; usa fstrim.timer periódico; programa trims fuera de pico.

5) TRIM funciona en bare metal, no en VMs

  • Síntoma: El huésped ejecuta fstrim y reporta recortes, pero el dispositivo host sigue degradándose; o el huésped recorta 0 bytes.
  • Causa raíz: El hipervisor/almacenamiento de respaldo no propaga discards; el tipo de disco virtual no lo soporta; comportamiento del proveedor cloud.
  • Solución: Verifica soporte de discard en la capa de virtualización. Si no se propagan, usa mecanismos de reclaim en el host o acepta que necesitas capacidad extra y reprovisionado periódico.

6) La provisión fina llega a su límite

  • Síntoma: El thin pool o dispositivo de respaldo se llena, el rendimiento cae, trims no parecen liberar espacio.
  • Causa raíz: Discards no pasados al thin pool, snapshots fijan bloques, o pool sobrecomprometido y poco vigilado.
  • Solución: Valida ajustes de discard en thin; reduce la retención de snapshots; monitoriza data% del pool como un SLO de primera clase; mantiene espacio libre.

Listas de verificación / plan paso a paso

Este es el plan operativo que puedes pasar a la rotación on-call sin también darles el número de tu terapeuta.

Checklist A: Demostrar que el problema es TRIM/GC (30–90 minutos)

  1. Captura la latencia base del dispositivo durante el periodo “malo” (iostat -x y latencia p99 de la aplicación).
  2. Confirma la capacidad de discard en el dispositivo crudo (/sys/block/nvme*/queue/discard_max_bytes).
  3. Confirma la capacidad de discard en el dispositivo fuente del montaje (a menudo dm-*).
  4. Ejecuta sudo fstrim -av y registra bytes recortados por montaje.
  5. Ejecuta una prueba controlada con fio y registra percentiles p95/p99.
  6. Repite fio después de fstrim (y una breve ventana de inactividad) usando parámetros idénticos.
  7. Si la latencia de cola mejora materialmente: trata la ruta TRIM y el presupuesto de espacio libre como objetivo de corrección.

Checklist B: Hacer TRIM fiable (ventana de mantenimiento)

  1. Habilita fstrim.timer y verifica que esté programado.
  2. Asegura que /etc/crypttab incluya opciones de discard si usas LUKS y tu modelo de amenazas lo permite.
  3. Reinicia o reabre mapeos dm-crypt de forma segura según sea necesario.
  4. Confirma que /sys/block/dm-*/queue/discard_max_bytes sea distinto de cero.
  5. Ejecuta fstrim -av manualmente una vez y confirma trims distintos de cero.
  6. Rastrea logs semanales de fstrim y alerta si recorta 0 bytes repetidamente en volúmenes con churn.

Checklist C: Mantenerlo arreglado (higiene continua)

  1. Define objetivos de capacidad: mantén 15–30% de espacio libre en volúmenes con muchas escrituras.
  2. Separa cargas con muchas escrituras en volúmenes/discos cuando sea factible.
  3. Registra un perfil estándar de fio para tu entorno y ejecútalo mensualmente (o tras cambios de kernel/almacenamiento).
  4. Monitorea NVMe SMART: temperatura, advertencias críticas, errores de medios, percentage_used.
  5. Monitorea percentiles de latencia, no solo throughput y await medio.

Preguntas frecuentes

1) ¿Por qué el rendimiento de SSD/NVMe se degrada con el tiempo?

Porque la flash requiere borrar antes de escribir a nivel de bloque. Cuando el SSD no encuentra bloques limpios, debe mover datos válidos (GC) antes de escribir. Sin TRIM, asume que más datos son válidos, aumentando la amplificación de escritura y los picos de latencia.

2) ¿No se supone que NVMe es “siempre rápido”?

NVMe es un protocolo e interfaz optimizada para paralelismo y baja sobrecarga. No cambia cómo funciona la NAND internamente. Una interfaz rápida puede entregar una caída más rápida desde la cima.

3) ¿Debería montar ext4 con discard en Ubuntu 24.04?

Por lo general no. Prefiere fstrim.timer periódico. Usa discard continuo solo tras realizar benchmarks y solo en volúmenes donde el patrón de eliminación y los requisitos de latencia lo justifiquen.

4) ¿Con qué frecuencia debo ejecutar fstrim?

Semanalmente es una buena configuración por defecto. Para cargas de alto churn, podrías ejecutarlo diariamente fuera de pico. Mide: si el rendimiento decae en días, recorta más seguido o arregla nivel de llenado y problemas de carga.

5) ¿TRIM funciona a través del cifrado LUKS?

Puedes hacerlo funcionar, pero solo si está habilitado. dm-crypt puede bloquear discards a menos que se configure (comúnmente mediante discard en /etc/crypttab). Habilitarlo puede filtrar patrones de asignación, así que decide según tu modelo de seguridad.

6) Ejecuté fstrim y recortó mucho. ¿Eso perjudica la vida útil del SSD?

TRIM en sí no escribe datos; informa al SSD que los bloques ya no son necesarios. Puede reducir la amplificación de escritura ayudando al SSD a limpiar más eficientemente. El mayor riesgo para la vida útil es la amplificación sostenida de escritura por operar casi lleno sin TRIM efectivo.

7) ¿Por qué fstrim muestra 0 bytes en un servidor activo donde borramos datos diariamente?

Razones comunes: discards bloqueados en dm-crypt/LVM; provisión fina o snapshots mantienen bloques “en uso”; el backend ignora discards (algunos discos virtuales); o tu carga sobrescribe en sitio sin liberar extentos de forma que genere espacio recortable.

8) ¿Puedo “resetear” el SSD para restaurar rendimiento?

Algunos discos soportan secure erase o formateos que devuelven el dispositivo a un estado como nuevo, pero eso es destructivo. Operativamente, el enfoque no destructivo es: asegurar que TRIM funcione, mantener espacio libre y evitar apilar capas que bloqueen discards.

9) Mi disco muestra solo 3% usado (SMART percentage_used), ¿por qué está lento?

percentage_used en SMART es desgaste, no ocupación. Puedes tener un disco casi nuevo con rendimiento terrible si se mantiene con alto llenado lógico, con escrituras constantes, sin TRIM efectivo y mucha GC interna.

10) ¿Necesito cambiar el scheduler de I/O para NVMe en Ubuntu 24.04?

A menudo no; los kernels modernos usan valores razonables por defecto (comúnmente none para NVMe). Los ajustes de scheduler no compensarán un disco forzado a GC en primer plano. Arregla discard y espacio libre primero, luego ajusta si es necesario.

Conclusión: próximos pasos prácticos

Si tu SSD/NVMe en Ubuntu 24.04 se vuelve más lento con el tiempo, trátalo como un problema de ingeniería, no como folclore. Prueba la hipótesis con mediciones antes/después: mismo trabajo de fio, mismo dispositivo, con y sin un trim exitoso. Si la latencia de cola mejora tras el trim, deja de debatir y arregla la ruta de discard de extremo a extremo.

Próximos pasos que merece la pena hacer en este orden:

  1. Revisa la cadena de discard: soporte de discard en NVMe crudo, luego en el dispositivo dm, luego la salida de fstrim.
  2. Haz fiable fstrim: habilita el temporizador, confirma trims distintos de cero con el tiempo, alerta si no hace nada.
  3. Arregla el problema estructural: deja de operar volúmenes de escritura caliente al 95–99% de ocupación; es un impuesto de latencia autoimpuesto.
  4. Guarda recibos: almacena un perfil base de fio y vuelve a ejecutarlo tras upgrades, cambios de imagen y modificaciones de la pila de almacenamiento.

El disco seguirá haciendo recolección de basura. Tu trabajo es mantenerla en segundo plano, donde pertenece.

← Anterior
Errores de checksum ZFS en Proxmox: disco o cable — cómo demostrarlo
Siguiente →
WordPress cron no funciona: por qué fallan las publicaciones programadas y cómo solucionarlo

Deja un comentario