Por qué no escribimos nuestro propio sensor eBPF
Beyla ya resuelve la parte difícil, tediosa y perpetua del tracing a nivel kernel. Reconstruirla nos hubiera costado lo único que no podemos recuperar.
23 de junio de 2026 · 6 min de lectura
El agente de runtime necesita saber qué tan rápido responde un servicio y con qué frecuencia falla, sin tocar la aplicación. Esa es una oración fácil de escribir en un pitch deck. Sacarla de un proceso vivo sin un SDK, sin un sidecar, sin un reinicio es un problema distinto, y durante las primeras semanas de construir el agente asumimos que lo íbamos a resolver nosotros mismos.
El plan era simple en el papel: uprobes en SSL_write/SSL_read para el tráfico TLS, kprobes en tcp_sendmsg para el resto, parsear el framing de HTTP y gRPC en un programa eBPF chico, y emitir métricas RED (rate, errors, duration) sin que el proceso observado se entere de que lo estamos mirando. Tuvimos una prueba de concepto funcionando contra un servidor HTTP en Go simple en menos de una semana. Después la apuntamos a un servicio Spring Boot real y se cayó.
Dónde se rompe en realidad
No en el verifier de eBPF — esa parte está genuinamente bien diseñada, y el kernel rechaza un programa que pueda loopear o crashear mucho antes de que corra. Se rompe en el límite del userspace, en la parte que nadie cuenta en la charla de la conferencia: los offsets de los uprobes son función del build exacto de la librería. El offset de SSL_write para OpenSSL 3.0.2 en Ubuntu 22.04 no es el offset de OpenSSL 3.0.13 en la misma distro seis meses después, y es otro número distinto en el build linkeado con musl de Alpine, y otro distinto de nuevo cuando estás dentro de una JVM haciendo su propio TLS a través de un provider embebido en vez del del sistema. Multiplicá eso por cada runtime de lenguaje, cada imagen base de contenedor, cada versión menor que un cliente esté corriendo, y te queda una matriz de offsets que necesita re-derivación constante y un banco de pruebas para kernels que no controlás.
Nada de esto es un problema de investigación. Es un problema de mantenimiento, para siempre, y no se termina cuando lo lanzás — cada release menor de OpenSSL es una regresión potencial de la que te enterás por un mensaje de Slack de un cliente en vez de por tu propio CI.
Por qué elegimos Beyla en su lugar
Beyla (el proyecto de instrumentación eBPF de Grafana Labs) ya carga con esa carga de mantenimiento, en abierto, con una comunidad de gente cuyo trabajo de tiempo completo es perseguir el drift de kernel y librerías en los mismos entornos que nosotros terminaríamos descubriendo cliente por cliente. Nos da métricas RED por servicio — tasa de requests, tasa de errores, duración p50/p99 — con cero código en la aplicación observada. Nos queda margen para gastar nuestro propio presupuesto de eBPF en la parte que realmente es nuestra: procnet, nuestro propio colector que lee /proc/<pid>/net/tcp para mapear conexiones TCP en vivo a contenedores, una superficie más angosta y más estable que parsear protocolos de capa 7 en el kernel.
El costo honesto de esta decisión es que hoy el agente se distribuye como dos contenedores en vez de uno — el nuestro, y el de Beyla, ambos con privilegios elevados en el host. Eso es fricción en la que estamos trabajando activamente (empaquetar Beyla como proceso hijo supervisado del binario del agente es el próximo paso), pero es un problema de UX que resolver, no una apuesta de ingeniería que tengamos que ganarle a un objetivo en movimiento. Preferimos mostrar esa fricción con honestidad antes que aparentar que construimos algo que no construimos.
La regla con la que terminamos
Construí lo que es realmente tu producto. Para nosotros eso es el grafo: la resolución de entidades que le da a "el servicio de orders" la misma identidad ya sea que se lo vea desde un Dockerfile, un contenedor corriendo, o una conexión TCP, y la lógica de correlación que decide si una dependencia es real. eBPF en el límite de la ABI del kernel, a través de cada lenguaje y cada imagen base de contenedor que un cliente pueda llegar a correr, ya es el trabajo de tiempo completo de otra gente — y son buenos en eso.
¿Querés verlo en tu propio sistema?
Con la URL de un repositorio alcanza para el grafo estático. El agente de runtime necesita un solo archivo docker-compose.
