Before diving into any concepts, let us first get the full form of eBPF out of the way. eBPF stands for,
e - extended
B - Berkeley
P - Packet
F - Filter
This full form, however, does not really help us with understanding what eBPF is other than the fact that it helps with filtering network packets (but it’s “extended” so what all does that include?) which is why it is now considered a standalone term. Why is it one of the hottest technology areas in modern infrastructure computing?
eBPF allows us to load the kernel of the operating system with custom code dynamically. That means it can extend or even modify the way the kernel behaves.
Kernel
The Linux kernel is the software layer that sits between your applications and the hardware on which they execute. Programs run in an unprivileged layer known as user space, which has no direct access to hardware. Instead, an application uses the system call (syscall) interface to request that the kernel operate on its behalf. This hardware access can include reading and writing files, sending and receiving network data, or simply accessing memory. The kernel is also in charge of coordinating concurrent processes, which allows multiple programs to operate at the same time. We need over a 100 system calls just to print hello from a file using cat!
The Linux kernel is very complex and comprises of around 30 million lines of code. If we ever want to introduce a new function to the kernel, we would require familiarity with this codebase. So, unless you’re a kernel developer, this could pose as a serious challenge. Even if we are able to come up with an amazing solution, it takes around 5-8 years for it to actually reach any users. There may be new releases of the Linux kernel every 2-3 months, but most of us don’t directly use the Linux kernel, we use Linux distributions such as Ubuntu, Fedora, Debian, etc. All these distributions use older versions of the Linux kernel which is why our feature only reaches the end user after a few years.
An Alternative: Kernel Modules
The Linux kernel was built to support kernel modules that can be loaded and unloaded as needed. If you wish to update or enhance kernel behavior, developing a module is one option. The biggest challenge with this is we still need a kernel developer and if the kernel code crashes, it’ll take the entire machine and the processes running down with it. Along with this, a major factor is security. This kernel module could have malicious code or include vulnerabilities that an attacker might exploit. To use any kernel module, we need to be 100% sure that it is “safe to run”.
eBPF offers a very different approach to safety: the eBPF verifier, which ensures that an eBPF program is only loaded if it’s safe to run.
eBPF Verifier and Security
Because eBPF allows us to run arbitrary code in the kernel, there must be a method in place to ensure that it is safe to run, will not crash users' PCs, and will not jeopardize their data. The eBPF verifier is this approach.
The verifier examines an eBPF program to confirm that it will always terminate securely and within a defined amount of instructions, regardless of input. Verification also ensures that eBPF programs only access memory that they are authorized to access.
Of course, writing a malicious eBPF program is still possible. If data may be observed for legitimate reasons, it can also be observed for illegitimate ones. Only load trusted eBPF programs from reliable sources, and offer eBPF tool management permissions to people you would trust with root access.
eBPF Programs
eBPF programs can be dynamically loaded into and unloaded from the kernel. They will be triggered by an event once they are associated to it, regardless of what caused the event to occur. If you attach a program to the syscall for opening files, for example, it will be activated anytime any process tries to open a file. It makes no difference whether or not that process was already operating when the program was loaded.
This leads to one of the most significant advantages of observability or security tooling that employs eBPF: it instantaneously gains visibility into everything that is happening on the computer.
eBPF in Cloud Native Environments
Before we get into the details of why eBPF is so widely used in Cloud-Native environments, let us be clear on this, we have only one kernel per machine (or virtual machine), and all the containers running on it share the same kernel.
Containers might be grouped up into different pods but they're still all sharing the same kernel and whenever those pods the application code in those pods want to do anything interesting like accessing the network or creating more containers is going to have the kernel involved so the kernel is aware of everything that's happening in all of your applications running on that node and that means we can write ebpf programs to hook into the kernel and observe possibly even modify the behavior of all of our applications which is very powerful. We see this used in a CNCF sandbox project called Pixie which helps us to extract stack information of running applications. Another CNCF graduated project called Cilium which is an eBPF enabled networking, observability and security for cloud native environments.
Conclusion
I hope this blog gave you a small introduction to what eBPF is. For a more technical understanding, you may refer to ebpf.io or if you want any beginner guides, you can refer to Liz Rice’s GitHub repository.
References:
What is eBPF? by Liz Rice
WTF are eBPF & Cilium? with Liz Rice and Christopher Luciano
Top comments (0)