eBPF y NetFlow para monitoreo de tráfico: Desde servidores bare metal hasta Kubernetes
Un sistema basado en eBPF/XDP y NetFlow ofrece telemetría de red detallada en todas las capas, desde servidores físicos hasta clústeres de Kubernetes. Superó las limitaciones de sFlow/NetFlow tradicionales, como el alto costo de hardware, la muestreo y la falta de campos personalizados. El tráfico se procesa a través de una interfaz unificada router-on-a-stick, permitiendo que XDP capture paquetes entrantes sin modificar el kernel.
eBPF ejecuta programas directamente en el núcleo del sistema operativo con seguridad y latencia mínima, ideal para monitoreo en tiempo real. Se recopilan estadísticas por 5-tupla (direcciones IP, puertos, protocolo), bytes y paquetes, exportándose luego en formato NetFlow para recolectores.
Elección de mapas BPF para alto rendimiento
Los mapas BPF almacenan estadísticas como tablas clave-valor: la clave es la 5-tupla, el valor son contadores. Las pruebas revelaron problemas con BPF_MAP_TYPE_HASH:
- Contención de bloqueos bajo acceso multi-hilo desde múltiples núcleos.
- Condición de carrera que provocaba contadores inexactos.
Las operaciones atómicas (__sync_fetch_and_add) eliminan errores, pero reducen el rendimiento por la sobrecarga de sincronización.
Cambiar a BPF_MAP_TYPE_PERCPU_HASH crea un mapa separado por cada núcleo de CPU, eliminando bloqueos. La agregación ocurre en espacio de usuario. Las pruebas en 100 núcleos bajo cargas variables confirmaron que los mapas PERCPU superan a otros.
Cuando están llenos (600K 5-tuplas en un mapa de 60K entradas), BPF_MAP_TYPE_LRU_PERCPU_HASH elimina entradas antiguas, pero con un costo. El tipo PERCPU_HASH sigue siendo preferido para lecturas rápidas y puntuales.
// Determinar qué mapa escribir
#define SHARD_COUNT 25 // número de fragmentos
map_hash_idx = ctx->rx_queue_index % SHARD_COUNT + shard_offset;
Fragmentación de mapas y exportación multi-hilo
Un solo mapa con 10M registros se convertía en cuello de botella para un exportador mono-hilo. Fragmentarlo en 25 mapas (basado en rx_queue_index mediante RSS) permitió lectura paralela, acelerando el procesamiento 3 veces.
Ventajas de la fragmentación:
- Escalabilidad: añadir mapas sin reiniciar.
- Paralelismo: sensores leen múltiples mapas simultáneamente.
- Eficiencia de caché: mapas pequeños caben en L1/L2.
El sensor escrito en Go (con bibliotecas Cilium) aprovecha BPF_MAP_LOOKUP_AND_DELETE_BATCH para leer y vaciar mapas cada minuto, minimizando pérdidas durante desbordamientos.
Muestreo y adaptación dinámica de carga
Para equilibrar el rendimiento de reenvío con las necesidades de telemetría, se implementa muestreo. Un segundo stats_map (BPF_MAP_TYPE_HASH, max_entries=128) rastrea paquetes por fragmento:
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 128); // Número máximo de fragmentos
__type(key, __u32); // ID del fragmento
__type(value, __u64); // Contadores de paquetes/bytes
__uint(pinning, LIBBPF_PIN_BY_NAME);
} stats_map SEC(".maps");
Los temporizadores de eBPF calculan periódicamente el throughput (paquetes/segundo) y activan el muestreo cuando se superan umbrales por fragmento. Los temporizadores ejecutan tareas en segundo plano fuera del contexto de paquetes: agregan datos y reinician contadores.
Esto mantiene la estabilidad durante picos de tráfico (como DDoS) preservando la telemetría a nivel de sesión.
Adaptación a virtualización y Kubernetes
La arquitectura bare metal se escala sin problemas a entornos virtualizados y Kubernetes. En clústeres K8s, eBPF/XDP se ejecuta como DaemonSet, capturando tráfico de pods mediante CNI. La fragmentación se adapta a la afinidad de nodos; PERCPU_HASH se alinea con vCPUs.
La exportación de NetFlow agrega metadatos (namespace, IP del pod), mejorando la observabilidad de microservicios.
Conclusiones clave:
- PERCPU_HASH elimina la contención de bloqueos, aumentando el rendimiento 2–3x frente a HASH.
- La fragmentación acelera la exportación 3x gracias al paralelismo.
- Temporizadores eBPF + muestreo equilibran la carga sin sacrificar el reenvío.
- La variante LRU conviene en escenarios dinámicos con desbordamientos.
- El sensor en Go con bibliotecas Cilium destaca en análisis de alto rendimiento.
— Editorial Team
Aún no hay comentarios.