eBPF ist eine ereignisgesteuerte Programmiertechnologie, die es Entwicklern ermöglicht, effiziente, sichere und nicht-intrusive Programme zu schreiben, die direkt im Kernelbereich des Linux-Betriebssystems (OS) laufen und den OS-Kernel effektiv „erweitern“.
Der Kernel eines Betriebssystems ist eine extrem und bewusst stabile Einheit. Er unterstützt das gesamte Betriebssystem, daher kann es – konstruktionsbedingt – kompliziert und arbeitsintensiv sein, es zu ändern oder zu modifizieren. eBPFs lösen diese Herausforderung der Erweiterbarkeit, indem sie es Entwicklern ermöglichen, Sandbox-Programme in privilegierten Kontexten, wie beispielsweise einem Betriebssystem-Kernel, auszuführen.
Der Betriebssystem-Stack lässt sich in drei logische Schichten unterteilen: die Hardware-Schicht, die Kernel-Schicht und die Benutzer-Schicht. Die Kernel-Schicht ist der Kern eines Betriebssystems. Sie befindet sich zwischen der physikalischen Schicht – die die gesamte physische Hardware, den Speicher und die Speicherkomponenten eines Betriebssystems beherbergt – und der Benutzerschicht – die die Webbrowser und Anwendungen eines Betriebssystems beherbergt.
Die Apps und Browser im Benutzerbereich müssen mit Komponenten der physischen Schicht kommunizieren, um ihre jeweiligen Aufgaben zu erfüllen. Jede Komponente der physischen Schicht hat jedoch spezifische Kommunikationsprotokolle und Kompatibilitätsanforderungen. Hier kommt die Kernel-Schicht (oder der Kernel-Bereich) ins Spiel. Sie interpretiert Systemaufrufe und ermöglicht Anwendungen die effektive Kommunikation mit physischen Netzwerkkomponenten.
eBPF-Tools helfen Entwicklern, die Funktionen bestehender Software zur Laufzeit einfacher zu erweitern, ohne den Kernel-Quellcode zu modifizieren, Kernel-Module (ladbare Codeabschnitte, die Kernel-Funktionen erweitern können) zu laden oder den Kernel-Bereich auf andere Weise zu stören.
eBPF-Technologien stellen eine Weiterentwicklung des ursprünglichen Berkeley Packet Filter (BPF) dar, der eine einfache Möglichkeit zur Auswahl und Analyse von Netzwerkpaketen in einem Userspace-Programm bot. Aber über das Paketfiltern hinaus fehlte BPF-Programmen die Flexibilität, komplexere Aufgaben im Kernel zu bewältigen.
Die Linux-Gemeinschaft erkannte den Bedarf an einer vielseitigeren Technologie und entwickelte eBPF, der auf den Backend-Funktionen von BPF aufbaute, aber die Programmierbarkeit im Kernel erweiterte. Die fortschrittlichen Funktionen von eBPF-Programmen – und ihr Sandbox-Ansatz – ermöglichen es Entwicklern, verbesserte Paketfilterprozesse zu implementieren, die Observability und Überwachungsfunktionen im Kernel-Bereich zu verbessern, leistungsstarke Leistungsanalysen durchzuführen und Sicherheitsrichtlinien auf Kernel-Ebene sowohl in lokalen Rechenzentren als auch in cloudnativen Umgebungen durchzusetzen.
Die Hauptkomponenten eines eBPF-Programms sind:
eBPF-Programme werden zunächst in einer eingeschränkten C-Teilmenge geschrieben und dann mit Tools wie LLVM in eBPF-Bytecode kompiliert, der als Back-End-Architektur des eBPF für Front-End-Programmiersprachen (wie Clang) dient. Der Bytecode ist im Wesentlichen ein eingeschränkter Satz von Anweisungen, die der eBPF-Befehlssatzarchitektur entsprechen und Laufzeitfehler verhindern.
Die Linux-Kernel-Technologie kann eBPF-Bytecode in ausführbare Aktionen umwandeln, aber Just-in-Time-Compiler (JIT) bieten eine bessere Leistung. JIT-Compiler können Bytecode bei Bedarf in nativen Maschinencode für bestimmte Hardwareplattformen umwandeln.
Userspace-Loader sind Programme im Userspace, die den eBPF-Bytecode in den Kernel laden, ihn an die entsprechenden Hooks anhängen und alle zugehörigen eBPF-Karten verwalten. Beispiele für Userspace-Loader sind Tools wie BPF Compiler Collection (BCC) und bpftrace.
eBPF-Karten sind Datenstrukturen mit Schlüssel-Wert-Paaren und Lese-/Schreibzugriff, die gemeinsamen Speicherplatz bereitstellen und die Interaktion zwischen eBPF-Kernelprogrammen und Userspace-Anwendungen erleichtern. eBPF-Maps werden über Systemaufrufe erstellt und verwaltet und können auch dazu verwendet werden, den Zustand zwischen verschiedenen Iterationen der eBPF-Programme aufrechtzuerhalten.
Der Prüfer – eine entscheidende Komponente von eBPF-Systemen – prüft den Bytecode, bevor er in den Kernel geladen wird, um sicherzustellen, dass das Programm keine schädlichen Vorgänge wie Endlosschleifen, illegale Anweisungen oder unzulässige Speicherzugriffe enthält. Es hilft auch sicherzustellen, dass alle Datenpfade des Programms erfolgreich beendet werden.
Hooks sind Punkte im Kernel-Code, an die eBPF-Programme angehängt werden können. Wenn der Kernel einen Hook erreicht, wird das angehängte eBPF-Programm ausgeführt.
Verschiedene Arten von Hooks wie Tracepoints, Kprobes, Uprobes und Netzwerkpaket-Empfangswarteschlangen ermöglichen eBPF-Programmen einen umfassenden Datenzugriff und die Durchführung verschiedener Operationen. Tracepoints ermöglichen es Programmen beispielsweise, den Kernel oder andere Prozesse zu untersuchen und Daten darüber zu sammeln, während Traffic-Control-Hooks verwendet werden können, um Netzwerkpakete zu untersuchen und zu verändern. Und Kprobes und Uprobes erleichtern die dynamische Verfolgung auf Kernel- und Benutzerebene.
XDPs sind Datenpfade mit hoher Leistung, die die Paketverarbeitung auf Treiber-Ebene beschleunigen und die Übertragung zwischen Kommunikationsschichten erleichtern. Sie ermöglichen es eBPF-Systemen, Datenrouting-Entscheidungen zu treffen, bevor die Datenpakete überhaupt den Kernel erreichen.
Die Integration von XDPs mit dem Linux-Kernel (Mitte der 2010er Jahre) ermöglichte es Entwicklern letztlich, eBPF-basierte Lastverteilungsfunktionen bereitzustellen, die den Datenverkehr selbst in den verkehrsreichsten Rechenzentren verwalten können.
Da eBPFs keine beliebigen Funktionen erzeugen können und die Kompatibilität mit jeder möglichen Kernelversion aufrechterhalten müssen, sind die grundlegenden eBPF-Befehlssätze manchmal nicht differenziert genug, um fortgeschrittene Vorgänge auszuführen. Hilfsfunktionen schließen diese Lücke.
Hilfsfunktionen – Sätze vordefinierter, API-basierterKernelfunktionen, die eBPFs vom System aus aufrufen können – bieten eBPF-Programmen die Möglichkeit, komplexere Vorgänge (wie das Abrufen der aktuellen Uhrzeit und des aktuellen Datums oder das Generieren von Zufallszahlen) auszuführen, die nicht direkt vom Befehlssatz unterstützt werden.
Im Allgemeinen arbeiten eBPFs als virtuelle Maschinen (VMs) innerhalb des Linux-Kernels, die mit einer Low-Level-Befehlssatzarchitektur arbeiten und eBPF-Bytecode ausführen. Der komplexe Prozess der Ausführung eines eBPF-Programms folgt jedoch in der Regel bestimmten Hauptschritten.
Entwickler schreiben zuerst das eBPF-Programm und kompilieren den Bytecode. Der Zweck des Programms bestimmt den geeigneten Codetyp. Wenn ein Team beispielsweise die CPU-Nutzung überwachen möchte, schreibt es Code, der Funktionen zum Erfassen von Nutzungsmetriken enthält.
Nachdem der eBPF-Compiler den High-Level-C-Code in Low-Level-Bytecode konvertiert, generiert ein Userspace-Loader einen BPF-Systemaufruf, um das Programm in den Kernel zu laden. Der Loader ist auch dafür verantwortlich, Fehler zu beheben und alle eBPF-Karten einzurichten, die das Programm benötigt.
Wenn der Bytecode und die Karten des Programms vorhanden sind, führt der eBPF einen Prüfungsprozess durch, um sicherzustellen, dass das Programm sicher im Kernel ausgeführt werden kann. Wenn es als unsicher eingestuft wird, schlägt der Systemaufruf zum Laden des Programms fehl und das Loader-Programm erhält eine Fehlermeldung. Wenn das Programm die Prüfung besteht, darf es ausgeführt werden.
Mit Hilfe eines Interpreters oder eines JIT-Compilers wandelt das eBPF den Bytecode in umsetzbaren Maschinencode um. Bei eBPF handelt es sich jedoch um eine ereignisgesteuerte Technologie, die nur auf bestimmte Hook-Points oder Ereignisse innerhalb des Kernels reagiert (z. B. Systemanrufe, Netzwerkereignisse, Prozessinitiierung, CPU-Leerlauf). Wenn ein Ereignis auftritt, führt eBPF das entsprechende Bytecode-Programm aus, sodass Entwickler verschiedene Komponenten des Systems überprüfen und manipulieren können.
Wenn das eBPF-Programm läuft, können Entwickler vom Benutzerbereich aus mithilfe von eBPF-Karten damit interagieren. Beispielsweise könnte die Anwendung regelmäßig eine Karte überprüfen, um Daten vom eBPF-Programm zu sammeln, oder sie könnte eine Karte aktualisieren, um das Verhalten des Programms zu ändern.
Das Entladen des Programms ist der letzte Schritt der meisten eBPF-Ausführungsprozesse. Wenn der eBPF seine Arbeit erledigt hat, kann der Loader den BPF-Systemaufruf erneut verwenden, um ihn aus dem Kernel zu entladen. An diesem Punkt stoppt der eBPF und gibt die zugehörigen Ressourcen frei. Der Entladevorgang kann auch das Durchlaufen aller eBPF-Karten umfassen, die das Team nicht mehr benötigt, um nützliche einzelne Elemente freizugeben, und das anschließende Löschen der Karte selbst (mithilfe des Systemaufrufs „delete“).
Der Berkeley Packet Filter (BPF) wurde ursprünglich als Mechanismus zur Paketfilterung in Unix-basierten Systemen entwickelt, der es Benutzercode ermöglichte, Filter zu definieren, die Netzwerkpakete effizient im Kernel erfassen und verarbeiten konnten. Daher minimierte dieser Ansatz die Rechenleistung, die benötigt wird, um unnötige Daten in den Userspace zu übertragen, und er konnte Computernetzwerke rationalisieren und optimieren.
BPF verwendet einen Kernel-Agenten, um Pakete am Einstiegspunkt des Netzwerk-Stack zu verarbeiten. Nach der Entwicklung eines BPF-Programms wird dieses von einem BPF-Kernel-Agenten in den Kernel-Bereich geladen, der seine Genauigkeit überprüft, bevor er es an den entsprechenden Socket anhängt. Folglich können im Benutzerbereich nur Pakete, die dem Filter des BPF-Programms entsprechen, Daten von einem bestimmten Socket empfangen. Diese Schutzfunktion begrenzt den Zugriff eines Programms auf erlaubte Speicherbereiche und verhindert potenzielle Kernel-Abstürze.
eBPF entstand erstmals im Jahr 2014 und stellte zu diesem Zeitpunkt eine bedeutende Weiterentwicklung des ursprünglichen BPF-Konzepts dar. Zusätzlich zu den ursprünglichen Netzwerk-Anwendungsfällen wurden die eBPF-Anwendungen um Systemaufrufe und andere Funktionen erweitert, weshalb Entwickler es oft als den „vollständig erweiterten Berkeley Packet Filter“ bezeichneten.
Einer der Hauptanwendungsbereiche von eBPF ist die Überwachung der Netzwerkleistung. Es ermöglicht IT-Teams, Echtzeitanalysen und Fehlerbehebungen durchzuführen, indem es detaillierte Erkenntnisse über das Netzwerkverhalten, Leistungsmetriken und Engpässe bietet. eBPF spielt eine Schlüsselrolle bei der Netzwerksicherheit, der Überwachung und Filterung von Systemaufrufen und Netzwerkaktivitäten, der Durchsetzung von Netzwerksicherheitsrichtlinien und der Erkennung von Systemanomalien.
eBPF bietet Entwicklern außerdem ein wertvolles Werkzeug zur Nachverfolgung und Profilierung sowohl von Kernel- als auch Userspace-Anwendungen sowie zur Ausführung benutzerdefinierter Aktionen und Datenkonvertierungen, während Daten den Kernel durchqueren, was seine Vielseitigkeit und Nützlichkeit weiter erhöht. Aufgrund dieser umfassenden Funktionen (die weit über das Filtern von Paketen hinausgehen) wird eBPF jetzt als eigenständiger Begriff anerkannt und nicht mehr als Akronym für den erweiterten Berkeley Packet Filter.
Fortschritte in der eBPF-Technologie haben Softwareentwickler dazu veranlasst, ihre Anwendungen auf alle Betriebssysteme auszuweiten, sodass auch nicht auf Linux basierende Plattformen von den fortschrittlichen Verfolgungs-, Netzwerk- und Überwachungsfunktionen von eBPF profitieren können.1
Tatsächlich hat die eBPF Foundation – eine Erweiterung der Linux Foundation, zu deren Mitgliedern unter anderem Google, Meta, Netflix, Microsoft, Intel und Isovalent gehören – stark in die Erweiterung der Betriebssystemkompatibilität für eBPF-Programme investiert, in der Hoffnung, den Nutzen der eBPF-Programmierung zu steigern.2
Obwohl BPF die Grundlage für eine effiziente Paketfilterung gelegt hat, hat eBPF seinen Anwendungsbereich zweifellos erweitert. Moderne eBPFs bieten ein umfassendes Werkzeug für optimierte Observability, Leistung und Sicherheit in Linux-Systemen. Seine Fähigkeit, dynamische, benutzerdefinierte Programme im Kernel auszuführen, eröffnet neue Möglichkeiten der Systemüberwachung und -verwaltung, was eBPF zu einem unverzichtbaren Tool sowohl für Softwareentwickler als auch für Computerprogrammierer macht.
eBPF-Technologien sind bereits zu einem Eckpfeiler moderner Linux-Systeme geworden. Sie ermöglichen eine differenzierte Kontrolle über den Linux-Kernel und ermöglichen es Unternehmen, innovativere Programme innerhalb des Linux-Ökosystems zu entwickeln.
eBPF hat Fortschritte ermöglicht in den Bereichen:
eBPF ermöglicht Entwicklern die Implementierung schnellerer, individuellerer Paketverarbeitungsfunktionen, Load-Balancing-Prozesse, Skripte für die Anwendungsprofilerstellung und Netzwerküberwachungsmethoden. Open-Source-Plattformen wie Cilium stellen eBPF bereit, um sichere, skalierbare und beobachtbare Netzwerke für Kubernetes-Cluster und -Workloads sowie andere containerisierte Microservices zu gewährleisten.
eBPF hilft IT-Teams auch dabei, einfache und komplexe Regeln frühzeitig im Ereignispfad aufzustellen, um den Datenverkehr effektiver zu leiten, Inhalte zu filtern und Verluste zu verhindern. Durch die Nutzung der Paketweiterleitungslogik auf Kernel-Ebene können eBPFs Latenz minimieren, Routing-Prozesse rationalisieren und eine schnellere Reaktion des gesamten Netzwerks ermöglichen.
Da Apps in Microservices unterteilt werden, kann die Observability im Benutzerbereich schwierig werden. eBPFs bieten Überwachungstool eine Sichtweise auf den Kernel-Bereich, sodass die Observability durchgängig erhalten bleibt.
Mit eBPFs können Entwickler den Kernel und Userspace-Anwendungen instrumentieren, um detaillierte Leistungsdaten und Metriken zu sammeln, ohne die Leistung des Systems wesentlich zu beeinträchtigen. Diese Funktionen helfen Unternehmen, einen Schritt voraus zu sein, indem sie die Echtzeitüberwachung und Observability jeder Netzwerkkomponente (und ihrer Abhängigkeiten) ermöglichen.
eBPFs können Systemaufrufe, Netzwerkverkehr und Systemverhalten sowohl auf Kernel- als auch auf Socket-Ebene überwachen, um potenzielle Sicherheitsbedrohungen in Echtzeit zu erkennen und darauf zu reagieren. Falco (ein cloudnatives Laufzeitsicherheitstool) verwendet beispielsweise eBPF, um Laufzeit-Sicherheitsaudits und Incident Response zu implementieren, was die Gesamtsicherheit des Systems erhöht.
Viele eBPF-Tools können Systemaufrufe verfolgen, die CPU-Auslastung überwachen und die Ressourcennutzung (z. B. Festplatten-E/A) erfassen. Diese Funktionen unterstützen Entwickler dabei, Leistungsengpässe im System leichter zu erkennen,Debugging- Protokolle zu implementieren und Optimierungspotenziale aufzudecken.
eBPFs können Sicherheitsrichtlinien auf Kernel-Ebene installieren und durchsetzen (zum Beispiel Netzwerkverkehrsfilter, Firewalls und Verhaltensbeschränkungen) sowie Sicherheitsüberprüfungen, um böswillige Akteure und unbefugte Benutzer am Zugriff auf das Netzwerk zu hindern.
In einer Microservice-Architektur ist der Einblick in die Produktions-Workloads innerhalb des Containers entscheidend. Herkömmliche Observability-Tools können jedoch Schwierigkeiten haben, mit containerisierten Microservices Schritt zu halten.
Container sind von ihrem Konzept her kurzlebig; sie werden erstellt, wenn sie benötigt werden, und wieder vernichtet, sobald sie ihren Zweck erfüllt haben. Jeder Container verhält sich wie ein einzelner Host, und in einer Produktionsumgebung kann die schiere Menge an Metriken, die sie erstellen, die Standard-App-, Netzwerk- und Infrastrukturüberwachungstools leicht überfordern. Virtuelle Maschinen können sich ähnlich verhalten, aber die schnell zyklierende Natur von Containern kann die Telemetrieerfassung erschweren.
Außerdem werden Container in Cloud-Umgebungen oft in großer Zahl bereitgestellt, was die Sichtbarkeit noch weiter erschwert.
eBPF, das auf Kernel-Ebene eines Hosts oder Containers läuft, ermöglicht es Entwicklern, Telemetrie von kurzlebigen Datenentitäten zu sammeln. Es trägt zur Integration von Netzwerk-, Anwendungs- und Infrastrukturtransparenz in einen einheitlichen eBPF-basierten Service bei. Mit eBPF können Entwickler Daten zu Prozessen, Speichernutzung, Netzwerkaktivität und Dateizugriff auf Container-Ebene erfassen, selbst wenn die Container nicht in der Cloud bereitgestellt werden.
Ähnlich verwendet eBPF in Kubernetes-basierten, containerisierten Umgebungen eine einzige Schnittstelle und ein Toolset, um Daten aus verteilten Clustern zu sammeln, sodass IT-Teams keine einzelnen Userspace-Agenten bereitstellen müssen, um Datensammlungsaufgaben im Netzwerk zu erledigen. eBPF-Tools können auf Kontrollebenen-Knoten laufen (zum Beispiel zur API-Server-Überwachung) und Arbeiterknoten überwachen, um Erkenntnisse zu generieren, die Datenpunkte und Erkenntnisse von beiden Knotentypen für eine fein abgestimmte Cluster-Observability korrelieren.
Red Hat OpenShift on IBM Cloud ist eine vollständig verwaltete OpenShift Container Platform (OCP).
Mit IBM Spectrum Virtualize erhalten Sie eine sichere, zuverlässige und effiziente Speichervirtualisierung für VMware-Umgebungen.
Finden Sie die richtige Cloud-Infrastrukturlösung für Ihre Geschäftsanforderungen und skalieren Sie Ressourcen nach Bedarf.
1 Foundation Proposes Advancing eBPF Adoption Across Multiple OSes, DevOps.com, 21. August 2021.
2 Latest eBPF Advances Are Harbingers of Major Changes to IT, DevOps.com, 13. September 2023.