cloudflare/ebpf_exporter
Go
Captured source
source ↗cloudflare/ebpf_exporter
Description: Prometheus exporter for custom eBPF metrics
Language: Go
License: MIT
Stars: 2589
Forks: 276
Open issues: 16
Created: 2018-04-24T01:24:39Z
Pushed: 2026-06-02T03:24:21Z
Default branch: master
Fork: no
Archived: no
README:
ebpf_exporter
Prometheus exporter for custom eBPF metrics and OpenTelemetry traces.
- Metrics:

- [Traces](./tracing):

Motivation of this exporter is to allow you to write eBPF code and export metrics that are not otherwise accessible from the Linux kernel.
ebpf.io describes eBPF:
> eBPF is a revolutionary technology with origins in the Linux kernel that can > run sandboxed programs in a privileged context such as the operating system > kernel. It is used to safely and efficiently extend the capabilities of the > kernel without requiring to change kernel source code or load kernel modules.
An easy way of thinking about this exporter is bcc tools as prometheus metrics:
- https://iovisor.github.io/bcc
We use libbpf rather than legacy bcc driven code, so it's more like libbpf-tools:
- https://github.com/iovisor/bcc/tree/master/libbpf-tools
Producing OpenTelemetry compatible traces is also supported, see [Tracing docs](./tracing/) for more information on that.
Reading material
- https://www.brendangregg.com/ebpf.html
- https://nakryiko.com/posts/bpf-core-reference-guide/
- https://nakryiko.com/posts/bpf-portability-and-co-re/
- https://nakryiko.com/posts/bcc-to-libbpf-howto-guide/
- https://libbpf.readthedocs.io/en/latest/program_types.html
Building and running
Actual building
To build a binary, clone the repo and run:
make build
The default build target makes a static binary, but you could also use the build-dynamic target if you'd like a dynamically linked binary. In either case libbpf is built from source, but you could override this behavior with BUILD_LIBBPF=0, if you want to use your system libbpf.
If you're having trouble building on the host, you can try building in Docker:
docker build --tag ebpf_exporter --target ebpf_exporter . docker cp $(docker create ebpf_exporter):/ebpf_exporter ./
To build examples (see [building examples section](#building-examples)):
make -C examples clean build
To run with [biolatency](examples/biolatency.yaml) config:
sudo ./ebpf_exporter --config.dir=examples --config.names=biolatency
If you pass --debug, you can see raw maps at /maps endpoint and see debug output from libbpf itself.
Docker image
A docker image can be built from this repo. A prebuilt image with examples included is also available for download from GitHub Container Registry:
- https://github.com/cloudflare/ebpf_exporter/pkgs/container/ebpf_exporter
To build the image with just the exporter binary, run the following:
docker build --tag ebpf_exporter --target ebpf_exporter .
To run it with the examples, you need to build them first (see above). Then you can run by running a privileged container and bind-mounting:
$(pwd)/examples:/examples:roto allow access to examples on the host/sys/fs/cgroup:/sys/fs/cgroup:roto allow resolving cgroups
You might have to bind-mount additional directories depending on your needs. You might also not need to bind-mount anything for simple kprobe examples.
The actual command to run the docker container (from the repo directory):
docker run --rm -it --privileged -p 9435:9435 \ -v $(pwd)/examples:/examples \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ ebpf_exporter --config.dir=examples --config.names=timers
For production use you would either bind-mount your own config and compiled bpf programs corresponding to it, or build your own image based on ours with your own config baked in.
For development use when you don't want or have any dev tools on the host, you can build the docker image with examples bundled:
docker build --tag ebpf_exporter --target ebpf_exporter_with_examples .
Some examples then can run without any bind mounts:
docker run --rm -it --privileged -p 9435:9435 \ ebpf_exporter --config.dir=examples --config.names=timers
Or with the publicly available prebuilt image:
docker run --rm -it --privileged -p 9435:9435 \ ghcr.io/cloudflare/ebpf_exporter --config.dir=examples --config.names=timers
Kubernetes Helm chart
A third party helm chart is available here:
- https://github.com/kubeservice-stack/kubservice-charts/tree/master/charts/kubeservice-ebpf-exporter
Please note that the helm chart is not provided or supported by Cloudflare, so do your own due diligence and use it at your own risk.
Benchmarking overhead
See [benchmark](benchmark) directory to get an idea of how low ebpf overhead is.
Required capabilities
While you can run ebpf_exporter as root, it is not strictly necessary. Only the following two capabilities are necessary for normal operation:
CAP_BPF: required for privileged bpf operations and for reading memoryCAP_PERFMON: required to attach bpf programs to kprobes and tracepoints
If you are using systemd, you can use the following configuration to run as on otherwise unprivileged dynamic user with the needed capabilities:
DynamicUser=true AmbientCapabilities=CAP_BPF CAP_PERFMON CapabilityBoundingSet=CAP_BPF CAP_PERFMON
Prior to Linux v5.8 there was no dedicated CAP_BPF and CAP_PERFMON, but you can use CAP_SYS_ADMIN instead of your kernel is older.
If you pass --capabilities.keep=none flag to ebpf_expoter, then it drops all capabilities after attaching the probes, leaving it fully unprivileged.
The following additional capabilities might be needed:
CAP_SYSLOG: if you useksymdecoder to have access to/proc/kallsyms.
Note that you must keep this capability: --capabilities.keep=cap_syslog. See: https://elixir.bootlin.com/linux/v6.4/source/kernel/kallsyms.c#L982
CAP_IPC_LOCK: if you useperf_event_arrayfor reading from the kernel.
Note that you must keep it: --capabilities.keep=cap_perfmon,cap_ipc_lock.
CAP_SYS_ADMIN: if you want BTF information from modules.
See: https://github.com/libbpf/libbpf/blob/v1.2.0/src/libbpf.c#L8654-L8666 and https://elixir.bootlin.com/linux/v6.5-rc1/source/kernel/bpf/syscall.c#L3789
CAP_NET_ADMIN: if you use net admin related programs like xdp.
See:...
Excerpt shown — open the source for the full document.