Tu servidor ZFS rinde como un héroe localmente, y luego se arrastra cuando un cliente lo accede por 10GbE. Todo el mundo tiene una teoría. El almacenamiento culpa al switch. La red culpa a ZFS. El equipo de la aplicación culpa a “latencia”. Mientras tanto miras un diálogo de copia que parece que renderiza cada paquete a mano.
Así es como dejas de adivinar. Construirás una línea base, aislarás capas y te irás con pruebas: o bien la red es tu techo, o solo es el mensajero que entrega malas noticias desde otro sitio.
Un modelo mental que sobrevive a las reuniones
Para probar un cuello de botella, necesitas separar los techos de throughput de la amplificación de latencia y la serialización.
1) 10GbE tiene un techo duro, pero tu carga lo alcanza de forma distinta
En papel, 10GbE son 10 gigabits por segundo. En la práctica, el mejor throughput de carga útil TCP suele estar alrededor de 9.4–9.8 Gbit/s dependiendo del framing, offloads y CPU. Eso equivale a cerca de 1.1–1.2 GB/s en términos de copia de archivos si todo está alineado y en streaming.
Pero las cargas de ZFS no siempre son streaming. I/O pequeño, cháchara de metadatos, escrituras síncronas o un protocolo conversador pueden “gastarse” ancho de banda en overhead y tiempo en idas y vueltas. 10GbE puede parecer lenta cuando en realidad es rápida pero forzada a un comportamiento de parar-y-esperar por algo aguas arriba.
2) ZFS puede ser más rápido que tu red, y eso es una trampa
Un pool ZFS moderno con suficientes discos o NVMe puede superar 10GbE en lecturas secuenciales. Bien. Eso significa que la red se convierte en el limitador de transferencias grandes, y deberías ver una meseta clara: los discos no están ocupados, la CPU no está al máximo y la NIC está cerca de la velocidad de línea.
Si no ves una meseta clara, no estás “limitado por la red”. Estás “limitado por otra cosa” y la red solo está involucrada.
3) Probar un cuello de botella de red requiere dos medidas independientes
Estás intentando responder a una pregunta específica: ¿Es la red el punto más estrecho en este camino extremo a extremo?
Para probarlo necesitas:
- Una prueba solo de red (sin discos, sin sistemas de ficheros) que llegue cerca de la velocidad de línea.
- Una prueba solo de almacenamiento (local al servidor) que exceda lo que ves por la red.
- Y luego una prueba combinada (NFS/SMB/iSCSI) que coincida con el techo solo-de-red.
Si cualquiera de estas no cuadra, no tienes un cuello de botella de red limpio. Tienes un problema en capas, que es más molesto pero también más solucionable.
Una regla operacional que vale la pena pegarte en la frente: Nunca afines ZFS por un problema de red, y nunca afines la red por un problema de ZFS, hasta que tengas pruebas de aislamiento.
Hechos interesantes y breve historia (para dejar de repetir mitos)
- 10GbE no se diseñó inicialmente para cobre barato. Las primeras implantaciones fueron mayoritariamente en fibra; 10GBASE-T llegó después y consumía más energía comparado con óptica SFP+/DAC.
- Los jumbo frames existían antes de la popularidad de 10GbE. Se usaban para reducir la carga de CPU en enlaces muy ocupados mucho antes de que los switches comenzaran a “quizá soportarlos” por defecto.
- ZFS fue diseñado con integridad de datos end-to-end como característica principal. Checksums y copy-on-write no son “extras”; son el propósito, y tienen implicaciones de rendimiento.
- NFS ha vivido varias vidas. v3 es sin estado y común en appliances; v4 añade estado, locking y modos de fallo diferentes que aparecen como “problemas de rendimiento”.
- El rendimiento de SMB cambió drásticamente cuando multi-channel y las pilas modernas de Linux/Windows maduraron. Las viejas recetas de tuning de SMB aún se copian en entornos que no coinciden.
- El escalado de ventana TCP hizo posibles enlaces de alta latencia y alto throughput. Sin ello, tu “10GbE” se comportaría como una sugerencia educada.
- La moderación de interrupciones y los offloads son un compromiso. Pueden reducir el coste de CPU por paquete, pero también aumentar la latencia o ocultar bugs del driver.
- recordsize de ZFS no es lo mismo que “tamaño de bloque en disco”, pero influye fuertemente en el patrón de I/O y en cómo los protocolos de red pueden streamear datos eficientemente.
- Los buffers de los switches no son infinitos, y los microbursts pueden descartar paquetes incluso cuando la utilización media parece adecuada.
Libro de jugadas de diagnóstico rápido (primero/segundo/tercero)
Primero: demuestra que la red puede hacer 10GbE entre los dos hosts exactos
- Ejecuta
iperf3en ambas direcciones con múltiples flujos. - Comprueba la velocidad negociada de la NIC, el ancho PCIe, el driver y errores.
- Mira drops/retransmisiones. Si los ves, detente y arregla eso antes de tocar ZFS.
Segundo: demuestra que el servidor ZFS puede leer/escribir más rápido localmente de lo que el cliente ve
- Usa
fiolocalmente contra un dataset (y opcionalmente un zvol) con direct I/O para evitar ilusiones de “es solo ARC”. - Usa
zpool iostat -vpara confirmar que los discos hacen lo que crees que hacen. - Observa uso de CPU y latencia por dispositivo; si el pool no puede alimentar 1+ GB/s, la red no es el principal limitador.
Tercero: prueba el protocolo real (NFS/SMB/iSCSI) y correlaciona en ambos lados
- Ejecuta una transferencia de archivos controlada o
fiosobre NFS/SMB. - Captura simultáneamente: estadísticas de NIC, estadísticas de ZFS y retransmisiones del lado cliente.
- Si el throughput del protocolo coincide con el techo de iperf3 y los discos del servidor no están saturados, estás limitado por la red (por diseño, no por accidente).
Si haces solo una cosa: ejecuta iperf3 y captura retransmisiones. Si la red está enferma, lo confesará rápido.
Objetivos base para 10GbE + cómo se ve “bien”
Los objetivos varían según SO, NIC y CPU. Pero para un enlace 10GbE único en Linux moderno:
- iperf3 flujo único: a menudo 6–9 Gbit/s dependiendo del tuning TCP y la latencia.
- iperf3 4–8 flujos paralelos: debería acercarse a 9.4–9.8 Gbit/s en una LAN limpia.
- Retransmisiones TCP: deben estar cerca de cero en una LAN estable. Unas pocas en el calentamiento pueden ocurrir; retransmisiones persistentes significan drops, óptica/cables defectuosos, problemas de negociación dúplex/velocidad o presión de buffers.
- Errores/drops de la NIC: deberían ser cero o extremadamente bajos. “Un poco” no es un plan.
- Lectura secuencial local del servidor (fio): idealmente > 1.2 GB/s si quieres saturar 10GbE con margen; de lo contrario tu pool es el limitador.
También: no ignores el cliente. Muchos incidentes de “NAS lento” son en realidad “el cliente tiene un driver NIC de la Pleistocena”.
Broma #1: Un enlace 10GbE que llega a 2 Gbit/s sigue siendo “10GbE” de la misma manera que un coche deportivo con una rueda desinflada sigue siendo “un coche deportivo”.
Tareas prácticas: comandos, salidas, decisiones
Estas son tareas reales que puedes ejecutar hoy. Cada una incluye un comando, una salida de ejemplo y la decisión que tomas a partir de ello. Ejecútalas en el servidor ZFS y en el cliente cuando aplique.
Tarea 1: Verificar velocidad de enlace, dúplex y estado negociado
cr0x@server:~$ sudo ethtool enp65s0
Settings for enp65s0:
Supported ports: [ FIBRE ]
Supported link modes: 10000baseT/Full
Supported pause frame use: Symmetric
Supports auto-negotiation: No
Advertised link modes: 10000baseT/Full
Advertised pause frame use: Symmetric
Advertised auto-negotiation: No
Speed: 10000Mb/s
Duplex: Full
Port: FIBRE
PHYAD: 0
Transceiver: internal
Auto-negotiation: off
Link detected: yes
Qué significa: Si no ves 10000Mb/s Full con link detected, detente. No puedes sobre-tunear un enlace malo.
Decisión: Si la velocidad no es 10Gb, arregla cableado/óptica/configuración del switch primero. Si hay desajuste de auto-negociación (común con 10GBASE-T), corrígelo.
Tarea 2: Comprobar ancho y velocidad PCIe (sí, importa)
cr0x@server:~$ sudo lspci -s 65:00.0 -vv | egrep -i "LnkCap|LnkSta"
LnkCap: Port #0, Speed 8GT/s, Width x8, ASPM L0s, Exit Latency L0s <512ns, L1 <64us
LnkSta: Speed 8GT/s, Width x8
Qué significa: Una NIC 10GbE en una ranura PCIe funcionando x1 o a baja velocidad puede limitar el throughput o provocar picos de latencia bajo carga.
Decisión: Si el ancho/velocidad está por debajo de lo esperado, mueve la NIC, cambia ajustes BIOS o deja de compartir lanes con una HBA de almacenamiento si la placa base es tacaña.
Tarea 3: Comprobar contadores de errores y drops de interfaz
cr0x@server:~$ ip -s link show dev enp65s0
2: enp65s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 3c:fd:fe:aa:bb:cc brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped missed mcast
9876543210 1234567 0 0 0 1234
TX: bytes packets errors dropped carrier collsns
8765432109 2345678 0 0 0 0
Qué significa: Cualquier error/dropped no nulo durante pruebas es sospechoso. Dropped también puede ser desbordamiento de cola del host.
Decisión: Si los drops suben bajo carga, investiga tamaños de ring, driver, afinidad IRQ y congestión del switch. No toques ZFS aún.
Tarea 4: Buscar retransmisiones TCP en Linux (cliente y servidor)
cr0x@server:~$ sudo nstat -az | egrep "TcpRetransSegs|TcpOutSegs|TcpInErrs"
TcpInErrs 0 0.0
TcpOutSegs 4863921 0.0
TcpRetransSegs 12 0.0
Qué significa: Las retransmisiones deben ser extremadamente bajas en una LAN. Retransmisiones persistentes indican pérdida de paquetes o reordenamiento severo.
Decisión: Si las retransmisiones aumentan significativamente durante una prueba de throughput, arregla la ruta de red (cables/óptica, buffers del switch, hashing LACP, mismatch de MTU) antes de culpar a ZFS.
Tarea 5: Establecer throughput bruto de red con iperf3 (modo servidor)
cr0x@server:~$ iperf3 -s
-----------------------------------------------------------
Server listening on 5201 (test #1)
-----------------------------------------------------------
Accepted connection from 10.20.30.41, port 49822
[ 5] local 10.20.30.10 port 5201 connected to 10.20.30.41 port 49824
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.00 sec 10.8 GBytes 9.27 Gbits/sec
Qué significa: 9+ Gbit/s es una buena señal. Si te quedas en 3–5 Gbit/s, la red o la pila del host está limitando.
Decisión: Si iperf3 no puede ir rápido, no pierdas tiempo afinando NFS/SMB/ZFS. Arregla la tubería básica primero.
Tarea 6: Usar múltiples flujos para alcanzar la velocidad de línea
cr0x@client:~$ iperf3 -c 10.20.30.10 -P 8 -t 15
[SUM] 0.00-15.00 sec 17.1 GBytes 9.80 Gbits/sec receiver
Qué significa: Multi-stream a menudo oculta limitaciones de flujo único (tamaño de ventana, scheduling de CPU, peculiaridades de offload).
Decisión: Si multi-stream alcanza ~9.5–9.8 pero el flujo único es bajo, la red está bien; céntrate en tuning TCP, CPU y el comportamiento de la aplicación/protocolo (copy single-thread, escrituras sync, I/O pequeño).
Tarea 7: Validar MTU end-to-end (sin fragmentación, sin deseos)
cr0x@client:~$ ping -M do -s 8972 10.20.30.10 -c 3
PING 10.20.30.10 (10.20.30.10) 8972(9000) bytes of data.
8972 bytes from 10.20.30.10: icmp_seq=1 ttl=64 time=0.215 ms
8972 bytes from 10.20.30.10: icmp_seq=2 ttl=64 time=0.207 ms
8972 bytes from 10.20.30.10: icmp_seq=3 ttl=64 time=0.209 ms
--- 10.20.30.10 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2035ms
Qué significa: Si esto falla, no tienes jumbo frames funcionando en todo el path. Jumbo parcial es peor que ninguno.
Decisión: O haces MTU consistente en NICs/VLAN/puertos de switch, o te quedas en 1500 en todas partes y dejas de discutir.
Tarea 8: Revisar offloads de la NIC y sanity (TSO/GSO/GRO/RX/TX)
cr0x@server:~$ sudo ethtool -k enp65s0 | egrep "tcp-segmentation-offload|generic-segmentation-offload|generic-receive-offload|rx-checksumming|tx-checksumming"
rx-checksumming: on
tx-checksumming: on
tcp-segmentation-offload: on
generic-segmentation-offload: on
generic-receive-offload: on
Qué significa: Los offloads pueden mejorar throughput y reducir CPU, pero drivers/firmware con fallos pueden causar drops o latencia extraña.
Decisión: Si ves retransmisiones/drops y sospechas problemas de offload, alterna características una a la vez durante una prueba controlada. No desactives todo a lo loco “por Reddit”.
Tarea 9: Observar distribución de interrupciones (una CPU saturada puede caparte)
cr0x@server:~$ grep -i enp65s0 /proc/interrupts | head
72: 1203987 1123340 1189021 1098877 PCI-MSI 524288-edge enp65s0-TxRx-0
73: 23411 21987 24010 22022 PCI-MSI 524289-edge enp65s0-TxRx-1
74: 11234 10988 12001 11102 PCI-MSI 524290-edge enp65s0-TxRx-2
75: 9876 9455 10012 9666 PCI-MSI 524291-edge enp65s0-TxRx-3
Qué significa: Si una cola/CPU toma casi todas las interrupciones, golpearás un techo de CPU antes de la velocidad de línea.
Decisión: Si la distribución está sesgada, arregla RSS/RPS/XPS, revisa irqbalance y asegura que múltiples colas TX/RX estén activas.
Tarea 10: Confirmar salud del pool ZFS y layout básico (no, resilvering no “no importa”)
cr0x@server:~$ sudo zpool status -v tank
pool: tank
state: ONLINE
scan: scrub repaired 0B in 02:31:14 with 0 errors on Sun Dec 22 03:10:18 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
sdg ONLINE 0 0 0
sdh ONLINE 0 0 0
errors: No known data errors
Qué significa: Si estás haciendo resilver, scrub o estás degradado, las conclusiones de rendimiento están contaminadas.
Decisión: Solo realiza pruebas de rendimiento en un pool estable, o optimizarás para un estado de emergencia.
Tarea 11: Medir throughput y latencia de disco en servidor mientras corren clientes
cr0x@server:~$ sudo zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 3.12T 21.8T 210 180 1.15G 320M
raidz2-0 3.12T 21.8T 210 180 1.15G 320M
sda - - 26 22 142M 40M
sdb - - 26 22 144M 39M
sdc - - 26 22 143M 40M
sdd - - 26 22 142M 40M
sde - - 26 22 143M 40M
sdf - - 26 22 143M 40M
sdg - - 26 22 144M 41M
sdh - - 26 22 144M 41M
-------------------------- ----- ----- ----- ----- ----- -----
Qué significa: Si tu pool está leyendo a ~1.15G y tu NIC hace ~9.5 Gbit/s, la red podría ser el límite. Si el ancho del pool está muy por debajo y los dispositivos muestran muchas ops, estás limitado por IOPS/latencia.
Decisión: Si el pool no puede empujar localmente más allá de lo que observas por la red, deja de llamarlo problema de red.
Tarea 12: Medir rendimiento local de almacenamiento con fio (evitar ilusiones de caché)
cr0x@server:~$ sudo fio --name=seqread --directory=/tank/test --rw=read --bs=1M --ioengine=libaio --direct=1 --iodepth=32 --numjobs=1 --size=20G --runtime=30 --time_based
seqread: (g=0): rw=read, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=libaio, iodepth=32
fio-3.33
seqread: (groupid=0, jobs=1): err= 0: pid=28144: Fri Dec 25 10:12:01 2025
read: IOPS=1342, BW=1342MiB/s (1407MB/s)(40.0GiB/30538msec)
slat (usec): min=6, max=214, avg=17.32, stdev=7.11
clat (msec): min=1, max=41, avg=23.76, stdev=4.12
Qué significa: BW local (~1.4 GB/s) excede lo que 10GbE puede llevar. Genial: el almacenamiento puede alimentar el enlace.
Decisión: Si BW local está muy por encima de 1.2 GB/s pero las lecturas por red están muy por debajo, el cuello de botella es red/protocolo/CPU, no discos.
Tarea 13: Medir sensibilidad de escritura síncrona local (veracidad SLOG)
cr0x@server:~$ sudo fio --name=syncwrite --directory=/tank/test --rw=write --bs=16K --ioengine=libaio --direct=1 --iodepth=1 --numjobs=1 --size=5G --runtime=20 --time_based --fsync=1
syncwrite: (g=0): rw=write, bs=(R) 16.0KiB-16.0KiB, (W) 16.0KiB-16.0KiB, (T) 16.0KiB-16.0KiB, ioengine=libaio, iodepth=1
fio-3.33
syncwrite: (groupid=0, jobs=1): err= 0: pid=28410: Fri Dec 25 10:14:44 2025
write: IOPS=820, BW=12.8MiB/s (13.4MB/s)(256MiB/20008msec)
clat (usec): min=340, max=8241, avg=1169.55, stdev=422.12
Qué significa: Las escrituras sync pueden estar brutalmente limitadas por la latencia. El throughput se ve “malo” porque cada escritura espera por durabilidad.
Decisión: Si tu app/protocolo es muy síncrono (bases de datos, imágenes VM, NFS con sync), no saturarás 10GbE sin abordar la latencia de sync (SLOG, ajustes, diseño de la carga).
Tarea 14: Comprobar settings de dataset ZFS que influyen streaming vs cháchara
cr0x@server:~$ sudo zfs get -o name,property,value -s local,default recordsize,atime,compression,sync tank/data
NAME PROPERTY VALUE
tank/data recordsize 1M
tank/data atime off
tank/data compression lz4
tank/data sync standard
Qué significa: recordsize influye la eficiencia secuencial; atime puede añadir escrituras extra; compression puede aumentar el throughput aparente (si los datos son compresibles) o costar CPU.
Decisión: No toques esto hasta que el baseline de red esté probado. Luego afina según carga: archivos grandes quieren recordsize mayor; I/O random pequeño quiere menor y quizá estrategias de vdev/metadev especiales.
Tarea 15: Observar saturación de CPU y presión softirq durante la transferencia
cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.1.0 (server) 12/25/2025 _x86_64_ (32 CPU)
12:16:11 AM CPU %usr %nice %sys %iowait %irq %soft %steal %idle
12:16:12 AM all 12.4 0.0 18.1 0.7 0.0 22.8 0.0 46.0
12:16:12 AM 7 10.0 0.0 21.0 0.0 0.0 65.0 0.0 4.0
12:16:12 AM 15 11.0 0.0 20.0 0.0 0.0 62.0 0.0 7.0
Qué significa: Si una o dos CPUs están casi pegadas en %soft, estás limitado por la pila de red del host, no por la velocidad del enlace. Esto parece “10GbE es lento” pero en realidad es “el host no puede empujar paquetes lo bastante rápido”.
Decisión: Arregla IRQ/RSS, considera CPU más rápida, mejor NIC/driver o ajusta el comportamiento del protocolo (menos operaciones pequeñas, I/O más grande).
Tarea 16: Validar el montaje NFS y comportamiento de export en el cliente
cr0x@client:~$ nfsstat -m
/tank/data from 10.20.30.10:/tank/data
Flags: rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.20.30.41,local_lock=none
Qué significa: Tamaños pequeños de rsize/wsize o versión equivocada pueden atrofiar el throughput. v4.1 con 1M rsize/wsize es generalmente sensato para streaming grandes.
Decisión: Si rsize/wsize son pequeños, corrige opciones de montaje o configuración del servidor. Si usas UDP (raro hoy), deja de hacerlo.
Tarea 17: Observar retransmisiones RPC y comportamiento NFS cliente
cr0x@client:~$ nfsstat -rc
Client rpc stats:
calls retrans authrefrsh
987654 12 0
Client nfs v4:
null read write commit open
0 120034 60012 0 320
Qué significa: Retrans que suben se correlacionan con pérdida de red o sobrecarga del servidor. Mata el throughput porque RPC espera.
Decisión: Si retrans crece durante carga, investiga drops de red o contención de CPU en el servidor; no “aumentes timeo” y lo llames resuelto.
Tarea 18: SMB servidor/cliente: verificar multi-channel y comportamiento de throughput
cr0x@server:~$ sudo smbstatus -b
Samba version 4.18.6
PID Username Group Machine Protocol Version Encryption Signing
-----------------------------------------------------------------------------------------------------------------------------
12011 alice staff 10.20.30.41 (ipv4:10.20.30.41:52144) SMB3_11 - partial(AES-128-GMAC)
Service pid Machine Connected at Encryption Signing
------------------------------------------------------------------------------------------
data 12011 10.20.30.41 Fri Dec 25 00:18:12 2025 - partial(AES-128-GMAC)
Qué significa: Signing/encryption en SMB pueden costar CPU; multi-channel puede o no estar en uso dependiendo de la configuración cliente/servidor.
Decisión: Si la CPU es el limitador y signing/encryption de SMB está habilitado innecesariamente en una LAN de confianza, decide con seguridad si ajustarlo. Si lo necesitas, planifica margen de CPU.
Tarea 19: Rastrear throughput por protocolo vs throughput de NIC (lado servidor)
cr0x@server:~$ sar -n DEV 1 3
Linux 6.1.0 (server) 12/25/2025 _x86_64_ (32 CPU)
00:20:01 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
00:20:02 enp65s0 82000 79000 1150000 180000 0 0 120
00:20:03 enp65s0 83000 80000 1165000 175000 0 0 130
Qué significa: ~1,150,000 kB/s es ~1.15 GB/s recibido. Eso está cerca del techo práctico de payload de 10GbE.
Decisión: Si la NIC está cerca del techo pero los usuarios aún se quejan, probablemente estás saturando el enlace o hay reparto injusto entre clientes. Considera LACP (con cuidado), enlaces más rápidos o QoS—no rituales de recordsize de ZFS.
Tarea 20: Revisar ARC y presión de memoria en ZFS (porque la “cache” oculta problemas)
cr0x@server:~$ sudo arcstat 1 3
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
00:21:10 951 21 2 8 38 13 62 0 0 96G 112G
00:21:11 1002 24 2 9 37 15 63 0 0 96G 112G
Qué significa: Un miss% bajo durante lecturas sugiere que ARC está sirviendo mucho. Tu “prueba de throughput de red” puede ser en realidad una prueba de RAM.
Decisión: Para prueba, usa tests con direct I/O o working sets grandes. Si ARC está haciendo el trabajo, está bien operativamente, pero no atribuyas mal el resultado al rendimiento de disco.
Eso es más de una docena de tareas; usa las que encajen con tu stack. El punto no es coleccionar trivia. El punto es tomar una decisión tras cada comando.
Interpretación de resultados: demostrar el cuello de botella
Cómo se ve un “cuello de botella de red” cuando es real
Puedes declarar que la red es el cuello de botella cuando se cumplen simultáneamente estos puntos:
- iperf3 entre los mismos hosts alcanza ~9.4–9.8 Gbit/s con pocas retransmisiones.
- Almacenamiento local del servidor puede exceder 1.2 GB/s para tu patrón de acceso (o al menos exceder lo que obtienes sobre NFS/SMB).
- Durante acceso real a archivos, la NIC está cerca del techo mientras los discos no están saturados y la CPU no se está ahogando en softirq.
- Estadísticas específicas del protocolo (retrans NFS, bloqueos de crédito SMB, retrans iSCSI) no muestran patologías.
En ese caso, felicitaciones: tu sistema rinde normalmente. Has chocado contra la física y los estándares. La solución es capacidad: más enlaces, enlaces más rápidos o mejor distribución entre múltiples NICs/clientes.
Cómo se ve cuando no es un “cuello de botella de red”
La mayoría de las veces, “10GbE es lento” es uno de estos casos:
Caso A: Pérdida de paquetes y retransmisiones bajo carga
iperf3 puede verse bien en ráfagas cortas, pero transferencias sostenidas muestran drops, retransmisiones y colapso de throughput. Verás TcpRetransSegs en aumento, drops de NIC o descartes en puertos de switch. Esto es un problema de red—aunque el enlace esté negociado a 10Gb.
Culpables comunes: óptica/DAC defectuosos, cable 10GBASE-T marginal, mismatch de MTU causando fragmentación/agujeros negros, agotamiento de buffers del switch y uplinks sobresuscritos.
Caso B: Cuello de botella de CPU/interrupciones en servidor o cliente
La NIC está a 10Gb, pero el host no. %soft alto en una CPU, interrupciones desiguales o un bucle de copia single-thread pueden capar el throughput a 3–6 Gbit/s. Esto es dolorosamente común en CPUs antiguas o con defaults de driver desafortunados.
Caso C: Desajuste protocolo/carga (I/O pequeño sobre protocolo conversador)
10GbE brilla en I/O secuencial grande. Si tu carga es muchas lecturas pequeñas aleatorias, operaciones de metadata o escrituras síncronas, tu throughput estará determinado por IOPS y latencia, no por ancho de banda. Eso no es un cuello de botella de red. Es la realidad de la carga.
Caso D: Latencia de escritura sync en ZFS (y la mitología “SLOG nos salvará”)
Si haces escrituras síncronas, el throughput puede ser ínfimo mientras la red está ociosa. Verás MB/s bajos, pero recuentos de operaciones altos y latencia elevada. Sin un SLOG apropiado (y la expectativa correcta), no arreglas esto con cambios de MTU.
Una cita que deberías mantener en tu canal de incidentes
“La esperanza no es una estrategia.” — idea parafraseada frecuentemente en círculos de ingeniería y operaciones
La cuestión es: mide, aisla, decide.
Broma #2: Si “arreglas” el rendimiento 10GbE deshabilitando checksums, no afinaste un sistema: cometiste un delito contra la realidad.
Tres mini-historias corporativas (dolorosas, reales, útiles)
Mini-historia #1: El outage causado por una suposición equivocada
El equipo tenía un NAS basado en ZFS sirviendo imágenes VM por NFS a un pequeño clúster. Las pruebas de almacenamiento parecían fuertes: lecturas locales muy por encima de 1 GB/s, latencia parecía bien, todos se felicitaron. Entonces llegó el lunes y los boots de VM se arrastraron como una película zombi.
La suposición inmediata fue clásica: “NFS es lento” y “ZFS necesita tuning.” Alguien propuso cambiar recordsize, deshabilitar atime en todas partes (vale, pero irrelevante) y jugar con sync. El equipo de red dijo que los enlaces 10GbE estaban “up”, así que no podían ser ellos.
Un SRE corrió iperf3 y obtuvo 9.7 Gbit/s durante 10 segundos. ¿Caso cerrado? Excepto que el dolor ocurrió bajo carga sostenida. Reejecutaron iperf3 por 10 minutos con múltiples flujos y vieron throughput en sierra. Las retransmisiones subieron. Los contadores del switch mostraron descartes intermitentes.
Causa raíz: el NAS y los hypervisors estaban conectados a través de un par de switches leaf con un uplink que silenciosamente estaba sobresuscrito durante backups. El enlace era técnicamente “10GbE” y “saludable”, pero no estaba disponible cuando hacía falta. La suposición equivocada fue equiparar velocidad negociada con capacidad entregada.
Arreglo: mover tráfico de backup, añadir capacidad donde había contención y añadir alertas básicas sobre descartes del switch y retransmisiones en hosts. Las settings de ZFS quedaron intactas. Los problemas de rendimiento desaparecieron como si nunca hubieran existido.
Mini-historia #2: La optimización que salió mal
Otra compañía tenía un servidor ZFS apoyando almacenamiento compartido de medios por SMB. Querían transferencias más rápidas de archivos de video grandes. Alguien sugirió jumbo frames y aplicó MTU 9000 en el servidor y algunos desktops. El switch “soportaba jumbo”, así que debía estar bien.
Durante un día pareció mejorar. Luego llegaron los tickets: stalls aleatorios, transferencias que se congelaban al 95%, a veces una copia de archivo reiniciaba desde cero. Capturas de Wireshark mostraron retransmisiones TCP y mensajes ICMP “fragmentation needed” que no se entregaban consistentemente.
El problema no eran los jumbo frames como concepto. Era los jumbo frames como religión parcialmente desplegada. Un segmento de switch tenía MTU 9000, otro estaba atascado en 1500 por un interconector antiguo, y un firewall en el path trataba los frames grandes como equipaje sospechoso.
La “optimización” aumentó la probabilidad de blackholing difícil de diagnosticar y volvió el sistema menos fiable. Los promedios de throughput mejoraron en un caso estrecho, pero la latencia de cola y la tasa de fallos de transferencia empeoraron—que es cómo los usuarios perciben el rendimiento.
Arreglo: desplegar jumbo end-to-end con verificación (incluyendo cada salto y VLAN), o volver a 1500 y centrarse en protocolo y layout de disco. Revirtieron, luego mejoraron ajustes SMB y concurrencia cliente. Resultado neto: pico de throughput ligeramente menor, muchas menos interrupciones. Los usuarios dejaron de quejarse, que es la única métrica que importa.
Mini-historia #3: La práctica aburrida pero correcta que salvó el día
Una firma de servicios financieros ejecutaba un appliance ZFS para cargas nocturnas. Nada fancy: NFS, unos pocos enlaces 10GbE y un proceso de cambios estricto. Su arma secreta no era un sysctl mágico. Era disciplina aburrida.
Mantenían un runbook trimestral de “baseline de rendimiento”: iperf3 entre hosts conocidos, un fio local secuencial read/write y una prueba a nivel de protocolo que imitaba producción (mismos mounts, mismas credenciales, misma profundidad de directorios). Archivaban las salidas en un sistema de tickets. Era tan emocionante como ver pintura secarse. A propósito.
Un trimestre, la baseline de iperf3 cayó de cerca de la línea a unos 6 Gbit/s. Nadie se había quejado todavía. Lo trataron como un incendio de todos modos, porque las baselines no mienten sin ayuda.
La investigación encontró que una actualización de BIOS había reseteado defaults de power management PCIe y había empujado la NIC a un estado menos óptimo bajo carga. El cambio no rompió la conectividad; solo redujo el throughput silenciosamente. Gracias a las salidas baseline, pudieron probar la regresión, aislarla y aplicar los ajustes correctos.
La lección: pruebas aburridas, ejecutadas regularmente, detectan problemas antes que tus usuarios. “Pero funcionó el mes pasado” se convierte en “tenemos un diff.” Eso es madurez operativa.
Errores comunes: síntoma → causa raíz → arreglo
1) Síntoma: “Solo obtenemos 3–5 Gbit/s en 10GbE”
Causa raíz: Flujo TCP único limitado (tamaño de ventana, CPU, afinidad de interrupciones), o el cliente no puede seguir el ritmo.
Arreglo: Valida con iperf3 -P 8. Si multi-stream es rápido, ajusta la carga para usar paralelismo (múltiples hilos de copia), arregla IRQ/RSS o mejora CPU/NIC.
2) Síntoma: Throughput sube y luego colapsa cada pocos segundos
Causa raíz: Pérdida de paquetes por microbursts, agotamiento de buffers del switch o uplinks sobresuscritos; TCP retrocede fuertemente.
Arreglo: Revisa descartes del switch y retransmisiones en hosts. Reduce contención, añade ancho de banda o aplica QoS donde corresponda. No toques ZFS primero.
3) Síntoma: Lecturas secuenciales grandes son rápidas, las escrituras son dolorosamente lentas
Causa raíz: Escrituras sync (NFS/VM/bases de datos) limitadas por latencia ZIL; sin SLOG adecuado; o SLOG existe pero no es seguro ante pérdida de energía.
Arreglo: Confirma con tests fio sync y características de la carga. Añade SLOG adecuado solo si tu carga se beneficia, y elige un dispositivo diseñado para baja latencia y protección ante pérdida de energía.
4) Síntoma: “Jumbo frames mejoró un cliente pero rompió otros”
Causa raíz: Mismatch de MTU a lo largo del path, o dominios MTU mixtos sin enrutamiento/PMTUD correcto.
Arreglo: O despliega MTU end-to-end con validación usando ping -M do al tamaño objetivo, o estandariza en 1500.
5) Síntoma: Copia SMB lenta y CPU alta
Causa raíz: Overhead de signing/encryption SMB, comportamiento single-thread del cliente, o CPU del servidor saturada en kernel/pila de red.
Arreglo: Mide CPU y settings SMB. Decide con seguridad si relajar signing/encryption en redes de confianza; si no es posible, dota de CPU y considera cambios de protocolo.
6) Síntoma: NFS se cuelga y aparecen mensajes “server not responding”
Causa raíz: Drops/retrans de red, servidor sobrecargado, o picos de latencia en almacenamiento causando timeouts RPC.
Arreglo: Revisa retrans NFS, retrans TCP y latencia del servidor. Incrementa timeo solo después de arreglar la causa, no como sedante.
7) Síntoma: Gran rendimiento en sintéticos, malo en producción
Causa raíz: Benchmarks usan ARC, evitan metadata o usan I/O secuencial distinto a la carga real.
Arreglo: Prueba con working set mayor que RAM, usa --direct=1 en fio y mimetiza tamaño de I/O y concurrencia.
8) Síntoma: Añadiste LACP pero un solo cliente aún no pasa de ~10GbE
Causa raíz: LACP no aumenta throughput para un solo flujo; el hashing asigna flujos a un único miembro del enlace.
Arreglo: Usa múltiples sesiones/clientes, SMB multichannel, sesiones NFS, o pasa a enlaces más rápidos (25/40/100GbE) si se requiere throughput por cliente único.
Listas de verificación / plan paso a paso
Plan paso a paso para probar (no adivinar) el cuello de botella
- Congela el campo de batalla: asegúrate de no tener resilver/scrub, ni tareas de fondo importantes, y prueba en una ventana controlada.
- Registra la topología: cliente ↔ puertos de switch ↔ VLAN ↔ puerto del servidor. Si no puedes dibujarlo, no podrás depurarlo.
- Valida enlace y PCIe:
ethtool,lspci, contadores de error, drops. - Ejecuta baseline iperf3: flujo único, luego multi-stream, luego dirección inversa. Captura retrans antes y después.
- Valida política MTU: o 1500 en todas partes o jumbo en todas partes. Prueba con
ping -M do. - Mide almacenamiento local: fio secuencial read/write con
--direct=1; opcionalmente test de sync write si aplica. - Mide el protocolo real: NFS/SMB/iSCSI con una prueba representativa. Mantén reproducibilidad.
- Correlaciona durante la prueba: servidor
zpool iostat, throughput NIC (sar), softirq CPU (mpstat), retrans cliente (nstat). - Toma la decisión: elige el punto más estrecho soportado por los datos. Escríbelo con las salidas adjuntas.
- Cambia una cosa: vuelve a ejecutar la misma prueba. Si cambiaste tres cosas, no aprendiste nada.
Checklist: señales de que realmente estás limitado por la red (la checklist de “deja de tunear ZFS”)
- iperf3 estable cerca de la velocidad de línea con pocas retransmisiones
- Throughput de NIC cerca de 1.1–1.2 GB/s durante lecturas/escrituras de archivos
- Pool ZFS no saturado (ancho de banda y ops de disco no al máximo)
- CPU no pegada en softirq o en un solo core
- Estadísticas del protocolo limpias (sin picos de retrans NFS, sin stalls SMB)
Checklist: señales de que el cuello de botella es el host/protocolo
- iperf3 rápido con múltiples streams pero lento en flujo único
- %soft alto o interrupciones sesgadas durante transferencias
- Baja utilización de NIC mientras los usuarios esperan
- Carga con muchas escrituras sync y bajo MB/s pero alta latencia por operación
- Alta tasa de paquetes (pps) con I/O pequeño y operaciones de metadata
Preguntas frecuentes
1) ¿Qué throughput debo esperar de 10GbE para una copia de archivo grande?
En una LAN limpia, espera aproximadamente 1.0–1.2 GB/s de payload en el mejor caso. Si ves ~800–1100 MB/s en transferencias secuenciales grandes, probablemente estás bien.
2) ¿Por qué iperf3 muestra 9.8 Gbit/s pero la copia SMB solo 400 MB/s?
Porque la tubería de red está sana, y algo por encima no lo está: costo CPU de signing/encryption SMB, patrón de I/O pequeño, single-thread del cliente, softirq del servidor o comportamiento sync de ZFS. Mide CPU y estadísticas del protocolo durante la copia.
3) ¿Los jumbo frames siempre ayudan al rendimiento NAS ZFS?
No. Pueden reducir carga de CPU para altas tasas de paquetes, pero también crean modos de fallo si el path no está configurado consistentemente. Si no puedes probar MTU end-to-end, usa 1500 y sigue adelante.
4) ¿Debo desactivar offloads de la NIC para “arreglar rendimiento”?
Sólo si tienes evidencia de que están causando drops/retransmisiones o picos de latencia con tu driver/firmware específico. Alterna una característica a la vez y vuelve a probar. Desactivar todo en bloque suele aumentar uso de CPU y reducir throughput.
5) ¿Es LACP la respuesta para saturar 10GbE?
LACP incrementa ancho de banda agregado a través de múltiples flujos, no suele mejorar un flujo único. Si un cliente necesita >10Gb/s, quieres un enlace más rápido (25/40/100GbE) o un protocolo/cliente que use múltiples canales.
6) ¿La compresión de ZFS puede mejorar el throughput de red?
A veces, sí. Si tus datos se comprimen bien, el servidor envía menos bytes por la red, así que el throughput efectivo aumenta. Pero pagas CPU. Mide throughput y CPU antes de declarar victoria.
7) ¿Cómo sé si estoy limitado por escrituras síncronas?
Si el throughput de escritura es bajo, la latencia es alta y tests con fsync o cargas de bases de datos se comportan igual, probablemente estás limitado por la latencia de durabilidad. Añadir SLOG adecuado puede ayudar, pero solo para escrituras sync y solo si el dispositivo es apropiado.
8) ¿Por qué varía el rendimiento según la hora del día?
Usualmente por contención: uplinks de switch sobresuscritos, ventanas de backup, replicación o vecinos ruidosos en infraestructura compartida. Demúestralo correlacionando caídas de throughput con retransmisiones y descartes de puerto de switch durante esas ventanas.
9) ¿Cómo mantengo honestas las pruebas cuando ARC hace que todo parezca increíble?
Usa working sets mayores que la RAM, usa fio --direct=1 y repite ejecuciones tras calentamiento de cache con tamaños controlados. No midas memoria y lo llames almacenamiento.
10) Si realmente estoy limitado por la red, ¿cuáles son las mejores vías de mejora?
Añade ancho de banda (25GbE es un paso común), añade paralelismo (múltiples NICs/clientes) o divide cargas entre interfaces. La elección correcta depende de si necesitas velocidad por cliente o capacidad agregada multi-cliente.
Siguientes pasos que puedes hacer esta semana
- Ejecuta y guarda tres baselines: iperf3 (single + multi-stream), fio local secuencial read, y una prueba a nivel de protocolo (NFS/SMB) que coincida con producción.
- Añade dos alertas: retransmisiones TCP del host (cliente/servidor) y descartes/drops de puertos de switch en los puertos que miran al NAS.
- Decide tu política MTU: 1500 en todas partes o jumbo en todas partes. Documenta y hazla cumplir.
- Elige un cuello de botella para arreglar: pérdida de paquetes, softirq de CPU, latencia de escrituras sync, o saturación real del enlace. No intentes arreglarlos todos con un sysctl mágico.
- Escribe la prueba: pega salidas de comandos en tu ticket. Tu yo futuro agradecerá al yo presente cuando alguien diga “siempre ha sido así”.
Si haces las pruebas de aislamiento y los números aún no tienen sentido, eso no es fracaso. Es datos que dicen que el sistema real es más interesante que el diagrama. Bienvenido a producción.