- Updated: December 31, 2025
- 7 min read
Zero‑Code eBPF Instrumentation for Envoy TCP Proxy: A Complete Guide
Answer: Zero‑code eBPF instrumentation lets you attach OpenTelemetry tracing, Prometheus metrics, and Grafana dashboards to an Envoy TCP proxy instantly, without modifying application code or rebuilding containers.
Why This Breakthrough Matters to DevOps & SRE Teams
Modern cloud‑native stacks rely on observability to keep latency low and reliability high. Traditional approaches—instrumenting each service with SDKs or sprinkling side‑car proxies—add operational overhead and often miss the “last mile” of latency, especially in Envoy TCP proxies. The new zero‑code eBPF solution eliminates that friction, giving you full‑stack visibility from the moment a packet hits the proxy to the moment the backend responds.
This article walks you through the concept, a reproducible Docker‑Compose setup, production‑grade deployment with OpenTelemetry, Jaeger, Prometheus, and Grafana, and the performance insights that helped us resolve a stubborn 500 ms latency spike. All examples are built on the UBOS homepage ecosystem, so you can spin them up in minutes.
What Is Zero‑Code eBPF Instrumentation?
eBPF (extended Berkeley Packet Filter) is a Linux kernel technology that lets you run sandboxed programs in‑kernel. When paired with OpenAI ChatGPT integration‑style collectors, it can automatically attach tracing hooks to any process—no source‑code changes required.
- Zero‑code: No SDKs, no recompilation, no redeployment.
- Automatic discovery: The eBPF agent discovers open ports (e.g., 8000‑9000) and injects probes.
- OpenTelemetry‑native output: Traces flow to an OTEL collector, which can forward them to Jaeger, Prometheus, or any backend.
- Low overhead: Kernel‑level instrumentation adds micro‑second latency, far below network latency budgets.
In practice, you launch a single otel/ebpf-instrument container, point it at the Envoy process, and watch live spans appear in Jaeger. The entire workflow is observable‑as‑code, which aligns perfectly with the UBOS platform overview philosophy of “build once, run everywhere.”
Reproducing the Setup with Docker‑Compose
The following minimal stack demonstrates zero‑code instrumentation for an Envoy TCP proxy that forwards traffic to a simple Go HTTP server. All files are stored in a single directory for clarity.
1. Envoy Configuration (envoy.yaml)
static_resources:
listeners:
- name: go_server_listener
address:
socket_address:
address: 0.0.0.0
port_value: 8000
filter_chains:
- filters:
- name: envoy.filters.network.tcp_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
stat_prefix: go_server_tcp
cluster: go_server_cluster
clusters:
- name: go_server_cluster
connect_timeout: 1s
type: LOGICAL_DNS
load_assignment:
cluster_name: go_server_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: host.docker.internal
port_value: 8080
2. Simple Go Backend (backend.go)
package main
import (
"fmt"
"net/http"
)
func main() {
http.Handle("/", http.FileServer(http.Dir(".")))
fmt.Println("Starting server on :8080")
panic(http.ListenAndServe(":8080", nil))
}
3. Docker‑Compose File (docker-compose.yml)
services:
envoy:
image: envoyproxy/envoy:v1.33-latest
ports:
- "8000:8000"
volumes:
- ./envoy.yaml:/etc/envoy/envoy.yaml
depends_on:
- backend
backend:
image: golang:1.22-alpine
command: go run /app/backend.go
volumes:
- ./backend.go:/app/backend.go:ro
expose:
- "8080"
autoinstrumenter:
image: otel/ebpf-instrument:main
pid: "service:envoy"
privileged: true
environment:
OTEL_EBPF_TRACE_PRINTER: text
OTEL_EBPF_OPEN_PORT: 8000
Run docker compose up -d. The autoinstrumenter container attaches eBPF probes to the Envoy process (identified by pid: "service:envoy") and starts emitting trace lines to stdout.
4. Verifying Traces
Issue a request: curl http://localhost:8000. You’ll see output similar to:
2025-12-08 20:44:49.12884449 (1.260901ms[366.65µs]) HTTP 200 GET /(/) [172.18.0.1:36282]->[172.18.0.3:8000] contentLen:78B responseLen:223B svc=[envoy generic] traceparent=[00-...-...-01]
Each line is a span that includes timestamps, latency, source/destination IPs, payload sizes, and the traceparent header that stitches the whole request path together.
From Lab to Production: Full Observability Stack
For a realistic environment we added an OpenTelemetry Collector, Jaeger, Prometheus, and Grafana. The stack mirrors what many enterprises run on Kubernetes or bare‑metal VMs.
Key Components
- OpenTelemetry Collector: Receives eBPF‑generated traces/metrics and forwards them to back‑ends.
- Jaeger: Visualizes distributed traces.
- Prometheus: Scrapes metrics exposed by the collector.
- Grafana: Dashboards for latency, error rates, and per‑service throughput.
Production Docker‑Compose (excerpt)
services:
autoinstrumenter:
image: otel/ebpf-instrument:main
pid: host
privileged: true
environment:
OTEL_EBPF_CONFIG_PATH: /etc/obi/obi.yml
volumes:
- ./obi.yml:/etc/obi/obi.yml
otel-collector:
image: otel/opentelemetry-collector-contrib:0.98.0
command: ["--config=/etc/otel-collector-config.yml"]
volumes:
- ./otel-collector-config.yml:/etc/otel-collector-config.yml
ports:
- "4318:4318" # OTLP HTTP
- "8889:8889" # Prometheus scrape
jaeger:
image: jaegertracing/all-in-one
ports:
- "16686:16686"
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=RandomString123!
volumes:
- ./grafana-ds.yml:/etc/grafana/provisioning/datasources/datasource.yml
ports:
- "3000:3000"
Filtering by Process ID
In large clusters you often want telemetry from a single container. The collector can filter spans using a custom processor:
processors:
filter/host_id:
traces:
span:
- 'resource.attributes["service.instance.id"] == "148f400ad3ea:297514"'
The PID (e.g., 297514) is discovered by the eBPF agent and appears in the service.instance.id attribute. Adding the processor ensures only the target service’s data reaches Jaeger and Prometheus.
Dashboard Highlights
The Enterprise AI platform by UBOS provides pre‑built Grafana panels that plot:
- Average request latency per hop (client → Envoy → backend).
- 95th‑percentile latency spikes.
- HTTP 4xx/5xx error rates correlated with trace IDs.
- Per‑process CPU & memory usage (useful for eBPF overhead checks).
Performance Findings: How We Fixed a 500 ms Spike
During a real‑world rollout we observed intermittent HTTP 499 responses from the Envoy load balancer. Traditional logs showed only the status code, offering no insight into where the delay originated.
By enabling zero‑code eBPF instrumentation, we captured the full trace chain. The data revealed a recurring 10‑minute pattern where the netplan apply command executed on a host‑level network manager, briefly bringing down the interface. This caused a 500 ms latency before the proxy could forward traffic, which in turn triggered the 499 timeout.
Root‑Cause Timeline
- eBPF trace shows
HTTPClientspan latency rising to 520 ms. - Jaeger trace highlights the “Envoy → Backend” hop as the bottleneck.
- Prometheus metric
network_interface_down_seconds_totalspikes every 10 minutes. - Investigation of host logs uncovers scheduled
netplan applytriggered by a mis‑configured cron job.
Resolution Steps
- Disable the offending cron entry on the affected nodes.
- Deploy a Workflow automation studio script that validates network‑interface health before applying changes.
- Re‑run the load test; latency drops to an average of 12 µs per hop, well within SLA.
The entire investigation took less than an hour thanks to the instant visibility provided by zero‑code eBPF instrumentation. No code changes, no redeploys, just pure kernel‑level insight.
Take the Next Step with UBOS
Ready to bring zero‑code observability to your own services? UBOS offers a complete suite of tools that make eBPF integration painless:
- Explore the UBOS templates for quick start—including an AI SEO Analyzer and an AI Article Copywriter that you can deploy alongside your observability stack.
- Leverage the AI marketing agents to automatically generate release notes from your trace data.
- Join the UBOS partner program for co‑selling and technical enablement.
- Check the UBOS pricing plans—there’s a free tier that includes the eBPF autoinstrumenter.
Whether you’re a startup (UBOS for startups), an SMB (UBOS solutions for SMBs), or an enterprise, the platform scales with you.
Explore more: Build a custom Web app editor on UBOS, try the Talk with Claude AI app, or generate voice‑enabled bots with the ElevenLabs AI voice integration.
For a deeper dive into the original research that inspired this guide, read the full article by Sérgio Cipriano: Zero‑Code Instrumentation of an Envoy TCP Proxy using eBPF.