New Relic I/O, Ihr Hub für Instant Observability Jetzt Quickstart für Ihren Stack finden

Was ist der eBPF und warum ist er für Observability relevant?

6 Minuten Lesedauer

Bei der Implementierung von Sicherheits-, Netzwerk- und Observability-Funktionen ist es per se durchaus ideal, direkt im Linux-Kernel zu arbeiten. Ganz ohne Herausforderungen geht dies aber nicht einher. Ob bei der Anpassung von Kernel-Quellcode oder der Erweiterung um Module – Entwickler sehen sich in diesem Zusammenhang regelmäßig mit komplexer Infrastruktur und abstrahierten Layern konfrontiert, bei denen sich die Fehlerbehebung nicht einfach gestaltet. Extended BPF (eBPF) adressiert beides.

Mit dem in Linux ab Version 4.x verfügbaren Extended Berkeley Packet Filter, wie der eBPF in Langform bezeichnet wird, wird es möglich, Programme im Kernel ganz ohne Anpassungen an dessen Quellcode oder ergänzende Modul-Erweiterungen auszuführen. Technisch umgesetzt wird dies in Form einer Lightweight-VM, die innerhalb des Linux-Kernels eine Sandbox einrichtet. Darin kann dann BPF-Bytecode ausgeführt und über diesen bestimmte Ressourcen aus dem Kernel angesteuert werden.

Der eBPF erfordert also keine Anpassungen am Kernel-Quellcode. Ebenfalls soll er Software eine effizientere Nutzung bestehender Layer ermöglichen – ein Versprechen mit enormem Potenzial, könnte er damit doch die Bereitstellung von Services rund um Netzwerk, Observability und Security grundlegend verändern.

Wir zeigen, was es genau damit auf sich hat, wie er funktioniert und wann sich eine Implementierung lohnt.

Funktionsweise des eBPF

Das Grundprinzip des eBPF besteht darin, Programme an einen Codepfad anzubinden und eventgesteuert auszuführen. Hierfür beinhaltet der Codepfad bestimmte Trigger, genannt „Hooks“, die entsprechend ihrer Definition die Ausführung der jeweils angehängten eBPF-Programme auslösen. Als Hooks definiert werden können netzwerkbezogene Ereignisse, Systemaufrufe oder Funktionseingaben sowie Tracepoints im Kernel.

Kommt es zur Auslösung, wird der Programmcode in BPF-Bytecode kompiliert, vor seiner Ausführung jedoch zunächst noch auf das Risiko einer Endlosschleife geprüft. Mit diesem Verifizierungsschritt wird verhindert, dass das Programm den Linux-Kernel kompromittiert – sei es versehentlich durch einen Code-Fehler oder beabsichtigt durch Schadcode.

Passiert das Programm die Prüfung am Hook, werden die Ausführung und sogenannte „Helper Calls“ ausgelöst. Bei diesen handelt es sich um spezielle Funktionsaufrufe, die dem eBPF auf vielerlei Weise Zugriff auf den Speicher ermöglichen. Diese Features müssen zwar kernelseitig vorkonfiguriert sein, doch wird die Liste verfügbarer Helper laufend erweitert.

Aus der Taufe gehoben wurde der eBPF als Mittel zur besseren Sicherung und Überwachung der Vorgänge beim Filtern von Netzwerkpaketen. Peu á peu erkannte man dann aber, dass sich mit ihm auch die Implementierung von nutzerseitigem Code sicherer, leichter handhabbar und zudem performanter machen lässt.

Vorteile des eBPF

Die Kernfunktion und zugleich größte Stärke des eBPF liegt im Tracing von Prozessen auf Benutzerebene. Zum Tragen kommt dies wie folgt:

  • Speed und Performance: Der eBPF verlagert die Paketverarbeitung von der Kernel- auf die Nutzerebene. Zudem kompiliert er Code nach dem „Just-in-Time“-Prinzip: Nach der Kompilierung des Bytecode wird der eBPF aufgerufen – statt für jede einzelne Methode eine neue Interpretation desselben.
  • Unterbrechungsfreies Debugging: Mit dem eBPF können Programme während dieses Vorgangs ihren Ausführungsstatus beibehalten.
  • Bessere Sicherheit: In der Sandbox „sicher verwahrt“, können Programme keine Eingriffe im Kernel-Quellcode vornehmen. Der Verifizierungsschritt wiederum beugt der Ausführung von Code mit Endlosschleifen vor, die Ressourcen ausbremsen oder gar zum Absturz bringen könnten.
  • Einfache Handhabung: Kernel-Funktionen via Hook anzusteuern ist programmierungstechnisch deutlich weniger arbeitsintensiv als die Erstellung und Pflege von Kernel-Modulen.
  • Zentralisiertes Tracing: Der eBPF stellt ein umfassendes, funktionsstarkes und unkompliziertes Framework zum Tracing von Prozessen zur Verfügung. Dies sorgt für mehr Transparenz und Sicherheit.
  • Programmierbarkeit. Mit dem eBPF braucht es keine zusätzlichen Layer, um erweiterte Funktionen in eine Umgebung einzubetten. Die Ausführung des Codes im Kernel hat zudem den Vorteil, dass Daten zwischen Events gespeichert werden können. Andere Tracing-Tools müssen an diesen Punkten einen Export ziehen.
  • Expressive Syntax: Funktionsaufrufe erfolgen beim eBPF mittels Ausdrücken – ein Programmieransatz, den man sonst nur in höheren Sprachen findet.

Best Practices für eBPF

Der eBPF ist noch nicht lange genug verfügbar, als dass seine Möglichkeiten bereits in vollem Umfang hätten ausgelotet werden können. Konkrete Best Practices müssen sich also im Zuge einer breiteren Nutzung der Technologie erst noch herauskristallisieren. Ein paar Tricks und Kniffe gibt es aber bereits jetzt, die die Programmierung mit dem eBPF effektiver und die Resultate effizienter machen.

Hierzu einige Empfehlungen unsererseits:

  • In C geschriebenen Code mithilfe von LLVM Clang in Bytecode kompilieren: Zu den Anfängen des eBPF musste man den Code des Programms manuell schreiben und diesen dann ebenfalls manuell mithilfe des Kernel-Assemblers in Bytecode übersetzen lassen. Diese reichlich mühselige Aufgabe löst Clang am Frontend durch entsprechende Infrastruktur und Toolsets für Programmiersprachen der C-Familie. 
  • Für die BPF-Programmierung das BCC-Toolkit zu Hilfe nehmen: Mit der BPF Compiler Collection (BCC) geht die Erstellung von Programmen für Kernel-Tracing und -Manipulation leichter von der Hand. Besonders effizient gestalten sich mit dem Toolkit Aufgaben rund um die Analyse der Netzwerk-Performance sowie der Traffic-Steuerung.

Grenzen des eBPF

Der eBPF ist zwar enorm funktionsstark, doch keine Patentlösung für sämtliche Projekte oder Ökosysteme. Denn die Technologie birgt bestimmte Nachteile, die sich fallabhängig als frustrierend und unter Umständen auch als Hemmschuh für seinen Einsatz erweisen können. Dazu gehören:

  • Die Beschränkung auf Linux mit einer neuen Version des Kernels: Der eBPF wurde im Linux-Kernel geschrieben und ist dementsprechend vollständig um ihn herum aufgebaut. Verglichen mit anderen Tracern ist er daher nur wenig portierbar. Zudem läuft er nur auf einer vergleichsweise neuen Kernel-Version, alles unter Version 4.13 fällt bereits aus dem Raster.
  • Die mit Sandboxes per se verbundenen Einschränkungen: Der eBPF beschränkt im Sinne höherer Sicherheit das Spektrum an Ressourcen, auf das Programme zugreifen können. Im Umkehrschluss schränkt er damit aber auch ihre Funktionalität ein, da ihnen bestimmte Bereiche des Betriebssystems vorenthalten bleiben.

Typische Use Cases für den eBPF

Immer größeren Anklang findet der eBPF im Bereich der cloudnativen Anwendungen. Zum Einsatz kommt er dort in der Regel in den folgenden beiden Szenarien:

  • Wenn Observability via Kernel-Tracing umgesetzt werden muss: Hier erweist sich der eBPF als schneller und präziser. Dies einmal, weil er ohne Kontextwechsel auskommt, und außerdem aufgrund seines eventgesteuerten Programmkonzepts: Nichts wird ohne Trigger ausgeführt, also bleibt auch nichts unentdeckt.
  • Wenn klassisches Security Monitoring keine Option ist: In verteilten und containerbasierten Umgebungen wie Kubernetes ergeben sich Use Cases verschiedenster Art für den eBPF. Seine Stärke hier: Er vermittelt Transparenz für den bislang im Verborgenen gebliebenen Bereich des HTTP-Traffic.

Aussichtsreiche Deployment-Szenarien finden sich außerdem in Security-Prozessen rund um die folgenden Bereiche:

  • Firewalls
  • Gerätetreiber
  • Monitoring der Netzwerk-Performance

Der eBPF bei New Relic

Pixie, das nun zu New Relic gehört, bietet eine Kubernetes-native Open-Source-Plattform für In-Cluster-Observability, die Kubernetes-Workloads ohne jedwede manuelle Instrumentierung auf Anhieb transparent macht. Ein Kunststück, das Pixie größtenteils mithilfe des eBPF vollbringt. Denn wie bereits erläutert, lässt sich über den eBPF zugriffsbeschränkter Code via eventgesteuertem Trigger auszuführen. Und ein eben solches Event kann auch ein Funktionsaufruf sein, dies entweder im Kernelspace (kprobes) oder im Userspace (uprobes). Genau dieser uprobes- und kprobes-Aufrufe bedient sich Pixie, um service- und anwendungsübergreifend Observability zu ermöglichen. 

Über den eBPF erfasst Pixie automatisch die nötigen Telemetriedaten, die es dann KI-gestützt am Edge mit Kubernetes-Metadaten zusammenführt. So können die Daten an ihrem Ort verbleiben, zugleich aber umfassend analysiert werden. Die Lösung von New Relic für Kubernetes-Observability erhält hierdurch einen weiteren Baustein für tiefergehende Transparenz. Noch weiter geht dies bei Übermittlung der von Pixie generierten Telemetriedaten in New Relic One. Darin zentral und skalierbar erfasst, lassen sie sich in detaillierte Visualisierungen überführen, umfassend korrelieren und intelligente Alerts für sie definieren.

eBPF – Synonym für effiziente Observability

Der eBPF bringt auf innovative Weise mehr Observability in den Linux-Kernel und stärkt dort zugleich Sicherheits- und Netzwerkvorgänge. Weder Anpassungen am Quellcode des Kernels sind dabei nötig, noch muss er um zusätzliche Module ergänzt werden. Das erweitert die Funktionalität der Infrastruktur, ohne dabei die zugrunde liegenden Systeme übermäßig zu verkomplizieren.

Mit Blick auf das hier erläuterte Grundkonzept des eBPF, seine Funktionsweise und die mit ihm verbundenen Vorteile für verteilte Umgebungen wird klar, worin sein Potenzial liegt: in der Lösung einer Vielzahl von Herausforderungen im Zusammenhang mit Observability in der Cloud. Denn Monitoring direkt aus dem Kernel-Layer heraus, das bedeutet mehr Transparenz, mehr Kontext und mehr Datengenauigkeit.