What is eBPF?

The Linux kernel is the foundation of modern computing. It controls hardware, enforces isolation and security, and enables all software to run on a machine in an orderly, safe way. In most development use cases, the Kernel remains untouched. But when there is a need for deep system visibility, strict enforcement, ultra-low-latency performance, or support for new hardware or security models, the Kernel requires direct interactions.

Before eBPF, this involved significant hurdles, like modifying kernel source code, recompiling, or developing potentially unstable kernel modules. The result was slow innovation, high operational risk, and a very high barrier to entry for anyone who wanted to build deep system-level capabilities.

eBPF changed that.

eBPF (extended Berkeley Packet Filter) is a revolutionary technology that makes the Linux kernel programmable. It allows developers to dynamically inject custom logic into the operating system at runtime and execute programs safely and efficiently within the kernel’s privileged environment, all without altering the kernel’s source code or loading new kernel modules.

This capability now provides new levels of flexibility, performance, and insight into system operations.

FeatureTraditional Kernel ModuleeBPF Program
SafetyHigh risk (Kernel Panic)Guaranteed (Verifier)
DeploymentRequires reboot/recompileLoaded at runtime
SpeedNativeNear-native (via JIT)
ComplexityExtremely HighModerate (Standard Tooling)

How Does eBPF Work?

Below is the lifecycle of an eBPF program, from its creation in user space to its execution within the kernel:

  1. Development in User Space: eBPF kernel-side programs are typically written in restricted C or Rust, while the user-space controllers are often written in Go, Python, or C++. Developers use a restricted set of functions and types that adhere to the eBPF kernel API. These programs are designed to be concise and perform specific tasks.
  2. Compilation to Bytecode: Once written, the program is compiled into eBPF bytecode. This is usually done using specialized compilers like LLVM/Clang, which target the eBPF virtual instruction set architecture (ISA). This bytecode is a platform-agnostic, low-level representation of the program.
  3. Loading into the Kernel: The compiled eBPF bytecode is then loaded into the Linux kernel using the bpf() system call.
  4. The eBPF Verifier: Kernel’s Gatekeeper: Before an eBPF program is allowed to execute, it must pass a rigorous security and safety check by the eBPF Verifier. This component performs static analysis on the bytecode to ensure several vital properties:
    • Termination: The program must always terminate, modern eBPF allows bounded loops, the verifier ensures they cannot run indefinitely.
    • Memory Safety: It must not access arbitrary memory locations or out-of-bounds memory.
    • Resource Limits: It must adhere to predefined complexity and instruction limits.
    • Security: It must not attempt to use uninitialized variables or perform other operations that could compromise kernel integrity. The verifier is the cornerstone of eBPF’s safety, preventing malicious or buggy programs from crashing the kernel.
  5. JIT Compilation: If the program passes verification, the kernel’s Just-In-Time (JIT) compiler translates the eBPF bytecode into native machine instructions specific to the host CPU architecture (x86, ARM, etc.). This step is for performance, ensuring that eBPF programs run at near-native speed, comparable to compiled kernel code.
  6. Attaching to Hooks & Events: An eBPF program doesn’t run arbitrarily; it needs an “event” to trigger its execution. These events are called hooks, and they are strategically placed throughout the kernel. Examples of hooks include:
    • System Calls: Executing a specific system call (e.g., open, read, write).
    • Network Events: Packet ingress/egress, socket operations.
    • Tracepoints: Predefined instrumentation points within the kernel.
    • Kprobes/Uprobes: Dynamic instrumentation points attached to arbitrary kernel or user space functions. When a hooked event occurs, the associated eBPF program executes its logic within the kernel context, processing data related to that event.
  7. eBPF Maps: Sharing State: eBPF programs can’t directly communicate with user space processes or other eBPF programs using standard inter-process communication (IPC) mechanisms. Instead, they use eBPF Maps. These are highly optimized key-value data structures that reside in the kernel and can be accessed by both eBPF programs (for reading and writing) and user space applications (for reading, writing, and displaying results). Maps enable persistent state, configuration, and efficient data exchange.

Here’s what the eBPF program process looks like:

eBPF Use Cases

eBPF’s versatility has led to its rapid adoption across a wide range of domains. Its primary impact can be categorized into three pillars:

1. Observability

eBPF provides deep visibility into system performance and application behavior with minimal overhead.

  • System Tracing: By attaching to kprobes, tracepoints, and syscalls, eBPF programs can monitor nearly any kernel event, providing detailed insights into CPU usage, memory access patterns, disk I/O, network activity, and process interactions.
  • Application-Level Observability: Uprobes allow eBPF to trace functions within user space applications, offering insights into application logic, performance bottlenecks, and resource consumption without needing to modify application code.
  • Dynamic Profiling: Tools built on eBPF can dynamically profile entire systems, identifying hot spots in both kernel and user space with incredible granularity.

Case Study: Logz.io & eBPF

Logz.io leverages eBPF to help users gain observability into Kubernetes clusters. It deploys an agent as a DaemonSet to insert bytecode into the Linux kernel, relying on the kernel’s inherent verification process to ensure the code is sandboxed and will not compromise system stability.

Once loaded, the program attaches to specific kernel hooks, such as network interfaces and system calls, to instantly capture events like HTTP requests, database queries, and gRPC calls without touching the application code.

Finally, during the execution phase, the agent propagates OpenTelemetry context via headers and exporting the generated spans to the Logz.io “App 360” interface for visualization. Read more here.

2. Networking

eBPF revolutionizes network programmability, enabling extremely high-performance and flexible network functionality directly within the kernel.

  • eXpress Data Path (XDP): XDP allows eBPF programs to process network packets at the earliest possible point on the network interface card (NIC), even before the kernel’s network stack fully processes them. This enables astonishing packet processing speeds, ideal for DDoS mitigation, load balancing, and custom firewalls.
  • Advanced Traffic Control: eBPF enhances traditional Linux traffic control (tc) filters, allowing for more complex packet manipulation, routing, and policy enforcement.
  • Service Mesh & Load Balancing: Projects like Cilium leverage eBPF for intelligent, high-performance service mesh implementations, replacing traditional proxy-based solutions with kernel-native networking and load balancing.

3. Security

eBPF offers powerful capabilities for runtime security enforcement, threat detection, and detailed auditing.

  • Security Policy Enforcement: eBPF programs can intercept system calls or network events and enforce custom security policies, effectively acting as tiny, highly efficient in-kernel firewalls or access control lists. For example, restricting a process from accessing specific files or making certain system calls.
  • Runtime Security Monitoring: Detailed logging of critical system events (file access, process creation, network connections) can be performed with minimal overhead, providing rich data for security information and event management (SIEM) systems.
  • Rootkit Detection: By monitoring kernel internals, eBPF can detect anomalous behavior that might indicate the presence of rootkits or other malicious software attempting to hide their activities.

What are the Key Advantages of eBPF?

Vendors leverage eBPF when developing systems and capabilities, because eBPF ensures:

  • High Performance: Running directly within the kernel and benefiting from JIT compilation, eBPF programs execute with exceptional efficiency. They avoid the costly context switching inherent in user space programs trying to interact with the kernel.
  • Flexibility & Dynamism: eBPF programs can be loaded, updated, and unloaded on a running system without requiring reboots or recompiling the kernel. This dynamic nature enables agile development, rapid bug fixes, and continuous deployment.
  • Safety & Stability: The eBPF verifier guarantees that eBPF programs, even if buggy, cannot crash or destabilize the kernel.
  • Non-Intrusiveness: eBPF allows for deep introspection and modification of kernel behavior without needing to change existing kernel code or install new modules. This ensures compatibility and minimizes the risk of introducing new bugs into the core operating system.

Historical Context: From BPF to eBPF

The “BPF” in eBPF stands for Berkeley Packet Filter, a technology originally developed in the early 1990s for efficient network packet filtering. Its primary use was to allow tools like tcpdump to capture only specific network traffic by running a small, safe virtual machine inside the kernel.

Over the years, the original BPF architecture was found to be incredibly robust and secure. In the mid-2010s, the Linux kernel developers extended this concept significantly, transforming the simple packet filter into a general-purpose, event-driven execution engine. This “extended” version, eBPF, retained the core safety mechanisms but vastly expanded its capabilities, allowing it to hook into almost any part of the kernel and perform a much wider array of tasks, moving far beyond just network packets.

K8s Observability with Logz.io and eBPF

Logz.io has integrated OpenTelemetry eBPF Instrumentation (OBI) directly into its monitoring Helm chart (version 7.9.2 and above). This new feature allows DevOps and SRE teams to generate distributed traces for Kubernetes workloads instantly without modifying any application code.

The advantages of this eBPF-based approach:

  • Zero-Code Implementation: It operates independently of the application language, making it capable of instrumenting both modern microservices and legacy “black box” applications where source code is unavailable.
  • Automatic Data Capture: The integration automatically captures HTTP/S requests (including latency and status codes), database interactions (SQL and NoSQL queries), and gRPC calls.
  • Context Propagation: To ensure traces remain connected across service boundaries, the agent injects W3C standard headers at the network level.
  • Safety & Performance: The code is verified by the kernel to ensure stability and compiled into native machine code for high efficiency, avoiding the overhead associated with heavy user-space agents.

FAQs

Is eBPF a programming language?

No, eBPF is not a programming language itself. It defines a virtual instruction set architecture (ISA) and a runtime environment within the Linux kernel. Developers write programs in languages like C, Rust, or Go, which are then compiled into eBPF bytecode.

How is eBPF different from traditional kernel modules?

The key differences are safety and dynamism. Kernel modules can run arbitrary code and, if buggy, can crash the entire kernel. eBPF programs are rigorously verified by the kernel’s eBPF verifier to ensure they are safe and will terminate. Also, eBPF programs can be loaded and unloaded dynamically without affecting kernel stability, unlike kernel modules which often require careful management and can be harder to update.

Is eBPF only for networking?

While eBPF originated from network packet filtering (BPF), its capabilities have been vastly extended. Today, it’s widely used for observability (tracing, monitoring), security (policy enforcement, threat detection), and networking (load balancing, service mesh, firewalling).

What are eBPF hooks?

eBPF hooks are specific, well-defined points within the Linux kernel where an eBPF program can attach and execute. These can be system calls, network events, tracepoints, or dynamic probes (kprobes/uprobes) on specific kernel or user space functions.
What are some popular tools and projects that use eBPF?
Many projects leverage eBPF. Some notable ones include:
*Cilium: For cloud-native networking, security, and observability.
*Falco: For runtime security and threat detection.
*BCC (BPF Compiler Collection): A toolkit for creating eBPF programs, especially for tracing and performance analysis.
*bpftrace: A high-level tracing language built on eBPF.
*Logz.io: For Kubernetes observability.

Get started for free

Completely free for 14 days, no strings attached.