Aplicas un parche al kernel, actualizas el controlador de la tarjeta de red o instalas el paquete de almacenamiento “recomendado” del proveedor. Se cierra la ventana de cambios. Los gráficos parecen bien durante una hora. Luego la latencia sube como un ascensor estropeado: lento, constante y hacia un lugar donde no quieres estar.
Aquí es donde la gente discute “no puede ser el driver” porque la actualización “solo tocó la red”. Mientras tanto, tu base de datos agota tiempos de espera porque las colas de completado del almacenamiento están hambrientas tras una tormenta de interrupciones. A producción no le importa qué equipo es responsable; solo le importa que esté lento.
Qué cambia cuando cambian los controladores
Los controladores no son “solo controladores”. Deciden cómo se programa tu hardware, cómo se entregan las interrupciones, cómo se dimensionan las colas y cómo el kernel interpreta el flujo del tiempo bajo carga. Una actualización de controlador puede cambiar el rendimiento sin tocar una sola línea de tu código de aplicación. Eso no es un riesgo teórico; es martes.
Patrones de regresión de rendimiento que aparecen tras actualizaciones de controladores
- Picos de latencia sin pérdida de rendimiento: cambios en la vía de completado, ajustes de moderación de interrupciones o valores por defecto de profundidad de cola que cambian. Tus paneles muestran MB/s estables, mientras p99 de latencia se vuelve salvaje.
- Caída de throughput con CPU baja: offloads deshabilitados, enlace negociado a menor velocidad, PCIe negociando menos carriles o entra en acción una política conservadora del firmware.
- CPU alto y “nada más cambió”: cambió el número de vectores MSI-X, se reseteó la afinidad de IRQ, se togglearon RPS/RFS o un nuevo driver asigna trabajo a un solo núcleo.
- Sólo algunas máquinas presentan regresión: stepping/firmware distinto, valores por defecto del BIOS, diferencias en microcode o el driver empareja con un ID de dispositivo ligeramente diferente.
- Regresión solo bajo concurrencia: cambió el comportamiento de encolamiento; las pruebas single-thread van bien, pero las cargas reales no son single-thread.
Dónde ocurre el verdadero daño
En producción, “rendimiento del driver” suele significar uno de tres pipelines:
- Pipeline de E/S de almacenamiento: capa de bloque → planificador → multipath (quizá) → driver HBA/NVMe → firmware → medio. Las actualizaciones pueden afectar encolamiento, comportamiento de merge, timeouts y recuperación ante errores.
- Pipeline de red: colas netdev → GRO/LRO/offloads → moderación de interrupciones → sondeo NAPI → topología CPU/NUMA. Una actualización de driver puede cambiar silenciosamente tamaños de ring y coalescing por defecto, lo que altera la latencia de cola.
- Pipeline de aceleradores (GPU/DPDK/RDMA): memoria fijada, mapeo IOMMU, hugepages, DMA peer-to-peer. Una “pequeña” actualización puede invertir un valor por defecto que convierte el DMA en melaza.
Una verdad incómoda: tu actualización de driver no solo actualizó un controlador. Actualizó las suposiciones del sistema sobre cómo mover bytes.
Una cita para llevar siempre, porque es la versión operativa de la gravedad:
Idea parafraseada de Werner Vogels: “Todo falla todo el tiempo; diseña y opera con esa expectativa.”
También, un chiste corto antes de ponernos serios: Una actualización de driver es como reorganizar el garaje: inofensivo hasta que necesitas la llave a las 2 a. m.
Hechos y contexto histórico que aún nos muerden
Algunas regresiones “modernas” son problemas antiguos con hardware nuevo. Un poco de historia te ayuda a predecir dónde el rendimiento se desploma.
- La capa de bloque de Linux ha cambiado de dirección varias veces: de planificadores legacy a multi-queue (blk-mq), desplazando los cuellos de botella del merge de requests al scheduling de CPU y la gestión de colas.
- NCQ y tagged command queuing cambiaron lo que significa “profundidad de cola”: colas más profundas mejoraron throughput pero también expusieron latencia de cola y problemas de fairness en cargas mixtas.
- MSI/MSI-X reemplazaron las interrupciones compartidas por buenas razones: pero el número de vectores y cómo se asignan a CPUs puede hacer o deshacer sistemas de alto I/O. Los drivers suelen cambiar valores por defecto aquí.
- La moderación de interrupciones se inventó para ahorrar CPU: el coalescing mejora throughput pero puede destrozar p99. Las actualizaciones de driver a veces lo suben “amablemente”.
- Los offloads (TSO/GSO/GRO/LRO) son una espada de doble filo: pueden mejorar throughput y reducir CPU, pero también ocultar problemas y añadir latencia en sitios extraños. Las actualizaciones pueden resetearlos.
- La negociación de enlace ha sido un facepalm recurrente desde que Ethernet era joven: un solo desacuerdo de auto-negociación puede degradarte silenciosamente de 25/40/100G a algo embarazoso.
- Los defaults de multipath evolucionaron con los proveedores SAN: políticas de comprobación de path, comportamientos de queue_if_no_path y tiempos de failover pueden cambiar. “Funciona” no significa “rápido”.
- NVMe estandarizó mucho, pero el firmware todavía varía enormemente: políticas APST distintas y comportamientos de recuperación ante errores pueden cambiar la latencia por órdenes de magnitud.
Ninguno de estos es académico. Aparecen como “estaba bien la semana pasada”.
Guion rápido de diagnóstico
Estás contra el reloj. Los usuarios están gritando. La ventana de cambio ya pasó. Necesitas una secuencia que te lleve a un cuello de botella plausible rápidamente.
Primero: confirma que es real y define “lento” en una frase
- Elige un observable: p99 read latency, commit latency, network RTT, IOPS o CPU softirq.
- Elige una comparación: la baseline de ayer o otro host del mismo clúster que no actualizó.
- No “investigues rendimiento” de forma amplia. Morirás en el pantano.
Segundo: decide qué pipeline es culpable
Usa estas señales rápidas:
- iowait alto, disk await en subida, CPU estable → camino de almacenamiento o política de dispositivo/firmware.
- softirq alto, actividad de ksoftirqd, paquetes descartados → ruta de red/interrupciones.
- Un núcleo de CPU al 100% y los demás ociosos → regresión de afinidad de IRQ / mapeo de colas.
- Sólo bajo carga, no en pruebas en reposo → encolamiento, coalescing, scheduler o estados de energía.
Tercero: encuentra el “valor por defecto reseteado”
Tras actualizaciones, las regresiones a menudo vienen de un valor por defecto que vuelve:
- Tamaños de ring de NIC de vuelta a valores pequeños
- Afinidad de IRQ perdida o reordenada
- APST de NVMe reactivado
- Cambio del I/O scheduler
- Cambio de la política de multipath
- Modo IOMMU alternado
Cuarto: pruébalo con un test controlado
Ejecuta un micro-benchmark corto y reproducible en el host afectado y en un host conocido bueno. No buscas ganar un concurso de benchmarks; buscas aislar la dimensión de la regresión (latencia vs throughput vs CPU).
Quinto: elige la mitigación más segura
En orden de prioridad:
- Rollback del paquete driver/firmware (restaurar lo conocido es lo más rápido).
- Reaplicar tunables conocidos buenos (si el rollback está bloqueado).
- Desviar la carga desde los hosts afectados (comprar tiempo).
- Rollback completo del kernel si el cambio está acoplado al kernel.
El ritual post-actualización (la parte aburrida que gana)
Ritual suena místico. No lo es. Es una verificación repetible que evita la espiral de “actualizamos y ahora está más lento”. Los mejores equipos tratan las actualizaciones de controladores como migraciones de base de datos: reversibles, medidas y probadas bajo las mismas condiciones.
1) Anota las diferencias esperadas antes de actualizar
No “debería estar bien”. Expectativas concretas:
- Qué dispositivos se ven afectados (PCI IDs, modelo NIC, modelo NVMe, firmware HBA).
- Qué métricas podrían moverse (latencia, throughput, CPU softirq, tasas de error).
- Cuál es tu plan de rollback (ruta de downgrade del paquete, entrada previa del kernel, fallback de firmware si es posible).
2) Captura una baseline que puedas reproducir
Tu “baseline” no es la captura de pantalla del panel del mes pasado. Es un paquete de salidas de comandos que cuenten una historia coherente: versión del kernel, versiones de driver, versiones de firmware, tunables y el resultado de un benchmark pequeño.
3) Actualiza en una porción controlada
Canaries primero. No porque sea tendencia, sino porque las regresiones suelen ser específicas de hardware y quieres descubrirlo con un nodo, no con cuarenta.
4) Verifica de nuevo los valores por defecto que te importan
Los paquetes de drivers a veces vienen con nuevos valores por defecto. Algunos son mejores. Otros asumen que tu carga es “servir web” cuando en realidad eres “base de datos intensiva en escrituras con SLOs p99”. Trata los defaults como sugerencias del proveedor, no como ley.
5) Compara bajo carga, no bajo esperanza
Los sistemas inactivos mienten. La mayoría de las regresiones aparecen bajo concurrencia, al borde de los buffers circulares, cuando la capa de bloque está bajo presión o cuando la moderación de interrupciones cambia la cadencia de los completados.
Segundo y último chiste corto: La forma más rápida de encontrar una regresión es anunciar “esta actualización es segura” en una revisión de cambios. El universo se lo tomará personalmente.
Tareas prácticas: comandos, salidas y decisiones
A continuación hay tareas concretas que puedes ejecutar justo después de una actualización. Cada una incluye: el comando, qué significa la salida y qué decisión tomar.
Task 1: Confirma qué cambió realmente (kernel + módulos de driver)
cr0x@server:~$ uname -r
6.5.0-28-generic
cr0x@server:~$ modinfo ixgbe | egrep 'filename|version|srcversion'
filename: /lib/modules/6.5.0-28-generic/kernel/drivers/net/ethernet/intel/ixgbe/ixgbe.ko
version: 5.19.6-k
srcversion: 1A2B3C4D5E6F7A8B9C0D1E2
Significado: Tienes la versión del kernel en ejecución y la build/versión del driver cargado. Si la regresión apareció “después de la actualización”, demuestra que realmente estás ejecutando los bits actualizados.
Decisión: Si el kernel/driver no es lo esperado, para: tu despliegue/bootloader/pinning de paquetes no está funcionando. Arregla eso antes de tocar cualquier ajuste.
Task 2: Identifica versiones de firmware para NIC y almacenamiento
cr0x@server:~$ sudo ethtool -i eno1
driver: ixgbe
version: 5.19.6-k
firmware-version: 0x80000d7b
bus-info: 0000:3b:00.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: yes
supports-register-dump: yes
supports-priv-flags: yes
Significado: El firmware puede cambiar el comportamiento incluso cuando el driver no lo hace. Algunas actualizaciones instalan firmware por paquetes separados o durante mantenimiento.
Decisión: Si el firmware cambió, inclúyelo en el plan de rollback y en las comparaciones “conocido bueno”. No asumas que puedes revertirlo rápidamente.
Task 3: Comprueba velocidad/anchura del enlace PCIe (asesino silencioso del throughput)
cr0x@server:~$ sudo lspci -s 3b:00.0 -vv | egrep -i 'LnkCap:|LnkSta:'
LnkCap: Port #0, Speed 8GT/s, Width x8, ASPM not supported
LnkSta: Speed 2.5GT/s (downgraded), Width x4 (downgraded)
Significado: El dispositivo negoció a una velocidad menor. Eso puede suceder tras cambios en el BIOS, firmware o por peculiaridades de gestión de energía.
Decisión: Si LnkSta muestra velocidad/anchura degradada, deja de perseguir tunables del driver. Arregla primero la negociación física/PCIe (reinsertar, configuración BIOS, estados de energía, quirks conocidos de la plataforma).
Task 4: Diferencia latencia de almacenamiento vs saturación (iostat)
cr0x@server:~$ iostat -xz 1 3
Linux 6.5.0-28-generic (server) 01/22/2026 _x86_64_ (32 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
11.22 0.00 6.51 18.45 0.00 63.82
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %util await r_await w_await
nvme0n1 820.0 1250.0 52480.0 76800.0 0.0 0.0 97.8 9.82 6.10 12.40
Significado: %util cerca de 100% sugiere saturación. await indica latencia promedio; la separación read/write ayuda a identificar qué patrón empeoró.
Decisión: Si await saltó tras la actualización con throughput similar, sospecha estados de energía, ajustes de cola, cambios de scheduler o recuperación de errores del firmware. Si %util es bajo pero await es alto, sospecha problemas de path o timeouts.
Task 5: Detecta regresiones de estado de energía NVMe y APST
cr0x@server:~$ sudo nvme get-feature /dev/nvme0 -f 0x0c -H
get-feature:0xc (Autonomous Power State Transition), Current value:0x00000001
APSTE: 1
APST Entries:
Entry[ 0] Idle Time Prior to Transition (ITPT): 1000 ms
Entry[ 0] Idle Transition Power State (ITPS): 3
Significado: APST activado puede estar bien en portátiles y ser un desastre en servidores sensibles a latencia, dependiendo del dispositivo/firmware.
Decisión: Si la latencia regresó y APST está activado inesperadamente, prueba desactivarlo temporalmente y observa si p99 mejora. Luego hazlo persistente mediante el mecanismo apropiado para tu distro/kernel.
Task 6: Comprueba scheduler de bloque y ajustes de cola
cr0x@server:~$ cat /sys/block/nvme0n1/queue/scheduler
[mq-deadline] none
cr0x@server:~$ cat /sys/block/nvme0n1/queue/nr_requests
1024
cr0x@server:~$ cat /sys/block/nvme0n1/queue/read_ahead_kb
128
Significado: La elección de scheduler y la profundidad de cola influyen en fairness y latencia bajo contención. Las actualizaciones a veces cambian el scheduler por defecto o los límites de requests.
Decisión: Si el scheduler difiere del conocido bueno, alinéalo y repite la prueba. Si nr_requests fue reducido, puedes ver caídas de throughput bajo carga paralela; si aumentó, podrías ver picos de latencia.
Task 7: Valida el estado de multipath (las regresiones SAN adoran esconderse aquí)
cr0x@server:~$ sudo multipath -ll
mpatha (3600508b400105e210000900000490000) dm-2 IBM,2145
size=2.0T features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
|-+- policy='service-time 0' prio=50 status=active
| `- 5:0:0:1 sdb 8:16 active ready running
`-+- policy='service-time 0' prio=10 status=enabled
`- 6:0:0:1 sdc 8:32 active ready running
Significado: Las prioridades y políticas de path importan. Un cambio de política puede enrutar más I/O por un path más lento o causar thrashing durante failover.
Decisión: Si la selección de path activa difiere después de la actualización, compara multipath.conf y las características del mapa en ejecución. Corrige la política/ALUA antes de culpar a la base de datos.
Task 8: Revisa dmesg por resets de driver, timeouts o flaps de enlace
cr0x@server:~$ sudo dmesg -T | egrep -i 'nvme|ixgbe|timeout|reset|link is|error' | tail -n 20
[Wed Jan 22 10:12:41 2026] nvme nvme0: I/O 123 QID 5 timeout, completion polled
[Wed Jan 22 10:12:41 2026] nvme nvme0: Abort status: 0x371
[Wed Jan 22 10:14:03 2026] ixgbe 0000:3b:00.0 eno1: NIC Link is Up 10 Gbps, Flow Control: RX/TX
Significado: Los timeouts y abortos no son “ruido”. Son asesinos de rendimiento mucho antes de convertirse en outages.
Decisión: Si ves nuevos timeouts tras la actualización, deja de tunear y empieza a aislar: compatibilidad de firmware, gestión de energía, cable/SFP, PCIe o bugs del driver. Considera rollback inmediato.
Task 9: Verifica velocidad de enlace y ajustes negociados de la NIC
cr0x@server:~$ sudo ethtool eno1 | egrep 'Speed:|Duplex:|Auto-negotiation:|Link detected:'
Speed: 10000Mb/s
Duplex: Full
Auto-negotiation: on
Link detected: yes
Significado: Si la velocidad está mal, todo lo demás sufre. Este es el paso de “revisa el cable”, salvo que es 2026 y a veces es un valor por defecto de firmware.
Decisión: Si la velocidad bajó, arregla eso primero. Si la velocidad es correcta, pasa a offloads y tamaños de ring.
Task 10: Comprueba offloads de la NIC (a las actualizaciones les encanta reiniciarlos)
cr0x@server:~$ sudo ethtool -k eno1 | egrep 'tcp-segmentation-offload|generic-segmentation-offload|generic-receive-offload|rx-checksumming|tx-checksumming'
rx-checksumming: on
tx-checksumming: on
tcp-segmentation-offload: off
generic-segmentation-offload: on
generic-receive-offload: on
Significado: Un solo offload deshabilitado puede mover costo de CPU al kernel y reducir throughput. Pero habilitar todo a ciegas puede aumentar latencia o romper la observabilidad.
Decisión: Compara con el conocido bueno. Si TSO se apagó tras la actualización y subió CPU softirq, vuélvelo a activar y repite la prueba. Si la latencia es el problema, considera ajustar coalescing en lugar de activar todos los offloads.
Task 11: Inspecciona tamaños de ring y contadores de drops
cr0x@server:~$ sudo ethtool -g eno1
Ring parameters for eno1:
Pre-set maximums:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
Current hardware settings:
RX: 512
RX Mini: 0
RX Jumbo: 0
TX: 512
cr0x@server:~$ ip -s link show dev eno1 | tail -n 8
RX: bytes packets errors dropped missed mcast
9876543210 12345678 0 421 0 0
TX: bytes packets errors dropped carrier collsns
8765432109 11223344 0 0 0 0
Significado: Rings pequeños y drops en aumento son una clásica regresión post-actualización cuando cambian defaults. Los drops fuerzan retransmisiones, que se ven como “latencia aleatoria”.
Decisión: Si los drops aumentan y los rings son pequeños respecto al máximo, incrementa los tamaños de ring (con cuidado) y repite la prueba. Si los drops persisten, revisa coalescing y distribución de IRQ.
Task 12: Comprueba distribución de interrupciones (regresión de afinidad IRQ)
cr0x@server:~$ awk '/eno1/ {print}' /proc/interrupts | head -n 6
121: 9843321 0 0 0 PCI-MSI 524288-edge eno1-TxRx-0
122: 0 0 0 0 PCI-MSI 524289-edge eno1-TxRx-1
123: 0 0 0 0 PCI-MSI 524290-edge eno1-TxRx-2
124: 0 0 0 0 PCI-MSI 524291-edge eno1-TxRx-3
Significado: Todas las interrupciones en una CPU es un impuesto de rendimiento y generador de latencia. Tras una actualización, el comportamiento de irqbalance o el setup de vectores del driver puede cambiar.
Decisión: Si un vector está caliente y otros fríos, arregla afinidad (o RPS/RFS) y repite la prueba. Si no se crean vectores como se esperaba, revisa parámetros del driver y si MSI-X está habilitado.
Task 13: Mide carga de softirq (dolor en la ruta de red)
cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0-28-generic (server) 01/22/2026 _x86_64_ (32 CPU)
12:20:41 PM CPU %usr %nice %sys %iowait %irq %soft %idle
12:20:42 PM all 10.20 0.00 6.80 1.10 0.30 8.90 72.70
12:20:42 PM 7 2.00 0.00 4.00 0.00 0.00 65.00 29.00
Significado: Una única CPU ahogada en %soft sugiere desequilibrio en el procesamiento de interrupciones/paquetes. Eso suele ser un reset de configuración del driver, no “la app se volvió más lenta”.
Decisión: Si una CPU está sobrecargada en %soft, ajusta afinidad IRQ/RPS o revisa offloads/coalescing. Si softirq es bajo pero la latencia es alta, el cuello de botella podría estar en otro lugar.
Task 14: Valida concurrencia de la ruta I/O con fio (test controlado y corto)
cr0x@server:~$ sudo fio --name=randread --filename=/dev/nvme0n1 --direct=1 --ioengine=libaio --rw=randread --bs=4k --iodepth=64 --numjobs=4 --runtime=30 --time_based --group_reporting
randread: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=64
...
read: IOPS=220k, BW=859MiB/s (901MB/s)(25.2GiB/30001msec)
slat (nsec): min=920, max=110893, avg=3210.44, stdev=1800.12
clat (usec): min=60, max=9800, avg=112.30, stdev=95.20
lat (usec): min=62, max=9810, avg=115.60, stdev=95.50
clat percentiles (usec):
| 50.00th=[ 98], 90.00th=[ 180], 99.00th=[ 420], 99.90th=[1200]
Significado: Obtienes IOPS, ancho de banda y distribución de latencias. Los percentiles son lo que sienten tus usuarios. Una regresión de driver a menudo aparece en p99/p99.9 antes de que la media se mueva mucho.
Decisión: Compara con la baseline. Si p99/p99.9 empeoró materialmente, no discutas: haz rollback o arregla los ajustes que cambiaron.
Task 15: Comprueba modo IOMMU (sorpresas en rendimiento DMA)
cr0x@server:~$ dmesg -T | egrep -i 'DMAR|IOMMU|AMD-Vi' | head -n 8
[Wed Jan 22 09:01:11 2026] DMAR: IOMMU enabled
[Wed Jan 22 09:01:11 2026] DMAR: Intel(R) Virtualization Technology for Directed I/O
Significado: Algunas actualizaciones de driver interactúan con defaults de IOMMU. Para ciertos dispositivos de alto throughput, una mala configuración puede añadir overhead o causar contención en el mapeo.
Decisión: Si el rendimiento regresó y el modo IOMMU cambió recientemente, valida la guía de la plataforma para tu carga (especialmente DPDK/RDMA/GPU). No desactives a ciegas; prueba en un canario.
Task 16: Confirma la política de frecuencia de CPU (ahorro de energía puede parecer regresión de driver)
cr0x@server:~$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
powersave
cr0x@server:~$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
1200000
Significado: Tras actualizaciones o cambios en BIOS, los governors pueden cambiar. Frecuencia baja de CPU puede inflar latencia de interrupciones y de completado de I/O.
Decisión: Si el governor cambió de performance a powersave, arregla eso primero o tu tuning estará persiguiendo un objetivo móvil.
Tres micro-historias del mundo corporativo
Micro-historia 1: El incidente causado por una suposición equivocada
Operaban un clúster analítico respaldado por almacenamiento. Nada exótico: Linux, caché NVMe, store de objetos en red, muchas lecturas paralelas pequeñas. Cayó una actualización del kernel con “correcciones de seguridad y drivers actualizados”. El ticket del cambio estaba impecable. El equipo asumió que los drivers eran irrelevantes porque “de todos modos estamos limitado por CPU”.
Dos días después, los jobs nocturnos empezaron a perder deadlines. No catastrófico. Lo suficiente para provocar una reunión diaria. Los gráficos eran confusos: el throughput parecía estable, pero el tiempo de ejecución de los jobs se estiró. La CPU estaba más baja que antes. La gente tomó eso como buena noticia.
El síntoma real era latencia de cola en lecturas pequeñas. La nueva combinación driver/firmware NVMe reactivó una política agresiva de ahorro de energía. La latencia media casi no cambió; p99.9 se duplicó. La carga era un enjambre de lecturas pequeñas, así que la cola lenta dominó el tiempo de reloj.
La suposición equivocada no era “los drivers no importan”. Era más sutil: “si el throughput está estable, el almacenamiento está bien”. El throughput es una métrica cómoda porque es fácil de graficar. La latencia es la que paga tu salario.
Desactivaron la función de ahorro problemática en canaries, confirmaron la recuperación de percentiles con pruebas fio cortas y luego aplicaron el ajuste en todo el clúster. Más tarde, revertieron el firmware por si acaso. El postmortem tuvo una línea que quedó: medimos la cosa equivocada primero.
Micro-historia 2: La optimización que salió mal
Un equipo de plataforma quería reducir uso de CPU en nodos API saturados. Tras una actualización del driver NIC, vieron más knobs para moderación de interrupciones. Aumentaron coalescing porque los gráficos prometían menos interrupciones. La CPU bajó. Declararon victoria.
Entonces llegó el incidente con traje: la latencia orientada al cliente subió durante horas pico. No un pico, una deriva—más difícil de alertar, perfecta para arruinar un SLA silenciosamente. Sus paneles mostraban CPU más baja y throughput de red estable. De nuevo, métricas reconfortantes.
Causa raíz: coalescing aumentó el tiempo que los paquetes esperaban antes de ser procesados. Excelente para throughput. Malo para latencia de cola. Peor aún, interactuó con un patrón de requests ya sensible a jitter, así que p99 saltó lo suficiente como para provocar reintentos en la capa de aplicación.
La optimización fracasó porque optimizó el objetivo equivocado. Perseguían CPU, no latencia. La NIC hizo exactamente lo que se le pidió: agrupar trabajo. Producción hizo lo que siempre hace: castigar el tradeoff incorrecto.
La solución fue quirúrgica: revertir coalescing al perfil conocido bueno, luego afinar distribución de IRQ y tamaños de ring. La CPU subió algo, pero p99 se estabilizó. Aprendieron la lección operacional: “menos CPU” no es una meta; es una restricción que gestionas mientras cumples SLOs.
Micro-historia 3: La práctica aburrida pero correcta que salvó el día
Una financiera tenía una política de cambios que todos ridiculizaban: para actualizaciones de drivers requerían un “bundle de captura antes/después”. No era un proceso enorme. Un script recogía versión de kernel, versiones de módulos, versiones de firmware, tunables clave en sysfs y un fio de 30 segundos más una sencilla prueba iperf en entorno controlado.
El día que cayó una actualización de driver de almacenamiento, un nodo canario mostró un pequeño pero consistente aumento en percentiles de latencia de escritura. Nada “caído”. Si hubieran desplegado en todo el clúster, la base de datos habría sufrido durante el procesamiento de fin de día y eso habría sido un incidente real.
El bundle de captura hizo la regresión obvia: cambió el scheduler, nr_requests cambió y un parámetro de timeout se movió. La solución fue igualmente aburrida: fijar el paquete del driver, restaurar scheduler y ajustes de cola y abrir un ticket con el proveedor con diffs concretos.
Porque lo captaron en el canario, nadie tuvo que explicarle a ejecutivos por qué “una actualización menor” causó lentitud visible para clientes. El equipo siguió burlándose de la política, pero con menos entusiasmo. El aburrimiento está subestimado en operaciones.
Errores comunes: síntoma → causa raíz → solución
1) “El throughput está bien, pero la app está lenta”
Síntoma: MB/s estables; p95/p99 de latencia peor; aparecen timeouts/reintentos.
Causa raíz: Moderación de interrupciones aumentada; APST/estados de energía activados; cambió comportamiento de colas; la vía de completado se movió a menos CPUs.
Solución: Valida coalescing, características de energía NVMe, distribución de IRQ. Usa percentiles de fio, no latencia media.
2) “La CPU bajó tras la actualización y el rendimiento también”
Síntoma: CPU más baja; throughput menor; latencia de requests más alta.
Causa raíz: Offloads deshabilitados; enlace negociado a menor velocidad; dispositivo cayó a menos carriles PCIe; tamaños de ring reducidos.
Solución: Revisa ethtool offloads y velocidad de enlace; revisa PCIe LnkSta; aumenta rings si los drops suben.
3) “Solo un nodo está lento”
Síntoma: Un host regresa; peers bien con mismo software.
Causa raíz: Mismatch de firmware; topología PCIe/NUMA distinta; deriva en configuración del BIOS; diferencia de microcode; cambio de revisión del dispositivo.
Solución: Compara lspci -vv, ethtool -i, nvme id-ctrl entre nodos; alinea firmware/BIOS; no asumas homogeneidad.
4) “Aparecieron drops de red tras la actualización”
Síntoma: Contadores RX dropped en aumento; retransmisiones; jitter.
Causa raíz: Tamaños de ring reducidos; afinidad IRQ colapsada; coalescing demasiado agresivo; cambió el número de colas RSS.
Solución: Aumenta tamaños de ring; asegúrate de que múltiples colas estén activas; arregla afinidad; reevalúa coalescing para latencia.
5) “Storage muestra timeouts en dmesg pero el disco está sano”
Síntoma: líneas nvme timeout/abort; stalls ocasionales; sin fallos SMART.
Causa raíz: Mismatch driver/firmware; transiciones de estado de energía; resets de controlador; problemas de integridad de señal PCIe expuestos por nuevos timings del driver.
Solución: Trátalo como un problema de compatibilidad o de plataforma: prueba rollback, ajusta funciones de energía, revisa negociación PCIe, escala con logs reproducibles.
6) “Después de actualizar, multipath está ‘up’ pero el I/O es más lento”
Síntoma: multipath -ll parece normal; latencia peor bajo carga; failover de paths más ruidoso.
Causa raíz: Cambió la política (service-time vs round-robin); prioridades ALUA mal interpretadas; cambió queue_if_no_path; cambió el timing del checker de path.
Solución: Valida policy/prio; alinea multipath.conf; confirma comportamiento ALUA; vuelve a probar con carga controlada.
Listas de verificación / plan paso a paso
Pre-actualización (15 minutos que previenen un incidente de 5 horas)
- Define la superficie de riesgo: qué drivers/firmware cambian (NIC, HBA, NVMe, GPU, RDMA).
- Captura bundle baseline: uname -r, modinfo, ethtool -i/-k, lspci -vv (para dispositivos clave), settings sysfs de scheduler/queue, multipath -ll si aplica.
- Elige 2–3 métricas golden: una de throughput y al menos una de latencia de cola. Anótalas en el ticket de cambio.
- Plan de rollback: pasos de downgrade de paquete, entrada previa del kernel y restricciones de reversión de firmware.
- Elige canaries: hosts que representen la variedad de hardware, no solo “el menos ocupado”.
Durante la ventana de actualización (haz menos cosas, pero hazlas a propósito)
- Actualiza solo la porción canaria primero.
- Verifica kernel/módulos en ejecución tras el reboot.
- Revisa ancho/anchura del enlace PCIe para los dispositivos tocados.
- Confirma velocidad negociada y offloads de la NIC.
- Ejecuta una prueba estandarizada y corta (fio para almacenamiento; check de throughput/latencia ligero para red si tienes una ruta segura).
- Compara con la baseline, no con tu instinto.
Post-actualización (la parte del “ritual”)
- Reaplica tunables intencionales: afinidad IRQ, tamaños de ring, settings de scheduler, políticas de energía—todo lo que incluya tu conocido-bueno.
- Observa por regresiones retardadas: estados de energía y recuperación ante errores pueden parecer bien hasta que la carga cambie de forma.
- Expande el rollout gradualmente: si los canaries están limpios, procede por lotes con pausas suficientes para observar comportamiento bajo carga real.
- Archiva el after-state bundle: se convierte en tu nueva baseline si es bueno, o en evidencia si es malo.
Si sospechas una regresión: escalera de actuación
- Detén la hemorragia: drena cargas desde nodos afectados o reduce concurrencia.
- Reproduce en un nodo: ejecuta el benchmark controlado y recoge logs.
- Rollback de lo más pequeño posible: paquete del driver o tunable primero; rollback completo del kernel si es necesario.
- Solo después, afina: tunear sin saber qué cambió es como acabar con un sistema frágil que solo una persona entiende.
Preguntas frecuentes
1) ¿Por qué las actualizaciones de drivers causan regresiones de rendimiento aun cuando el hardware es el mismo?
Porque los drivers codifican políticas: dimensionado de colas, comportamiento de interrupciones, valores por defecto de offloads, gestión de energía y recuperación de errores. Cambiar política cambia rendimiento.
2) ¿Es mejor actualizar kernel y drivers por separado o juntos?
Por separado es más fácil de atribuir; juntos a veces es inevitable. Si debes hacerlo junto, aumenta el tiempo de canary y captura más evidencia antes/después.
3) ¿Cuál es la comprobación más rápida para una regresión de NIC?
Empieza por velocidad/duplex del enlace y contadores de drops. Si estás negociando a menor velocidad o hay drops, todo lo demás es una distracción.
4) ¿Cuál es la comprobación más rápida para una regresión de almacenamiento?
iostat para await/%util más dmesg en busca de timeouts/resets. Si el kernel está haciendo timeouts de I/O, la historia de rendimiento ya está escrita.
5) ¿Debo siempre desactivar NVMe APST en servidores?
No. Debes basarlo en una baseline. Algunos dispositivos se comportan bien; otros castigan la latencia de cola. Si tienes SLOs p99, prueba APST on/off con percentiles fio.
6) ¿Puede irqbalance “arreglar” automáticamente problemas de interrupciones?
A veces. También puede deshacer pinning intencional o tomar decisiones correctas para distribución promedio de CPU pero malas para latencia. Trátalo como una herramienta, no como una garantía.
7) ¿Por qué aumentar tamaños de ring ayudó al throughput pero no a la latencia?
Rings más grandes reducen drops y mejoran throughput en ráfagas, pero también aumentan buffering, lo que puede añadir latencia. Si la latencia es la prioridad, ajusta coalescing y distribución de IRQ cuidadosamente.
8) ¿Cuándo debería hacer rollback en lugar de tunear?
Si ves errores/timeouts/resets nuevos, haz rollback. Si es un desplazamiento limpio de rendimiento sin errores y puedes relacionarlo con un cambio de default, el tuning puede ser apropiado—primero en canaries.
9) ¿Cómo evito el “teatro de benchmarks” tras actualizaciones?
Usa pruebas cortas y estandarizadas y compara la misma prueba en un host conocido bueno. Registra percentiles, distribución de CPU y tunables clave. No hagas cherry-pick.
10) ¿Qué pasa si la regresión solo aparece en tráfico pico y no puedo reproducirla?
Busca indicadores de saturación: drops, encolamiento, hotspots de softirq en un solo núcleo, degradaciones PCIe bajo carga y transiciones de estado de energía. Si no puedes reproducir, aún puedes correlacionar.
Conclusión: próximos pasos que puedes hacer
Las actualizaciones de controladores no dan miedo. Las actualizaciones de controladores sin medición sí dan miedo. La cura no es heroísmo; es un ritual repetible que trata el rendimiento como una propiedad de corrección de primer orden.
- Construye un bundle baseline (versiones, firmware, tunables, un fio corto, una comprobación sanity de NIC) y hazlo obligatorio para cambios de drivers.
- Adopta el guion rápido de diagnóstico: define “lento”, elige el pipeline, busca el default reseteado, pruébalo con una sola prueba, mitiga de forma segura.
- Canary en cada actualización de drivers a través de las variantes de hardware. Si no puedes canaryar, no estás actualizando: estás apostando.
- Anota tus tunables conocidos buenos y vuelva a aplicarlos intencionalmente después de las actualizaciones. Los defaults no son tu gestión de configuración.
- Prefiere rollback sobre “tuneos misteriosos” cuando veas timeouts/resets/errores. Las regresiones de rendimiento con errores son el ensayo de los outages.
Si haces esto de forma consistente, “rendimiento post-actualización” deja de ser un género dramático y pasa a ser un elemento de checklist. A producción le encanta eso.