Tu panel SRE está tranquilo, los LEDs del enlace están felices y iperf3 acaba de gritar “10 Gbit/s” como si estuviera orgulloso. Mientras tanto la aplicación real parece enviar peticiones con palomas mensajeras. Este es el tipo de fallo que hace que los equipos discutan en Slack: “No puede ser la red, iperf está bien.” “Siempre es la red.” Ambos pueden estar equivocados.
El caso #24 es la trampa clásica: un benchmark de throughput demuestra que la tubería es ancha, pero tu carga necesita otra cosa: baja latencia en la cola, planificación de CPU sensata, colas estables, DNS predecible o almacenamiento que pueda seguir el ritmo. Te mostraré dónde se esconden los cuellos de botella en Ubuntu 24.04, cómo atraparlos con comandos que realmente puedes ejecutar y cómo tomar decisiones a partir de la salida en vez de coleccionar capturas para un postmortem.
Guía de diagnóstico rápido
Cuando la app va lenta pero iperf3 se ve genial, no “tunées” nada aún. Primero localiza la clase de cuello de botella: CPU/interrupts, TCP/ruta, resolución de nombres/TLS, almacenamiento o concurrencia de la aplicación. Aquí está el orden que encuentra el culpable más rápido en producción.
1) Confirma que el síntoma es latencia, no solo throughput
- Mide el tiempo de las peticiones desde el lado cliente (logs de la app, tiempos de curl, estadísticas del cliente de BD).
- Ejecuta una herramienta de latencia (
ping,mtr, retransmisiones enss) mientras se produce la ralentización.
2) Revisa presión de CPU y desequilibrio softirq/irq
- Si la CPU está saturada, la red puede ser “rápida” en iperf (un flujo en un núcleo) mientras tu app real está bloqueada en softirq, TLS, GC o syscalls.
- Busca alto
softirq,iowaito throttling en cgroups.
3) Revisa salud de TCP: retransmisiones, congestión, agujeros MTU
ss -timuestra retransmisiones y pacing.- Desajustes de MTU y PMTUD roto suelen producir “rápido a veces” más “bloqueos misteriosos”.
4) Revisa encolamiento y pérdidas: anillos NIC, qdisc, bufferbloat
- Las pérdidas pueden ser invisibles para iperf si sus flujos se recuperan; tu app podría no hacerlo.
- Observa
ethtool -S,nstaty estadísticas de qdisc.
5) Revisa almacenamiento y sistema de ficheros: iowait, escrituras sync, peculiaridades NFS/SMB
- Si la app espera por disco, los benchmarks de red son irrelevantes.
- Mira
iostat,pidstat -dy las opciones de montaje.
6) Revisa dependencias “de tuberías”: DNS, tiempo, TLS, proxies
- DNS lento parece “red lenta” y hace perder tiempo a todos.
- Los stalls de handshake TLS pueden dominar el P99 incluso con un enlace perfecto.
Idea parafraseada (atribución): Werner Vogels ha impulsado la idea de que optimizas por la cola, porque los usuarios experimentan la parte más lenta.
Ese es el corazón de este caso: iperf te dice el ancho de banda mediano; tus usuarios están atrapados en la cola.
Por qué iperf parece bien mientras tu app sufre
iperf3 es una herramienta fantástica. También es una herramienta muy específica: mide throughput (y algo de pérdida/jitter en modo UDP) bajo un patrón de flujo sintético. Las aplicaciones reales habitualmente necesitan otro conjunto de garantías:
- Distribución de latencia, no ancho de banda bruto. Muchas apps envían peticiones pequeñas, esperan respuestas y luego envían más. La tubería nunca se llena. iperf la llena.
- Muchos flujos concurrentes. El valor por defecto de iperf es uno o unos pocos streams. Tu malla de servicios puede ser miles de conexiones.
- CPU por byte costosa. TLS, compresión, parseo JSON, logging, copias en kernel, checksums y stacks de red en espacio de usuario consumen CPU. iperf puede ser relativamente liviano en comparación.
- Rutas y paths diferentes. Tu app puede pasar por proxies, NAT, conntrack, DNS, balanceadores L7, sidecars o una VPN. iperf suele ejecutarse punto a punto y evita la ruta real.
- Tamaños de paquete distintos. MSS, MTU, GSO/TSO, GRO/LRO cambian el comportamiento. Los patrones de payload de iperf no son los tuyos.
- Diferente retro-presión. Las apps pueden bloquearse en disco, locks, pools de BD o rate limiters. El socket se convierte en el mensajero acusado.
Aquí está la verdad incómoda: que iperf sea rápido demuestra casi nada más allá de “dos hosts pueden empujar bytes cuando se les pide amablemente”. El tráfico de producción no se pide amablemente.
Bromita #1: iperf es como una prueba de esfuerzo en cinta: demuestra que tu corazón funciona, pero no explica por qué te cansas cargando las bolsas de la compra.
Hechos interesantes e historia breve que importan
- TCP se creó por fiabilidad antes de que la velocidad fuera de moda. Es excelente en convertir pérdida en latencia cuando las colas se llenan.
- Linux ha usado disciplinas de encolamiento avanzadas durante años. Los valores por defecto modernos tienden hacia fair queueing (como
fq_codel) para combatir bufferbloat, pero tu entorno puede sobreescribirlo. - “Bufferbloat” se convirtió en un término operativo mainstream en los 2010s. Demasiado buffering puede hacer que el throughput se vea genial mientras la latencia interactiva se derrumba.
- La moderación de interrupciones y NAPI cambiaron las reglas. Las NICs pasaron de “interrupt por paquete” a batch, intercambiando latencia por eficiencia de CPU—bueno hasta que deja de serlo.
- TSO/GSO/GRO son milagros de rendimiento con letra pequeña. Las offloads reducen CPU al agrupar paquetes, pero pueden ocultar patrones de pérdida y complicar el troubleshooting.
- conntrack no es gratis. NAT stateful y el seguimiento del firewall pueden convertirse en cuello de botella mucho antes de saturar el enlace.
- Los fallos de PMTUD son un clásico “funciona en laboratorio” bug. Si ICMP “Fragmentation needed” está bloqueado, ciertos paths hacen blackhole a paquetes grandes y crean stalls raros.
- DNS pasó de “molestia menor” a “dependencia mayor”. Microservicios convirtieron lookups en una carga QPS alta; los timeouts se vuelven visibles para los usuarios.
- TLS se volvió más rápido y también más costoso. TLS 1.3 redujo rondas, pero empujó más trabajo a la CPU. En hosts ocupados, los handshakes aún pueden dominar.
Tareas prácticas: comandos, salidas y decisiones
Estas son tareas reales que puedes ejecutar en Ubuntu 24.04. Cada una incluye: el comando, qué significa la salida y la decisión que tomas. Ejecútalas durante la ralentización si puedes; de lo contrario estás diagnosticando un fantasma.
Task 1: Reproducir iperf de forma que coincida con tu app
cr0x@server:~$ iperf3 -c 10.0.0.20 -P 8 -t 20
Connecting to host 10.0.0.20, port 5201
[SUM] 0.00-20.00 sec 22.8 GBytes 9.79 Gbits/sec 0 sender
[SUM] 0.00-20.04 sec 22.8 GBytes 9.77 Gbits/sec receiver
Qué significa: Múltiples streams paralelos (-P 8) pueden ocultar límites por flujo. Si tu app usa muchas conexiones, esto es más representativo que un solo flujo.
Decisión: Si un solo flujo es lento pero multi-flujo es rápido, sospecha restricciones por flujo: control de congestión, MTU/PMTUD, policers o un único cuello de botella de CPU/IRQ.
Task 2: Medir latencia y estabilidad de ruta con mtr
cr0x@server:~$ mtr -rwzc 200 10.0.0.20
Start: 2025-12-30T10:12:31+0000
HOST: server Loss% Snt Last Avg Best Wrst StDev
1.|-- 10.0.0.1 0.0% 200 0.25 0.32 0.19 1.90 0.18
2.|-- 10.0.0.20 0.0% 200 0.42 0.55 0.35 5.70 0.44
Qué significa: Promedio bajo pero peor caso alto sugiere encolamiento o pérdidas/retransmisiones intermitentes.
Decisión: Si los picos del peor caso se correlacionan con la lentitud de la app, pasa a verificar colas/pérdidas y retransmisiones TCP.
Task 3: Ver si el host está con CPU escasa o atascado en iowait
cr0x@server:~$ uptime
10:14:02 up 12 days, 3:21, 2 users, load average: 18.42, 16.90, 14.11
Qué significa: El load average son tareas ejecutables + ininterrumpibles. Load alto puede ser contención de CPU o esperas de I/O.
Decisión: Load alto con uso de CPU bajo a menudo significa I/O bloqueado (disco o filesystem de red) o contención de locks. No toques el tuning de la NIC hasta que lo sepas.
Task 4: Desglosar CPU, softirq y iowait
cr0x@server:~$ mpstat -P ALL 1 5
Linux 6.8.0-xx-generic (server) 12/30/2025 _x86_64_ (32 CPU)
12:14:21 CPU %usr %sys %iowait %soft %idle
12:14:22 all 38.10 21.33 0.15 18.40 22.02
12:14:22 7 10.00 15.00 0.00 70.00 5.00
Qué significa: El CPU 7 está ahogado en %soft (softirq). Eso es procesamiento de paquetes y tareas afines.
Decisión: Si uno o dos CPUs están saturados en softirq, probablemente tienes un desequilibrio IRQ/RPS/RFS. Arregla eso antes de culpar “la red”.
Task 5: Identificar qué interrupciones están calientes
cr0x@server:~$ cat /proc/interrupts | egrep -i 'eth0|mlx|ixgbe|enp|eno' | head
98: 192837465 0 0 0 PCI-MSI 524288-edge enp5s0f0-TxRx-0
99: 120044 0 0 0 PCI-MSI 524289-edge enp5s0f0-TxRx-1
100: 118900 0 0 0 PCI-MSI 524290-edge enp5s0f0-TxRx-2
Qué significa: La cola 0 recibe casi todas las interrupciones. Las otras colas están inactivas.
Decisión: Habilita o corrige la afinidad de IRQ (o usa irqbalance con cuidado) y verifica que las colas RSS estén configuradas y distribuyan la carga.
Task 6: Comprobar offloads de la NIC y estado de enlace actual
cr0x@server:~$ sudo ethtool enp5s0f0
Settings for enp5s0f0:
Supported link modes: 1000baseT/Full 10000baseT/Full
Speed: 10000Mb/s
Duplex: Full
Auto-negotiation: on
Link detected: yes
Qué significa: El enlace negoció la velocidad/duplex esperada. Si ves 1000Mb/s inesperadamente, para aquí y corrige cableado/SFP/configuración del puerto del switch.
Decisión: Corrige la capa física/enlace antes de hacer algo “inteligente” en software.
Task 7: Buscar pérdidas a nivel NIC y overruns de anillo
cr0x@server:~$ sudo ethtool -S enp5s0f0 | egrep -i 'drop|discard|miss|overrun|timeout' | head -n 20
rx_missed_errors: 18234
rx_no_buffer_count: 14590
tx_timeout_count: 0
Qué significa: rx_no_buffer_count sugiere que la NIC/controlador se quedó sin buffers de recepción—a menudo un problema de tamaño de anillo, saturación de CPU/softirq, o presupuestos de memoria demasiado pequeños bajo presión.
Decisión: Si estos contadores aumentan durante la ralentización, aborda la distribución CPU/IRQ y considera ajustar anillos (ethtool -g/-G). También verifica si el host sufre presión de memoria.
Task 8: Inspeccionar tamaños de anillo (y si puedes cambiarlos)
cr0x@server:~$ sudo ethtool -g enp5s0f0
Ring parameters for enp5s0f0:
Pre-set maximums:
RX: 4096
TX: 4096
Current hardware settings:
RX: 512
TX: 512
Qué significa: Los anillos son pequeños respecto al máximo. Anillos pequeños pueden perder durante micro-bursts; anillos enormes pueden aumentar la latencia al bufferizar demasiado. Elige tu veneno intencionalmente.
Decisión: Si ves drops en RX y picos de latencia bajo carga bursty, aumentar moderadamente el anillo RX puede ayudar. Si tu queja es latencia en la cola bajo carga moderada, no infles buffers a ciegas.
Task 9: Comprobar retransmisiones TCP y salud de sockets
cr0x@server:~$ ss -ti dst 10.0.0.20 | head -n 20
ESTAB 0 0 10.0.0.10:46322 10.0.0.20:443
cubic wscale:7,7 rto:204 rtt:3.2/0.8 ato:40 mss:1448 pmtu:1500 rcvmss:1448 advmss:1448
bytes_sent:184233 bytes_retrans:12480 bytes_acked:171753 segs_out:2219 segs_in:1962 data_segs_out:2010
Qué significa: bytes_retrans no trivial es una pistola humeante. Las retransmisiones se convierten en latencia, bloqueo head-of-line y lentitud visible por el usuario.
Decisión: Si las retransmisiones se correlacionan con periodos lentos, céntrate en pérdida en la ruta, drops en colas, policers, problemas de MTU o fallos del NIC/controlador.
Task 10: Revisar estadísticas de red del kernel para retransmisiones y timeouts
cr0x@server:~$ nstat -az | egrep 'TcpRetransSegs|TcpTimeouts|TcpExtTCPSynRetrans|IpExtInNoRoutes'
TcpRetransSegs 18432 0.0
TcpTimeouts 1220 0.0
TcpExtTCPSynRetrans 219 0.0
Qué significa: Retransmisiones/timeouts crecientes apuntan a pérdida, encolamiento pobre o blackholes en la ruta. Retransmisiones SYN pueden indicar drops de SYN (firewall, conntrack o listener sobrecargado).
Decisión: Si las retransmisiones SYN aumentan, inspecciona límites de conntrack, reglas de firewall y la cola de aceptaciones/backlog en el servidor.
Task 11: Detectar agujeros MTU/PMTUD con una sonda controlada
cr0x@server:~$ ping -M do -s 1472 -c 5 10.0.0.20
PING 10.0.0.20 (10.0.0.20) 1472(1500) bytes of data.
1472 bytes from 10.0.0.20: icmp_seq=1 ttl=64 time=0.42 ms
1472 bytes from 10.0.0.20: icmp_seq=2 ttl=64 time=0.44 ms
--- 10.0.0.20 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4004ms
Qué significa: Esto confirma que MTU 1500 funciona end-to-end. Si falla con “Frag needed” o cae silenciosamente, tienes un desajuste de MTU o ICMP bloqueado causando fallo de PMTUD.
Decisión: Si falla, arregla consistencia de MTU o permite los ICMP necesarios. No “arriesgues” con MSS clamping a menos que controles todo el path y entiendas el tradeoff.
Task 12: Inspeccionar qdisc y comportamiento de colas
cr0x@server:~$ tc -s qdisc show dev enp5s0f0
qdisc mq 0: root
qdisc fq_codel 0: parent :1 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms ecn
Sent 29837294812 bytes 21833890 pkt (dropped 482, overlimits 0 requeues 1221)
backlog 0b 0p requeues 1221
Qué significa: Drops a nivel de qdisc pueden ser saludables (drop controlado) o sintomáticos (límite demasiado pequeño, app bursty). Requeues sugieren contención o pacing.
Decisión: Si ves drops sostenidos y latencia creciente, ajusta colas y pacing—pero solo después de verificar CPU y drops de NIC. Si la latencia en la cola es el problema, fq_codel suele ser tu aliado; reemplazarlo por pfifo_fast es como viajar en el tiempo a 2009.
Task 13: Revisar presión de conntrack (cuello de botella NAT/firewall)
cr0x@server:~$ sudo sysctl net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_max = 262144
cr0x@server:~$ sudo cat /proc/sys/net/netfilter/nf_conntrack_count
258901
Qué significa: Estás cerca del límite. Cuando conntrack se llena, las conexiones nuevas fallan o se quedan colgadas. iperf puede seguir funcionando si reutiliza conexiones o si pruebas fuera de ruta.
Decisión: Incrementa nf_conntrack_max (considerando memoria), reduce churn de conexiones o evita conntrack para tráfico que no lo necesita. También revisa timeouts adecuados para tu carga.
Task 14: Confirmar que DNS no es el “problema de red”
cr0x@server:~$ resolvectl query api.internal.example
api.internal.example: 10.0.0.20 -- link: enp5s0f0
(A) -- flags: answer
52ms
Qué significa: 52ms para resolver un nombre interno es sospechoso en un contexto LAN. Unos cuantos de esos por chain de peticiones y de repente “la app está lenta”.
Decisión: Si la latencia DNS es alta o inconsistente, inspecciona la ruta de resolvers (systemd-resolved, DNS upstream, dominios de búsqueda, reintentos). Cachea donde corresponda y arregla el upstream.
Task 15: Cronometra una petición completa: DNS + connect + TLS + primer byte
cr0x@server:~$ curl -sS -o /dev/null -w 'dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\n' https://10.0.0.20/health
dns:0.000 connect:0.003 tls:0.118 ttfb:0.146 total:0.147
Qué significa: El handshake TLS está dominando. Tu “red lenta” en realidad es CPU, entropía, tamaño de cadena de certificados, problemas de OCSP stapling o terminación TLS sobrecargada.
Decisión: Si TLS es lento, perfila el endpoint de terminación: CPU, cifrados, resumption de sesión, tamaño de la cadena de certificados y si hay un proxy haciendo trabajo extra.
Task 16: Revisar espera I/O y saturación de disco (porque la app escribe en algún sitio)
cr0x@server:~$ iostat -xz 1 3
Device r/s w/s rkB/s wkB/s await svctm %util
nvme0n1 120.0 950.0 5200.0 88100.0 24.10 0.70 92.00
Qué significa: El disco está ~92% utilizado y la espera media es 24ms. Las apps esperando por disco “se sienten como red lenta” porque las respuestas no se generan.
Decisión: Si %util es alto y await sube durante incidentes, arregla la contención de almacenamiento: separa cargas, ajusta patrones fsync, añade cache o escala almacenamiento.
Task 17: Encontrar qué proceso hace I/O o está siendo throttled
cr0x@server:~$ pidstat -dl 1 5
# Time UID PID kB_rd/s kB_wr/s iodelay Command
10:18:01 1001 21422 0.00 8420.00 120 postgres
10:18:01 0 9981 0.00 1200.00 40 fluent-bit
Qué significa: La base de datos y el agente de logging compiten. En el mundo real, los logs a menudo consumen el presupuesto de latencia primero.
Decisión: Si tu logging/telemetría es pesado, limita su tasa, sácalo del camino crítico o mándalo a un disco separado. Observabilidad que causa downtime es arte, no ingeniería.
Task 18: Revisar throttling de CPU en cgroups (común en contenedores)
cr0x@server:~$ cat /sys/fs/cgroup/system.slice/docker.service/cpu.stat
usage_usec 8922334455
user_usec 6122334400
system_usec 2800000055
nr_periods 238994
nr_throttled 82211
throttled_usec 992233445
Qué significa: El servicio está siendo throttled. Eso crea picos de latencia, stalls en conexiones y TLS lento—aunque la NIC esté bien.
Decisión: Aumenta cuota de CPU, reduce trabajo de CPU por petición o reequilibra placement. Si estás limitando, deja de interpretar la salida de iperf como la realidad única.
Tres micro-historias corporativas desde el campo
Mini-historia 1: El incidente causado por una suposición equivocada
Tuvieron una ventana de migración y una checklist. Alguien ejecutó iperf3 entre los viejos servidores de aplicación y el nuevo clúster de base de datos. Alcanzó la velocidad de línea. Declararon la red “validada” y siguieron adelante.
El lunes por la mañana, la cola de tickets empezó a llenarse con “la app se congela durante 10–30 segundos”. No era un crash ni una falla dura. Solo pausas largas y humillantes. El equipo de redes señaló los resultados de iperf. El equipo de base de datos mostró gráficas de CPU “bien”. El equipo de aplicación reescribió tres timeouts de clientes en pánico y empeoró la situación.
El problema real era un desajuste de MTU a través de un límite VLAN. La nueva ruta tenía jumbo frames activados en un subconjunto de puertos del switch, mientras que un firewall en medio descartaba ICMP “fragmentation needed”. Paquetes pequeños pasaban, por eso ping parecía bien y muchas peticiones funcionaban. Ciertos tamaños de payload activaban el fallo de PMTUD y quedaban en blackhole hasta que TCP hacía timeout y probaba segmentos más pequeños.
iperf se veía genial porque la prueba usó una ruta diferente (un salto enrutado directo que evitaba el firewall) y porque el comportamiento del stream se recuperaba. La app, con muchas conexiones TLS de corta duración y respuestas ocasionalmente más grandes, golpeaba los casos rotos constantemente.
Arreglarlo fue aburrido: MTU consistente, permitir los tipos ICMP necesarios para PMTUD y un path estándar para pruebas. La lección no fue “iperf es malo”. La lección fue “la suposición de que iperf prueba todo el path es una mentira que te contaste”.
Mini-historia 2: La optimización que salió mal
Un equipo de plataforma quería menor uso de CPU en sus nodos Ubuntu 24.04. El procesamiento de red aparecía en flamegraphs como tiempo de softirq. Alguien sugirió activar offloads más agresivos y aumentar los anillos de NIC “para que nunca droppee”. Sonaba razonable. También se desplegó a producción un viernes, lo cual es un fuerte indicador de optimismo.
El uso de CPU bajó. ¿Éxito, verdad? Pero el síntoma visible al cliente—latencia P99—empeoró. No un poco. Llamadas que normalmente estaban bien se volvieron espaciadas e impredecibles. La parte del negocio lo notó porque siempre lo nota cuando tocas la latencia de cola.
El problema fue bufferbloat clásico, pero dentro del host. Anillos agrandados y colas más profundas absorbieron picos en vez de dropear temprano, así TCP no recibió señales de congestión a tiempo. Los paquetes se quedaron en buffers más tiempo y los flujos interactivos esperaron detrás de transferencias bulk. Las gráficas de throughput se veían excelentes. La experiencia de usuario no.
Rollback inmediato mejoró el P99. Luego hicieron lo maduro: re-aplicaron cambios gradualmente, midieron latencia de cola, mantuvieron fair queueing y ajustaron anillos solo hasta el punto en que las pérdidas dejaron de ser patológicas.
Bromita #2: Nada hace a un sistema “rápido” como bufferizar peticiones hasta la semana que viene.
Mini-historia 3: La práctica aburrida pero correcta que salvó el día
Un servicio relacionado con finanzas tenía SLOs estrictos de latencia y la costumbre de fallar ruidosamente en fin de trimestre. El equipo no tenía tiempo para debugging heroico. Hicieron algo aburrido: estandarizaron un runbook de rendimiento “dorado” para cada clase de host.
Cada nodo se desplegó con la misma base: MTU consistente, ajustes qdisc conocidos buenos, plantillas de afinidad IRQ por modelo de NIC y un pequeño conjunto de exporters “always-on” que seguían TcpRetransSegs, CPU en softirq y espera de disco. También fijaron comportamiento DNS: resolvers explícitos, listas de search cortas y cache donde procediera.
Cuando llegó una ralentización, el on-call no debatió ideologías. Compararon el host en vivo contra las salidas baseline. Un nodo mostraba rx_no_buffer_count en aumento y tenía una versión de kernel distinta por un reboot perdido. Eso fue todo. Sin thriller misterioso.
Dran el nodo, lo reiniciaron al kernel correcto y el incidente terminó. El postmortem fue corto y ligeramente embarazoso, que es lo mejor: “teníamos una baseline, detectamos deriva, arreglamos la deriva”.
La práctica no era excitante. Era efectiva. La mayor parte del trabajo de fiabilidad es prevenir que tu yo futuro se sorprenda.
Errores comunes: síntomas → causa raíz → solución
Esta sección es donde me pongo opinativo. Estos son patrones que consumen días porque suenan plausibles. Úsalos como prueba de olor.
1) “iperf es rápido, así que la red está bien”
Síntoma: iperf reporta Gbit/s altos; la app tiene alta latencia P95/P99 y timeouts.
Causa raíz: Validaste throughput para un pequeño número de streams, no pérdida, jitter, encolamiento ni latencias de dependencias. El tráfico real usa rutas distintas (proxies/NAT/VPN/malla de servicios).
Solución: Re-ejecuta pruebas por la ruta real (mismo VIP, mismo DNS, mismo TLS) y mide retransmisiones, drops de qdisc y tiempos DNS/TLS. Usa desgloses estilo curl -w y ss -ti.
2) “La app solo está lenta bajo carga”
Síntoma: Funciona con poco tráfico, colapsa durante picos; iperf fuera de pico es perfecto.
Causa raíz: Encolamiento y bufferbloat, saturación de softirq, agotamiento de conntrack o contención de disco bajo concurrencia real.
Solución: Observa durante el pico. Captura mpstat, nstat, ethtool -S, tc -s, iostat. Arregla el recurso más apretado: distribución CPU/IRQ, equidad de qdisc, dimensionado de conntrack o aislamiento de almacenamiento.
3) “La pérdida de paquetes es minúscula, así que no puede importar”
Síntoma: Pérdida bajo 1%, pero stalls y reintentos visibles por usuarios.
Causa raíz: TCP es sensible a pérdida, especialmente para flujos cortos y durante slow start. Incluso pérdidas moderadas pueden inflar la latencia de cola.
Solución: Localiza el punto de caída: drops en anillos NIC, drops en qdisc, policers del switch, Wi‑Fi/underlay problemático o enlaces oversubscribed. No todas las pérdidas son iguales; las que ocurren en el momento equivocado dañan más.
4) “Aumentamos buffers, ahora es estable” (hasta que no lo es)
Síntoma: Menos drops, peor interactividad, P99 sube.
Causa raíz: Demasiado buffering causa demora por encolamiento; la equidad entre flujos empeora; TCP ve congestión más tarde.
Solución: Prefiere fair queueing y drop controlado sobre buffers profundos. Ajusta tamaños de anillos con cuidado y mide latencia, no solo throughput.
5) “Es overhead de Kubernetes/service mesh” (a veces cierto, a menudo perezoso)
Síntoma: iperf en host es rápido; pod-a-pod o servicio-a-servicio es lento.
Causa raíz: Desajuste MTU en overlay, presión de conntrack, escalado de kube-proxy iptables, sidecar con throttling de CPU o vecinos ruidosos en cgroups.
Solución: Verifica MTU end-to-end, monitoriza conteo de conntrack, mide throttling por pod y confirma que la prueba use la misma ruta de servicio que el tráfico de producción.
6) “La base de datos está lenta, pero la red es rápida”
Síntoma: Consultas BD cuelgan; iperf está bien; CPU parece OK.
Causa raíz: Latencia de almacenamiento (fsync, WAL, NFS, NVMe saturado) o contención de locks que parece “esperar bytes”.
Solución: Mide iostat await, I/O por proceso con pidstat -d y eventos de espera específicos de la BD. No uses herramientas de red para depurar almacenamiento.
Listas de verificación / plan paso a paso
Checklist A: Cuando alguien dice “iperf está bien”
- Pregunta: “¿Qué exactamente está lento?” Identifica si es tiempo de conexión, tiempo TLS, primer byte o respuesta total.
- Confirma la ruta de la app: nombre DNS, VIP, cadena de proxies, NAT, overlay, zonas de firewall. Asegúrate de que tu prueba use la misma ruta.
- Captura retransmisiones y timeouts:
ss -ti,nstat. - Captura drops:
ethtool -S,tc -s qdisc. - Captura softirq de CPU y distribución de IRQ:
mpstat,/proc/interrupts. - Captura latencia de almacenamiento:
iostat -xz,pidstat -d. - Solo entonces considera tunear. Si tuneas primero, solo estarás cambiando la escena del crimen.
Checklist B: Arreglar hotspots IRQ/softirq de forma segura
- Verifica que RSS esté habilitado y que existan múltiples colas (
ethtool -lsi es soportado). - Inspecciona interrupciones por cola en
/proc/interrupts. - Comprueba si
irqbalanceestá corriendo y si ayuda o perjudica tu carga. - Cambia una cosa a la vez (afinidad o RPS), luego mide distribución de softirq y latencia de la app.
- Registra tu configuración final en gestión de configuración. La deriva es el asesino silencioso.
Checklist C: Validar MTU end-to-end
- Confirma MTU de interfaz en todos los hosts implicados (
ip link show). - Sondea con
ping -M doal tamaño esperado. - Si hay overlay/VPN, considera overhead de encapsulación y reduce MTU interna acorde.
- Asegura que los mensajes ICMP requeridos para PMTUD no estén bloqueados por la política de seguridad.
- Reprueba comportamiento a nivel de aplicación (handshakes TLS, respuestas grandes) después de cambios.
Checklist D: Cuando huele a DNS
- Cronometra lookups con
resolvectl querydurante el incidente. - Comprueba si dominios de búsqueda causan lookups NXDOMAIN repetidos.
- Verifica salud del upstream resolver y si el cache funciona eficazmente.
- Confirma que la app no haga lookups por petición debido a falta de pooling o mal config del cliente.
Preguntas frecuentes (FAQ)
1) Si iperf es rápido, ¿puede la red seguir siendo el problema?
Sí. iperf prueba mayormente ancho de banda bajo un patrón de flujo específico. Tu problema puede ser pérdida, jitter, demora por encolamiento, PMTUD, policers o una ruta diferente que involucre NAT/proxies.
2) ¿Debería ejecutar iperf con más streams paralelos?
A menudo sí. Usa -P para imitar concurrencia de conexiones. Si muchos streams van rápido pero uno va lento, sospecha restricciones por flujo (pérdida, policers, MTU, control de congestión).
3) ¿Cuál es el indicador más rápido de que se están perdiendo paquetes?
Retransmisiones crecientes en ss -ti y nstat, más contadores de NIC como rx_no_buffer_count o drops de qdisc en tc -s. Las pérdidas no siempre aparecen en ping.
4) ¿Por qué veo softirq alto y la app se ralentiza?
Softirq es donde el kernel procesa paquetes. Si está pegado a un núcleo (común con mala distribución IRQ/RSS), tus hilos de app compiten por CPU y se retrasan. Distribuye interrupciones y steering de paquetes entre CPUs.
5) ¿Es buena idea aumentar buffers de NIC?
A veces. Puede reducir drops durante ráfagas, pero también aumentar latencia al bufferizar más. Si tu SLO es latencia, ajusta anillos con conservadurismo y mide P99 antes/después.
6) ¿Cómo puede DNS hacer mi “red” lenta?
Cada lookup es una dependencia de red con timeouts y reintentos. En microservicios, los lookups DNS pueden estar en la ruta crítica más a menudo de lo que se admite. Mídelo con resolvectl y desglosa tiempos de petición con curl -w.
7) ¿Puede el almacenamiento ser el cuello de botella aunque los clientes se quejen de “respuestas lentas”?
Absolutamente. Si el servidor no puede leer o escribir datos rápidamente, no puede responder rápido. Revisa iostat await y %util, luego identifica qué procesos generan I/O.
8) ¿Por qué solo pasa en contenedores o Kubernetes?
Los contenedores añaden límites de cgroup, redes overlay y a menudo caminos con mucha carga de conntrack. Throttling de CPU, overhead MTU y agotamiento de conntrack son comunes. Mide throttling y conteos de conntrack directamente.
9) ¿Debería desactivar offloads (TSO/GRO/LRO) para “arreglar latencia”?
No como primer movimiento. Desactivar offloads suele aumentar uso de CPU y puede empeorar latencia de cola bajo carga. Solo cambia offloads cuando tengas evidencia de un bug del driver/firmware o una interacción específica de offload.
10) ¿Qué pasa si iperf es rápido, ping está bien y todo sigue atascado?
Mira la “plomería”: tiempo de handshake TLS, DNS, conntrack, colas de accept/backlog y agotamiento de pools de la aplicación (conexiones BD, thread pools). Las herramientas de red no revelan eso directamente.
Conclusión: siguientes pasos que puedes hacer hoy
Si recuerdas una cosa del caso #24, que sea esta: throughput no es la experiencia de usuario. iperf es un instrumento contundente; tu app es un organismo quisquilloso que se preocupa por la cola.
Haz esto a continuación, en este orden:
- Captura un único desglose de “petición lenta” (
curl -wo tiempos de la app) para identificar si el dolor es DNS, connect, TLS o tiempo del servidor. - Durante el incidente, recoge cuatro snapshots:
mpstat,ss -ti,nstat,iostat. Esos por sí solos suelen decir qué subsistema miente. - Si softirq/IRQs están calientes, arregla distribución antes de tunear buffers.
- Si retransmisiones/timeouts suben, busca pérdidas y problemas MTU end-to-end.
- Si espera de almacenamiento es alta, deja de culpar a la red y ten la incómoda conversación de “el disco está en llamas”.
- Escribe una baseline y hazla cumplir. El mejor incidente es el que puedes acabar comparando salidas, no improvisando.