Debian 13: TRIM no se ejecuta — Habilitar el temporizador fstrim y verificar que funciona

¿Te fue útil?

Instalaste Debian 13, pasaste a SSDs (o NVMe) y esperabas que el sistema se mantuviera limpio en segundo plano. Luego el rendimiento se vuelve algo “pegajoso”, las cifras de desgaste del disco parecen peor de lo esperado, o notas que fstrim nunca se ejecutó. Clásico.

TRIM es una de esas tareas de mantenimiento que solo echas de menos cuando falta—como las copias de seguridad, hasta que las necesitas y no están. Hagamos que Debian 13 ejecute TRIM según lo programado, demostremos que realmente hace algo y solucionemos las trampas comunes donde el comando parece tener éxito pero la pila de almacenamiento ignora la petición.

Qué es TRIM (y qué no es)

TRIM es el sistema operativo indicándole al almacenamiento en estado sólido qué bloques ya no contienen datos útiles. Eso suena mundano hasta que recuerdas cómo funcionan los SSD: la memoria flash no puede sobrescribir en el lugar; escribe nuevas páginas en otros sitios y luego borra bloques antiguos en trozos mayores. Si la unidad no sabe que un bloque está libre, puede mantenerlo como “tal vez todavía en uso”, lo que aumenta la amplificación de escritura, reduce el rendimiento sostenido en escrituras y puede incrementar el desgaste.

En Linux, te encontrarás con TRIM mediante dos mecanismos:

  • TRIM periódico: fstrim recorre los sistemas de archivos montados y envía operaciones de discard para el espacio libre. Debian normalmente lo programa semanalmente mediante un temporizador de systemd.
  • Discard continuo: la opción de montaje discard (o variantes específicas del sistema de archivos) emite discards conforme se liberan bloques.

Usa TRIM periódico a menos que tengas una razón fuerte para no hacerlo. El discard continuo puede funcionar bien, pero también puede añadir latencia en cargas con muchas escrituras y tiende a complicar la depuración del rendimiento. TRIM periódico es aburrido. Lo aburrido es bueno.

TRIM tampoco es un botón mágico para “hacer mi SSD rápido”. Si tu cuello de botella son lecturas aleatorias a profundidad de cola 1, TRIM no te salvará. Si tu problema es que el host de la VM miente sobre soporte de discard, TRIM tampoco arreglará eso.

Una cita que vale la pena mantener en tu cuaderno mental: Werner Vogels (CTO de Amazon) dijo, “Todo falla, todo el tiempo.” (idea parafraseada). El almacenamiento está incluido. Asume que fallará—luego verifica.

Datos interesantes y contexto (para quienes gustan de saber por qué)

  • Dato 1: El comando SATA TRIM se introdujo como parte de los estándares ATA alrededor del momento en que los SSD se hicieron mainstream; antes de eso, las unidades tenían que adivinar qué datos estaban obsoletos.
  • Dato 2: En NVMe, el equivalente se llama Dataset Management / Deallocate, pero Linux sigue tratándolo bajo el paraguas de “discard”.
  • Dato 3: Los primeros SSD a veces manejaban mal TRIM. Algunas versiones de firmware trataban los discards tan mal que los administradores los desactivaron en flotas enteras durante años por pura autodefensa.
  • Dato 4: Los sistemas de archivos no “necesitan” TRIM para funcionar. Lo necesitan para evitar que la recolección de basura del SSD se convierta en un impuesto silencioso de rendimiento.
  • Dato 5: La mayoría de las distribuciones Linux modernas pasaron de discard siempre activo a fstrim programado porque es más fácil de razonar y a menudo más rápido en conjunto.
  • Dato 6: El almacenamiento thin-provisioned (LVM thin, discos virtuales, LUNs SAN) puede recuperar capacidad en capas superiores con discard—si cada capa coopera. Una capa dice “no” y seguirás pagando por bloques que borraste hace meses.
  • Dato 7: dm-crypt históricamente tenía por defecto no pasar discards porque los discards pueden filtrar información sobre qué bloques están en uso. Puedes optar por permitirlo.
  • Dato 8: Muchos controladores RAID y algunas pilas de device-mapper solían descartar por completo las peticiones de discard. Los kernels modernos son mejores, pero “mejor” no es “garantizado”.

Broma #1: TRIM es como limpiar tu escritorio—nadie nota cuando lo haces, pero todos notan cuando no lo haces.

Guía rápida de diagnóstico (comprueba esto primero)

Si TRIM “no se está ejecutando”, en realidad estás depurando una de tres cosas: programación, permisos/unidades, o soporte de discard a través de la pila de almacenamiento. No intentes solucionarlo todo a la vez. Comprueba en este orden:

1) ¿Está el temporizador habilitado y disparando?

  • Comprueba que fstrim.timer esté habilitado y tenga una próxima ejecución.
  • Revisa cuándo se ejecutó por última vez y si tuvo éxito.

2) ¿Funciona fstrim -av manualmente?

  • Si el trim manual falla: no es un problema de programación. Es soporte, opciones de montaje o la pila de dispositivos.
  • Si el trim manual funciona pero el temporizador no: es el estado de la unidad systemd, enmascarado, o problemas de reloj/temporizador.

3) ¿El dispositivo de bloque anuncia soporte de discard?

  • Usa lsblk -D (granularidad de discard/máx bytes) y comprobaciones de blkdiscard.
  • Para LUKS/LVM/RAID/VMs, valida que cada capa pase los discards.

4) ¿Estás haciendo trim de lo correcto?

  • fstrim solo recorta sistemas de archivos montados. Si tu montaje importante no está montado cuando corre el temporizador (raro, pero ocurre), no se recortará.
  • Algunos sistemas de archivos u opciones de montaje pueden deshabilitar discard por completo.

Tareas prácticas: comandos, salida esperada y qué decides

Esta es la sustancia. Cada tarea incluye: un comando, lo que significa la salida y la decisión que tomas a continuación. Ejecuta estas acciones como root o con sudo según se indica.

Task 1: Confirmar que Debian ve tus discos como con capacidad de discard

cr0x@server:~$ lsblk -D -o NAME,MODEL,ROTA,DISC-GRAN,DISC-MAX,DISC-ZERO
NAME        MODEL               ROTA DISC-GRAN DISC-MAX DISC-ZERO
nvme0n1     Samsung SSD 980      0      4K       2T         0
sda         ST1000DM010-2EP1     1      0B       0B         0

Significado: Que DISC-GRAN y DISC-MAX sean distintos de cero indica que el dispositivo declara soporte de discard. Los discos rotacionales (ROTA=1) suelen mostrar 0B porque TRIM es para medios tipo SSD.

Decisión: Si tu SSD/NVMe muestra 0B/0B, deja de culpar a systemd. Probablemente tengas una capa bloqueando el discard (dm-crypt, RAID, tipo de disco virtual) o un dispositivo que realmente no lo soporta.

Task 2: Comprobar el estado del temporizador fstrim

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-29 09:10:12 UTC; 3h ago
    Trigger: Sun 2026-01-04 00:24:31 UTC; 4 days left
   Triggers: ● fstrim.service

Significado: Habilitado + activo (waiting) con una próxima ejecución es lo que deseas. Si dice disabled, inactive, masked, o no tiene trigger, no se ejecutará.

Decisión: Si está deshabilitado, habilítalo. Si está activo pero nunca se dispara, inspecciona temporizadores y logs (tareas siguientes).

Task 3: Listar temporizadores y verificar que fstrim esté programado

cr0x@server:~$ systemctl list-timers --all | grep -E 'fstrim|NEXT|LAST'
Sun 2026-01-04 00:24:31 UTC  4 days left Sun 2025-12-28 00:22:09 UTC  1 day ago  fstrim.timer  fstrim.service

Significado: Obtienes un NEXT y un LAST. Si LAST es “n/a”, nunca se ejecutó. Si NEXT es “n/a”, no se ejecutará.

Decisión: Si nunca se ejecutó, ejecútalo manualmente y lee los logs. Si se ejecutó pero recorta 0 bytes siempre, puedes tener una capa upstream que ignora los discards—o simplemente no hay espacio libre nuevo para recortar.

Task 4: Ver si el servicio fue invocado y qué hizo

cr0x@server:~$ systemctl status fstrim.service
● fstrim.service - Discard unused blocks on filesystems from /etc/fstab
     Loaded: loaded (/usr/lib/systemd/system/fstrim.service; static)
     Active: inactive (dead) since Sun 2025-12-28 00:22:12 UTC; 1 day ago
TriggeredBy: ● fstrim.timer
       Docs: man:fstrim(8)
    Process: 2021 ExecStart=/sbin/fstrim --fstab --verbose --quiet (code=exited, status=0/SUCCESS)
   Main PID: 2021 (code=exited, status=0/SUCCESS)

Significado: El estado 0/SUCCESS significa que se ejecutó. “inactive (dead)” es normal después de que un servicio oneshot finaliza.

Decisión: Si ves códigos de fallo, ve al journal. Si es exitoso, verifica los bytes recortados y la ruta del discard.

Task 5: Leer el journal para detalles de fstrim

cr0x@server:~$ journalctl -u fstrim.service -n 50 --no-pager
Dec 28 00:22:09 server systemd[1]: Starting fstrim.service - Discard unused blocks on filesystems from /etc/fstab...
Dec 28 00:22:09 server fstrim[2021]: /: 18.7 GiB (20068429824 bytes) trimmed on /dev/nvme0n1p2
Dec 28 00:22:12 server systemd[1]: fstrim.service: Deactivated successfully.
Dec 28 00:22:12 server systemd[1]: Finished fstrim.service - Discard unused blocks on filesystems from /etc/fstab.

Significado: Esta es tu prueba. Muestra qué puntos de montaje se recortaron y cuánto.

Decisión: Si solo lista algunos sistemas de archivos, revisa /etc/fstab y el estado de los montajes. Si recorta 0 bytes repetidamente, valida soporte de discard; puede estar bloqueado o no haber nada nuevo que descartar.

Task 6: Ejecutar fstrim manualmente en todos los sistemas de archivos montados

cr0x@server:~$ sudo fstrim -av
/: 18.7 GiB (20068429824 bytes) trimmed on /dev/nvme0n1p2
/var: 2.1 GiB (2254857830 bytes) trimmed on /dev/nvme0n1p3

Significado: -a significa “todos los sistemas montados que lo soportan”; -v muestra lo ocurrido. Si ves “Operation not supported,” tienes un problema de pila o limitación del sistema de archivos.

Decisión: Si el manual funciona pero el temporizador no, céntrate en systemd. Si falla manualmente, céntrate en la pila de almacenamiento y los montajes.

Task 7: Comprobar qué sistemas de archivos son elegibles (montados y en fstab)

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

Significado: Muestra opciones de montaje y sistema de archivos. Con TRIM periódico, no necesitas la opción de montaje discard.

Decisión: Si usas discard y persigues picos de latencia, considera eliminarla y confiar en el temporizador.

Task 8: Confirmar que fstrim considerará el sistema de archivos (filtro fstab)

cr0x@server:~$ grep -vE '^\s*#|^\s*$' /etc/fstab
UUID=8c2b1f2a-6a3f-4ad4-9b7f-3d2b0b7b6f12 /     ext4 defaults,errors=remount-ro 0 1
UUID=0f3f0c1a-27ae-4f1c-a90f-8b0b7fe1f5c1 /var  ext4 defaults                  0 2

Significado: El fstrim.service de Debian suele ejecutar fstrim --fstab, lo que significa que usa las entradas de fstab en lugar de “lo que esté montado”. Si montas algo manualmente que no está en fstab, puede que nunca lo recorte el temporizador.

Decisión: Si un montaje debe ser recortado, agrégalo a fstab o ajusta tu estrategia de trim.

Task 9: Verificar que el temporizador no esté enmascarado ni anulado

cr0x@server:~$ systemctl is-enabled fstrim.timer
enabled

Significado: “masked” significa que alguien lo deshabilitó de forma que sobrevive a intentos de habilitación.

Decisión: Si está enmascarado, desmáscara y habilita (se muestra más adelante). Si está deshabilitado, habilita.

Task 10: Comprobar si hay overrides de la unidad systemd que cambien el comportamiento

cr0x@server:~$ systemctl cat fstrim.service
# /usr/lib/systemd/system/fstrim.service
[Unit]
Description=Discard unused blocks on filesystems from /etc/fstab
Documentation=man:fstrim(8)

[Service]
Type=oneshot
ExecStart=/sbin/fstrim --fstab --verbose --quiet

Significado: Si ves secciones extra bajo /etc/systemd/system/fstrim.service.d/, puedes tener un override. Los overrides son poderosos y también una gran forma de confundir al Tú del futuro.

Decisión: Si está anulado, confirma que todavía recorta lo que esperas y que la salida/log no está suprimida hasta volverse invisible.

Task 11: Validar soporte de discard a través de dm-crypt (LUKS)

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

Significado: Esto no dice directamente si discard está habilitado. Para eso, normalmente revisas tu /etc/crypttab o la tabla de device-mapper. Pero ver dm-crypt en la ruta es una pista: los discards pueden estar bloqueados a menos que se permitan explícitamente.

Decisión: Si usas LUKS y quieres TRIM, planea habilitar discards deliberadamente (con comprensión completa de las compensaciones de filtrado de metadatos).

Task 12: Confirmar límites de discard en nodos de device-mapper

cr0x@server:~$ lsblk -D -o NAME,TYPE,DISC-GRAN,DISC-MAX /dev/mapper/cryptroot
NAME     TYPE DISC-GRAN DISC-MAX
cryptroot crypt     4K       2T

Significado: Si el mapeo dm-crypt informa capacidad de discard, la ruta al menos es plausible. Si informa 0B/0B, los discards están siendo bloqueados en esa capa.

Decisión: 0B/0B aquí: corrige las opciones de crypttab o acepta “sin TRIM” para ese volumen.

Task 13: Validar que el sistema de archivos soporte trimming

cr0x@server:~$ df -T /
Filesystem     Type  1K-blocks      Used Available Use% Mounted on
/dev/nvme0n1p2 ext4  960379552 302118912 609136192  34% /

Significado: ext4, xfs, btrfs generalmente soportan TRIM. Algunos sistemas de archivos raros o antiguos pueden no soportarlo, o pueden requerir opciones específicas.

Decisión: Si estás en algo exótico, verifica soporte y expectativas. Si estás en ext4/xfs/btrfs y los discards fallan, probablemente esté más abajo del sistema de archivos.

Task 14: Comprobar si estás dentro de una VM que no pasa discards

cr0x@server:~$ systemd-detect-virt
kvm

Significado: Estar virtualizado no prohíbe TRIM, pero significa que ahora necesitas que el hipervisor y el tipo de disco virtual estén configurados para pasar discard/unmap.

Decisión: Si esto es una VM, coordina con el equipo de plataforma (o contigo mismo, si eres quien lleva esa responsabilidad) para habilitar discard/unmap end-to-end.

Task 15: Simular si los discards son rechazados en la capa de bloque

cr0x@server:~$ sudo blkdiscard -v -n /dev/nvme0n1p2
blkdiscard: /dev/nvme0n1p2: 0 bytes were discarded

Significado: -n es una simulación en muchos sistemas (no descarta realmente). Esto comprueba que existe la ruta ioctl. Si recibes “Operation not supported,” la pila del kernel no acepta discards para ese dispositivo.

Decisión: Si no está soportado aquí, fstrim no puede hacerlo. Arregla la capa subyacente, o deja de intentarlo.

Task 16: Confirmar que el temporizador realmente se disparó cuando crees que lo hizo (tiempo y ejecuciones perdidas)

cr0x@server:~$ systemctl show -p LastTriggerUSec,LastTriggerUSecMonotonic fstrim.timer
LastTriggerUSec=Sun 2025-12-28 00:22:09 UTC
LastTriggerUSecMonotonic=120394889230

Significado: Confirma la última hora de disparo. Útil cuando sospechas ejecuciones perdidas tras suspensión, downtime o saltos de reloj.

Decisión: Si el temporizador no se está disparando, investiga el comportamiento de los timers de systemd, el reloj del sistema y si la unidad está inhibida.

Habilitar el temporizador fstrim en Debian 13 (la forma correcta)

En Debian con systemd, quieres el temporizador, no un trabajo cron aleatorio que encontraste en un post de 2014. El temporizador se integra con el registro del servicio, dependencias y gestión uniforme. También hace que las auditorías sean menos dolorosas.

Habilitar y arrancar el temporizador

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

Significado: Habilitado para el arranque e iniciado inmediatamente. A partir de ahora, Debian debería ejecutar TRIM semanalmente automáticamente.

Decisión: Si gestionas flotas, incorpora esto en tu baseline (Ansible, Salt, lo que uses). No confíes en que “alguien lo recordará”.

Si está enmascarado, desmárcalo

cr0x@server:~$ sudo systemctl unmask fstrim.timer
Removed "/etc/systemd/system/fstrim.timer".

Significado: Enmascarar es la opción de “realmente deshabilitado”. Desmarcar quita el bloqueo fuerte.

Decisión: Si estaba enmascarado, averigua por qué. El enmascaramiento suele ser una cicatriz de un incidente, una postura de seguridad o un ajuste mal informado.

Forzar una ejecución ahora (sin esperar una semana)

cr0x@server:~$ sudo systemctl start fstrim.service

Significado: No mostrar salida es normal; revisa el journal para resultados.

Decisión: Verifica siempre los bytes recortados en los logs. Una “ejecución exitosa” que no recortó nada aún puede indicar un problema.

Ajustar la programación (con cuidado)

El semanal por defecto está bien para la mayoría de servidores. Si ejecutas grandes bases de datos con churn agresivo, podrías querer recortar con más frecuencia—pero no lo supongas. Mide. El recorte excesivamente frecuente suele ser inofensivo en discos modernos, pero puede convertirse en ruido de fondo en perfiles de rendimiento.

Si debes cambiar la programación, usa un override de systemd para el temporizador, no edites las unidades del proveedor. Ejemplo: ajustarlo para que se ejecute diariamente a una hora predecible.

cr0x@server:~$ sudo systemctl edit fstrim.timer

Luego añade un override como este (el editor de systemd se abrirá):

cr0x@server:~$ cat /etc/systemd/system/fstrim.timer.d/override.conf
[Timer]
OnCalendar=daily
RandomizedDelaySec=1h
Persistent=true

Significado: RandomizedDelaySec evita que todos los servidores de una flota recorten al mismo minuto. Persistent=true significa que si la máquina estuvo apagada a la hora programada, systemd ejecutará el trabajo perdido en el siguiente arranque.

Decisión: Para flotas, mantiene la aleatorización. Si quieres “exactamente 02:00”, acepta que puedes crear una pequeña avalancha auto-infligida.

cr0x@server:~$ sudo systemctl daemon-reload
cr0x@server:~$ sudo systemctl restart fstrim.timer

Verificar que TRIM funciona de extremo a extremo (la parte que la gente omite)

Aquí está la verdad incómoda: ver que fstrim informe “X GiB trimmed” es bueno, pero no suficiente en todos los entornos. En una VM, LUN thin, SAN o una configuración en capas de device-mapper, te importa si los discards se propagan al almacenamiento físico real.

Verificar desde el sistema de archivos hacia afuera

Empieza con la salida de fstrim -av y las entradas del journal. Si muestran bytes recortados y sin errores, el sistema de archivos está emitiendo discards.

Luego verifica que el dispositivo de bloque realmente soporte discard usando lsblk -D. Quieres valores no nulos en la capa más baja relevante (dispositivo físico NVMe/SATA) y en la capa mapeada que estás recortando (volúmenes LUKS/LVM).

Saber qué significa realmente “0 bytes trimmed”

Cero bytes recortados puede ser perfectamente normal. Si ejecutaste trim ayer y no cambió nada, no hay nada que descartar. También puede significar:

  • el sistema de archivos no soporta TRIM,
  • el dispositivo no soporta discard,
  • el discard está bloqueado por una capa intermedia,
  • estás recortando un montaje que no está respaldado por almacenamiento SSD.

Verificar que la programación realmente se ejecuta cuando la máquina está “encendida”

Portátiles, servidores de laboratorio y nodos de borde son notorios: se apagan de noche, duermen los fines de semana y sus temporizadores nunca se disparan. Por eso existe Persistent=true—úsalo cuando sea apropiado.

Broma #2: Si tu temporizador solo se ejecuta cuando el servidor está apagado, felicitaciones—has inventado la ventana de mantenimiento de Schrödinger.

Dónde muere TRIM: cifrado, LVM, RAID, SAN y VMs

TRIM es una petición que debe sobrevivir un viaje a través de múltiples componentes. Cada uno de ellos puede bloquearla por razones que van desde “predeterminado por seguridad” hasta “firmware del controlador de otra era geológica”. Aquí está cómo suele romperse y qué hacer al respecto.

LUKS/dm-crypt: seguridad vs recuperación

dm-crypt puede pasar discards, pero normalmente necesitas optar por ello. El riesgo: los discards pueden revelar qué bloques están en uso, lo cual es una forma de filtrado de metadatos. En muchos modelos de amenaza (la mayoría de salas de servidores), eso es aceptable. En otros (algunos portátiles, entornos de alto riesgo), no lo es.

En Debian, habilitar discards para una raíz cifrada a menudo implica añadir discard a la entrada relevante en /etc/crypttab, luego reconstruir initramfs y reiniciar. No hagas esto a la ligera en producción sin entender tu cadena de arranque y ruta de recuperación.

cr0x@server:~$ sudo grep -vE '^\s*#|^\s*$' /etc/crypttab
cryptroot UUID=2d4f1f67-8f5f-4a4b-9a0e-2c6d52f9c5a1 none luks,discard

Significado: La opción discard indica a dm-crypt que pase las peticiones de discard hacia abajo. Sin ella, los dispositivos mapeados a menudo muestran 0B de discard en lsblk -D.

Decisión: Decide según el modelo de amenaza. Si lo habilitas, verifica con lsblk -D tanto en la capa dm-crypt como en el dispositivo subyacente después del reinicio.

LVM (thick y thin)

El LVM clásico (thick) en SSD generalmente recorta bien siempre que el PV subyacente soporte discard y nada lo bloquee. LVM thin provisioning es donde debes tener especial cuidado: los discards pueden recuperar espacio en el thin pool, pero la configuración y el comportamiento del kernel importan.

Si tu objetivo es recuperar espacio en el thin pool (o en un SAN upstream), no solo estás “optimizando la salud del SSD”, estás haciendo gestión de capacidad. Valida toda la cadena.

mdadm RAID y RAID por hardware

El soporte de discard en RAID por software (md) ha mejorado con el tiempo, pero la capacidad depende del nivel RAID y del comportamiento del kernel. El RAID por hardware es otro universo: algunos controladores traducen discard correctamente; otros lo descartan. A veces la única forma de saberlo es probar y observar la recuperación de capacidad upstream.

Máquinas virtuales: el hipervisor debe cooperar

En entornos KVM/QEMU, el soporte de discard depende del tipo de disco virtual (virtio-scsi vs virtio-blk), de ajustes como “discard=unmap” y del almacenamiento de respaldo. En VMware, depende del soporte del invitado, del tipo de provisión del disco virtual y de si UNMAP está habilitado. En proveedores cloud, depende de lo que expongan.

El invitado puede estar perfectamente configurado y aun así gritar peticiones TRIM a un vacío si el host se niega a pasarlas.

Sistemas de archivos: matices de ext4, xfs, btrfs

  • ext4: TRIM periódico con fstrim es un patrón normal. La opción de montaje discard existe pero no es obligatoria.
  • xfs: También soporta fstrim. Funciona bien en sistemas de archivos grandes; el trim suele ser directo.
  • btrfs: Soporta discard y tiene sus peculiaridades. Muchos administradores aún prefieren fstrim periódico para mantener el comportamiento explícito.

Tres mini-historias corporativas desde el terreno

Incidente causado por una suposición errónea: “Estamos en SSD, así que TRIM debe estar activado”

Una empresa mediana migró un clúster de procesamiento por lotes de SSDs SATA antiguos a NVMe nuevos. Hicieron la migración de la manera “sensata”: imágenes del SO construidas una vez, desplegadas en todas partes, y almacenamiento gestionado por un layout estándar cifrado LVM. Todos asumieron que el rendimiento mejoraría automáticamente.

Al principio fue así. Luego, en unas semanas, los nodos con muchas escrituras empezaron a mostrar tiempos de trabajo más largos. Nada dramático, solo lo suficiente para incumplir ocasionalmente los SLO internos. Los gráficos parecían una marea lenta, no un cliff abrupto. Esos son los peores.

El equipo persiguió los sospechosos habituales: vecinos ruidosos, actualizaciones del kernel, jitter de red, regresiones a nivel de aplicación. Un ingeniero atento finalmente ejecutó lsblk -D y notó que la capa dm-crypt reportaba 0B de discard. fstrim manual “funcionaba” en algunos montajes pero recortaba cantidades minúsculas. Las unidades realizaban garbage collection sin que alguien les dijera qué estaba libre. La amplificación de escritura subió y el rendimiento sostenido cayó.

La solución no fue exótica: habilitaron explícitamente los discards para los volúmenes cifrados (tras una revisión de seguridad) y verificaron los bytes recortados en journald semanalmente. El rendimiento se estabilizó. La lección mayor: “SSD” no es una configuración. Es un hecho de hardware. La pila de software aún necesita que le digas lo que quieres.

Después añadieron una comprobación de baseline: si un montaje respaldado por SSD reporta 0B de discard en la capa mapeada, el nodo falla la readiness. Molesto, pero les salvó de repetir el mismo error en el siguiente entorno.

Optimización que salió mal: habilitar discard continuo en todas partes

Otra organización tenía una filosofía simple: “Si discard es bueno, más discard es mejor.” Activaron la opción discard de montaje en toda la flota, incluidos servidores de bases de datos y algunos boxes de ingestión de logs que machacaban el sistema de archivos con pequeñas escrituras y borrados.

El efecto fue sutil al principio. Los percentiles de latencia subieron, especialmente durante picos de ingestión. No consistentemente—solo lo suficiente como para hacer noches de on-call picantes. El equipo vio aumento en I/O wait pero no lo podía mapear claramente a cambios de aplicación.

Eventualmente alguien correlacionó los picos con operaciones frecuentes de discard en trazas de la capa de bloque. El discard continuo añadía trabajo síncrono en momentos inoportunos, y el backend de almacenamiento tampoco estaba encantado con el constante ruido de unmap. La optimización se volvió jitter.

Revirtieron a fstrim periódico vía el temporizador systemd. El perfil de latencia se calmó y la recuperación todavía ocurría en un horario predecible. La moraleja: el mantenimiento predecible vence al comportamiento “inteligente” que ocurre en el peor momento posible.

Práctica aburrida pero correcta que salvó el día: registrar y verificar como rutina

Un equipo de servicios financieros ejecutaba Debian en NVMe cifrados, con mezcla de bare metal y VMs. Tenían una lista de verificación semanal estándar que incluía revisar la salud de timers de systemd y asegurarse de que un conjunto de servicios de mantenimiento estuviera en marcha. Sí, era aburrido. Sí, fue efectivo.

Una semana notaron que las entradas del journal de fstrim cambiaron: seguían “SUCCESS”, pero los bytes recortados cayeron a casi cero en varias VMs que normalmente recortaban unos gigabytes. No se dispararon alertas porque nada “falló”. Los humanos lo notaron porque lo estaban revisando.

Resultó que la plataforma de virtualización se había actualizado y un valor por defecto cambió: el discard/unmap ya no se pasaba a invitados para un subconjunto de tipos de disco. Los invitados seguían emitiendo discards; el host los ignoraba cortésmente. El almacenamiento thin-provisioned comenzó a inflarse y el equipo SAN iba a tener un mal mes.

Puesto que el equipo de ops lo detectó temprano, la solución fue limpia: actualizar la configuración del disco VM para permitir discard y validar usando trim a nivel de invitado más comprobaciones de recuperación de espacio en el host. Nada de compras de capacidad de emergencia, ni ventana de mantenimiento de fin de semana, ni reunión ejecutiva de “¿cómo lo pasamos por alto?”. La práctica aburrida pagó por sí misma silenciosamente, como la mayor parte del buen trabajo SRE.

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

1) “TRIM no se ejecuta” pero el temporizador está deshabilitado

Síntoma: systemctl status fstrim.timer muestra disabled/inactive; list-timers no tiene entrada de fstrim.

Causa raíz: El temporizador nunca se habilitó (o una imagen base lo deshabilitó hace mucho).

Solución: Habilita e inicia: systemctl enable --now fstrim.timer. Luego ejecuta systemctl start fstrim.service y revisa journalctl -u fstrim.service.

2) Temporizador habilitado, pero no pasa nada durante semanas

Síntoma: El temporizador está habilitado; LAST es “n/a” o muy antiguo; la máquina suele estar apagada/suspendida.

Causa raíz: El sistema no estuvo activo en la hora programada; el temporizador no es persistente.

Solución: Añade override al temporizador con Persistent=true. O prográmalo con más frecuencia y aleatorización.

3) fstrim manual falla con “Operation not supported”

Síntoma: sudo fstrim -av muestra errores; blkdiscard informa no soportado; lsblk -D muestra 0B de discard.

Causa raíz: El dispositivo o una capa (LUKS, RAID, hipervisor) no soporta/no pasa discard.

Solución: Identifica la capa que reporta 0B en lsblk -D. Habilita passthrough de discard (opciones de crypttab/hipervisor) o acepta no tener TRIM en esa ruta.

4) fstrim se ejecuta pero solo recorta “/” y se salta /var u otros montajes

Síntoma: El journal muestra trim para algunos montajes solamente.

Causa raíz: fstrim --fstab solo recorta montajes definidos en fstab; el montaje no está en fstab, o no está montado en tiempo de ejecución.

Solución: Pon el montaje en /etc/fstab (o ajusta tu unidad para usar -a sin --fstab, si realmente quieres “todo lo montado”). Asegúrate de que esté montado cuando el temporizador se ejecute.

5) “0 bytes trimmed” siempre, pero esperabas más

Síntoma: El trim tiene éxito, pero siempre recorta 0 bytes.

Causa raíz: No se liberaron bloques nuevos desde el último trim; el sistema está mayormente lleno; o los discards se coalescen/ignoran upstream.

Solución: Libera algo de espacio y vuelve a probar. Verifica soporte de discard con lsblk -D en cada capa. En entornos thin-provisioned, valida la recuperación upstream por separado.

6) Habilitaste discard en volúmenes cifrados y te preocupó la seguridad

Síntoma: La revisión de seguridad alerta sobre riesgo de filtrado de metadatos.

Causa raíz: Los discards pueden revelar patrones de asignación.

Solución: Decide explícitamente. Si el modelo de amenaza lo exige, mantén los discards deshabilitados y acepta las compensaciones de rendimiento/desgaste. No “habilites a medias” de forma que nadie lo entienda después.

7) Intentaste “arreglarlo” con cron y ahora tienes dos trims en conflicto

Síntoma: Los trims se ejecutan dos veces, los logs están confusos, a veces se solapan.

Causa raíz: Trabajo cron más temporizador systemd, ambos activos.

Solución: Elimina el cron job. Mantén el temporizador systemd. Un jefe por proceso.

Listas de verificación / plan paso a paso

Checklist A: Solución mínima (host Debian 13 único, SSD en bare metal)

  1. Comprobar capacidad de discard: ejecutar lsblk -D. Confirma que tu SSD muestre valores de discard distintos de cero.
  2. Habilitar temporizador: systemctl enable --now fstrim.timer.
  3. Forzar una ejecución: systemctl start fstrim.service.
  4. Verificar resultados: journalctl -u fstrim.service -n 50. Busca “X bytes trimmed” en los montajes esperados.
  5. Confirmar programación: systemctl list-timers --all | grep fstrim.

Checklist B: Almacenamiento en capas (LUKS + LVM + SSD)

  1. Comprobar discard del dispositivo base: lsblk -D /dev/nvme0n1.
  2. Comprobar discard del dispositivo mapeado: lsblk -D /dev/mapper/cryptroot (y LVs si aplica).
  3. Si la capa mapeada muestra 0B, revisa /etc/crypttab por la opción discard, y aplica el cambio de forma segura (initramfs + reinicio si la raíz está cifrada).
  4. Ejecuta fstrim -av y confirma bytes recortados.
  5. Confirma la automatización semanal vía temporizador y journal.

Checklist C: Invitado VM en almacenamiento compartido (plan “confiar pero verificar”)

  1. En el invitado: lsblk -D debe mostrar soporte de discard en el disco virtual.
  2. En el invitado: ejecuta fstrim -av. Confirma que no hay “Operation not supported.”
  3. Confirma programación del temporizador y entradas de journald a lo largo del tiempo.
  4. En el host/almacenamiento: verifica que unmap/discard esté habilitado para el tipo de disco VM y que la recuperación de espacio sea observable (depende de la plataforma).
  5. Documenta el proceso. “Creemos que funciona” no es un control.

Checklist D: Baseline de flota (qué automatizar)

  1. Garantizar fstrim.timer habilitado en todos los nodos respaldados por SSD.
  2. Aplicar override al temporizador con aleatorización y persistencia donde corresponda.
  3. Comprobación diaria/semanal: verificar systemctl is-enabled fstrim.timer y parsear journalctl -u fstrim.service por ejecuciones exitosas recientes.
  4. Alertar sobre “Operation not supported” y sobre caída global repentina de bytes recortados en un clúster (así detectas regresiones del hipervisor).

Preguntas frecuentes

1) ¿Debo usar la opción de montaje discard o fstrim semanal?

Usa fstrim semanal para la mayoría de sistemas. Es predecible y más fácil de razonar. Usa discard continuo solo si lo has medido y sabes que no perjudica tu perfil de latencia.

2) ¿Por qué Debian usa un temporizador en lugar de cron?

Los timers de systemd se integran con la gestión de dependencias y los logs de journald. Operativamente son más fáciles de inspeccionar y auditar (list-timers, logs por unidad) que un crontab misterioso.

3) Si fstrim dice “X GiB trimmed”, ¿eso significa que el SSD realmente lo recuperó?

Significa que el sistema de archivos emitió discards y el kernel los aceptó. En configuraciones en capas (VMs, SAN, thin provisioning) aún debes confirmar que la capa de respaldo los respeta.

4) ¿Es seguro habilitar discard en LUKS?

Es una compensación. Puede filtrar patrones de asignación (qué bloques se usan). Muchos modelos de amenaza de servidores lo aceptan; otros no. Decide deliberadamente, documenta y no mezcles supuestos.

5) ¿Por qué fstrim omite algunos montajes?

A menudo porque Debian ejecuta fstrim --fstab. Si un montaje no está en /etc/fstab (o no está montado), no se incluirá. Confirma con la salida del journal y findmnt.

6) ¿Es malo si fstrim recorta 0 bytes?

No necesariamente. Si no se liberó nada nuevo, 0 es esperado. Si siempre es 0 en un sistema con mucho borrado de datos, investiga soporte de discard con lsblk -D y busca capas que lo bloqueen.

7) ¿Puede TRIM causar problemas de rendimiento?

TRIM periódico suele tener un impacto mínimo. El discard continuo puede añadir latencia en algunas cargas. Además, recortar sistemas de archivos enormes durante picos puede competir por I/O—planifica con sensatez si eres sensible a esto.

8) ¿Necesito TRIM en SSDs o NVMe empresariales?

Sí, en general. Las unidades empresariales tienen controladores y firmware mejores, pero aún se benefician de conocer con precisión el espacio libre para reducir la amplificación de escritura y ayudar al rendimiento en estado estable.

9) ¿Qué pasa con las particiones de swap y TRIM?

Swap en SSD puede ser recortado, pero el comportamiento depende del kernel y la configuración. En la mayoría de los casos, tus mayores ganancias están en recortar los sistemas de archivos principales y asegurar que el soporte de discard sea correcto.

10) ¿Cómo demuestro que TRIM se ejecuta regularmente para auditorías?

Usa systemctl list-timers para prueba de programación y journalctl -u fstrim.service para evidencia de ejecución y bytes recortados. Eso es operativamente creíble y reproducible.

Conclusión: siguientes pasos que realmente reducen el riesgo

Habilita el temporizador, ejecuta trim una vez y verifica los logs. Eso es la línea base. Luego haz la parte adulta: confirma el soporte de discard a través de cada capa de almacenamiento de la que dependes. Si estás en una VM o en almacenamiento thin-provisioned, trata “TRIM funciona” como un contrato multi-equipo, no como una configuración solo del invitado.

Pasos prácticos siguientes:

  1. Ejecuta lsblk -D e identifica dónde el discard se vuelve 0B/0B.
  2. Habilita e inicia fstrim.timer; dispara fstrim.service manualmente una vez.
  3. Verifica que las entradas del journal muestren bytes recortados significativos en los montajes que te importan.
  4. Si está cifrado: decide sobre discard en crypttab según el modelo de amenaza, luego implanta limpiamente y valida tras el reinicio.
  5. Si está virtualizado: verifica la configuración de discard/unmap del hipervisor y confirma la recuperación de espacio upstream.
  6. Para flotas: añade una comprobación de cumplimiento para temporizador habilitado + logs recientes de trim exitoso, y alerta sobre cambios en el comportamiento de trim.

TRIM no es glamuroso. Por eso falla silenciosamente. Haz que vuelva a ser aburrido—habilitado, verificado y sin importancia.

← Anterior
Fallos de passthrough PCI en Proxmox: Grupos IOMMU y las trampas clásicas
Siguiente →
Docker “manifest unknown”: etiquetas vs digests explicado (y solucionado)

Deja un comentario