Debugging in Produktion: Chaos Engineering mit eBPF

Observability und Security für zuverlässigen Softwarebetrieb in Produktion: Security-Policies und Datenerfassung verifizieren mit Chaos Engineering und eBPF.

In Pocket speichern vorlesen Druckansicht
Debugging in Produktion: Chaos Engineering mit eBPF

(Bild: iX)

Lesezeit: 23 Min.
Von
  • Michael Friedrich
Inhaltsverzeichnis

Angesichts der zunehmenden Komplexität moderner Softwareentwicklungs- und Deployment-Infrastrukturen sind Entwicklerinnen und Entwickler auf Methoden und Werkzeuge angewiesen, die eine Automatisierung der Prozesse unterstützen und tiefere Einblicke in die Produktionsumgebung gewähren. Das auf Monitoring, Logging und Tracing aufbauende klassische System-Debugging weicht allmählich dem ganzheitlicheren Ansatz der Observability, die auch in komplexen verteilten Cloud-nativen Umgebungen detailliertere Beobachtungsmöglichkeiten erschließt – um unter anderem den Netzwerkverkehr zwischen Containern in einem Kubernetes-Cluster nachvollziehen zu können.

Michael Friedrich

Michael Friedrich ist Senior Developer Evangelist bei GitLab mit Fokus auf Observability, DevSecOps, AI und schreibt auf opsindev.news über seine Erfahrungen. Michael entspannt gerne beim LEGO-Bauen.

Dem "Extended Berkley Packet Filter" (eBPF) kommt dabei eine entscheidende und immer wichtiger werdende Rolle zu. Er eröffnet auf Ebene des Linux-Kernels die Möglichkeit, den Netzwerkverkehr und Syscalls zu überwachen. Im Zusammenspiel von eBPF und Observability lassen sich umfassende Informationen aus Metriken, Logs und Traces erschließen, die auch zu mehr Sicherheit beitragen können. Bereits ein Grundverständnis von eBPF und darauf aufbauenden Tools und Frameworks kann helfen, Probleme effizienter zu lösen.

eBPF – was ist das?​

"Extended Berkley Packet Filter" (eBPF) ist eine erweiterte Form des Berkley Packet Filter (BPF), der ursprünglich als Erweiterung des Linux-Kernel zur Netzwerküberwachung angelegt war. eBPF geht mit zusätzlichen Filteroptionen noch darüber hinaus und eröffnet sowohl Systemadministratoren als auch Entwicklerinnen und Entwicklern weitere Einsatzbereiche wie Sicherheit, Observability und Tracing. Anders als direkt ausführbare Netzwerküberwachungstools wie tcpdump lassen sich eBPF-Programme jedoch nur in einem der Sandbox vergleichbaren Verfahren im privilegierten Umfeld des Kernels ausführen.

Ein Just-in-Time-Compiler (JIT) übersetzt den speziellen Bytecode, und ein Verifier stellt vor dem Ausführen der eBPF-Programme sicher, dass sie keine schädlichen Operationen durchführen. Somit sind nicht nur die Sicherheit und langfristige Stabilität der Kernel-Weiterentwicklung gewährleistet, sondern die eBPF-Anwendungen laufen auch mit einer Geschwindigkeit, die der von nativem Kernel-Code nahekommt.

Über die Netzwerkpaketfilterung hinaus lässt sich eBPF unter anderem auch zur Performanceanalyse, Anwendungs- und Netzwerküberwachung sowie -sicherheit und das Syscall-Monitoring nutzen. Über sogenannte Hook Points lassen sich die eBPF-Programme dazu an den geeigneten Stellen im Kernel "einhängen" – etwa an Netzwerkschnittstellen, Tracepoints oder Systemaufrufen. Um darüber hinaus Daten zwischen Kernel- und Benutzerbereich oder zwischen verschiedenen eBPF-Programmen teilen zu können, stehen die eBPF-Maps zur Verfügung. Diese Datenstrukturen unterstützen verschiedene Datentypen und sind damit ein zentrales Merkmal vieler eBPF-Anwendungen.

Den Umgang mit eBPF und das Entwickeln von eBPF-Programmen erleichtern verschiedene Entwicklertools, Frameworks und Bibliotheken – darunter die BPF Compiler Collection (BCC) und bpftrace.

eBPF revolutioniert die Art und Weise, wie sowohl Entwicklerinnen und Entwickler als auch Systemadministratoren Systeme überwachen, debuggen und sichern. Es bietet hohe Flexibilität, ohne die Stabilität oder Sicherheit des Systems zu gefährden.

Weitergehende Informationen und Anregungen zum Lernen liefert auch das Buch "Learning eBPF" von Liz Rice.

Welche Tools verwenden eBPF und welche Programmiersprache ist für eigene eBPF-Programme nötig? Der Linux-Kernel erwartet eBPF-Programme im Bytecode-Format oder in Assembler-Code, der sich in Bytecode kompilieren lässt. Für Entwicklerinnen und Entwickler, die vorwiegend höhere Programmiersprachen verwenden, stellen beide Formate eine hohe Einstiegshürde dar. Der LLVM-Compiler clang bietet als erster die Möglichkeit, C-Programme in Bytecode zu kompilieren, und eröffnet damit einer breiteren Developer-Community die Chance, effiziente eBPF-Programme zu schreiben.

Allerdings ist auch für den C-Code sowie die benötigten Header-Dateien ein grundlegendes Kernel-Verständnis erforderlich. Hilfe bieten an dieser Stelle unter anderem der Blog von Brendan Gregg sowie einschlägige Community-Meetups. Dann gelingt es, sich zunächst auf bestehende Tools zu fokussieren, um zu sehen, was möglich ist, und sich Inspiration für erste eigene Programmierversuche zu holen.

Wer die im Folgenden vorgestellten CLI-Tools schnell testen möchte, kann dazu die Workshop-Übungen in einem vom Autor frei zur Verfügung gestellten Projekt auf GitLab nutzen. Dort findet sich eine Lima/Vagrant-Umgebung sowie ein generisches Ansible-Playbook. Alternativ lässt sich anhand des Playbooks auch eine Linux-VM provisionieren, etwa Ubuntu ab Version 22 in der Cloud.

Zum Einstieg lassen sich die bcc-Tools (BPF Compiler Collection) dazu verwenden, unterschiedlichste Linux-System-Calls und -Komponenten zu überwachen. Das einfachste Beispiel ist das Überwachen ausgeführter Programme wie eines Ping-Kommandos in einer Endlosschleife. Dazu öffnet man zwei Terminals und startet eine While-Schleife mit Ping- und Sleep-Kommando. Im zweiten Terminal führt man execsnoop-bpfcc mit dem -t-Parameter für Tracing aus:

# sudo apt update && apt -y install make clang linux-headers-`uname -r` bpfcc-tools

# 1. Terminal
$ sudo execsnoop-bpfcc -t

# 2. Terminal
$ while true; do ping -c 1 heise.de; sleep 1; done

Abbildung 1 zeigt die resultierende Ausgabe.

Die beiden Terminalfenster zeigen die Ping-Endlosschleife und das Tracing mit dem execsnoop-bpfcc-Kommando (Abb. 1).

Die bcc-Tools umfassen zwei Komponenten: Im User-Space lassen sich Python-Programme verwenden, die beim Ausführen das Kernel-eBPF-Programm kompilieren und den Bytecode zur Laufzeit in den Kernel laden. Nachteil dabei ist, dass die Buildtools und Kernel-Header auf dem Zielsystem zu installieren sind, was nicht auf allen Produktionssystemen – unter anderem aus Sicherheitsgründen – möglich ist. Darüber hinaus ist das Kompilieren und Laden deutlich langsamer – ein Nachteil, wenn man schnell Probleme debuggen möchte.

Bpftrace, eine Tracing-Hochsprache für BPF, hilft bei der Problemanalyse mit einer Reihe praktischer einzeiliger Kommandofolgen (One-Liner). Sie erleichtert insbesondere Einsteigern das Leben, wenn es darum geht, schnell Systemmetriken und Trace-Endpunkte auszulesen. Darüber hinaus sind Tools wie opensnoop.bt für den Syscall open() verfügbar, die überwachen, ob Prozesse Dateien öffnen (siehe Abbildung 2). Bpftrace benötigt für einzelne Befehle spezielle Debug-Symbole, die sich wie in Listing 1 gezeigt aus dem ddeb.ubuntu.com-Repository installieren lassen.

opensnoop.bt läuft im Vordergrund und listet alle Dateisystemoperationen mit open()-Calls auf. Der cat-Befehl auf die /etc/passwd-Datei wird erkannt (Abb. 2).

Listing 1: Tracing mit bpftrace

$ echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" | \
sudo tee -a /etc/apt/sources.list.d/ddebs.list

$ sudo apt install ubuntu-dbgsym-keyring
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F2EDC64DC5AEE1F6B9C621F0C8CAB6595FDFF622
$ sudo apt-get update

$ sudo apt -y install bpftrace bpftrace-dbgsym

$ sudo opensnoop.bt

# 2. Terminal
$ cat /etc/passwd

Netzwerkdaten lassen sich am einfachsten analysieren und bieten zudem die Möglichkeit, verschiedene Filter für TCP, UDP, ICMP und andere Protokolle zu testen. Im Folgenden soll daher ein erstes eBPF-Programm mit Fokus auf Netzwerkdaten mit dem eXpress DataPath (XDP-Netzpaketprozessor aus dem IO-Visor-Projekt) erstellt und am Loopback-Interface getestet werden.

Ergänzend zum klassischen C-Code für eBPF-Programme haben sich einige Bibliotheken entwickelt, die es erlauben, abstrahierten Code zu schreiben und sich auf wesentliche Programmabläufe zu fokussieren. Im Go-Umfeld gibt es die beiden populären Bibliotheken cillium/epbf-go und aquasecurity/libbpfgo, die in den Open-Source-Projekten Cilium und Tracee zum Einsatz kommen und kontinuierlich weiterentwickelt werden.

Die Rust-Bibliothek aya-rs erlaubt es beispielsweise, die Kernel-eBPF- sowie Userspace-Programme im gleichen Kontext zu schreiben, und sie übernimmt mit Cargo als Build-Umgebung das Kompilieren und Laden der eBPF-Programme (siehe Listing 2). Das erleichtert das Entwickeln ungemein, da der Bytecode automatisch in den Kernel geladen wird. Das aya-rs-Projekt hält zudem hilfreiche Tutorials für die Arbeit mit dem XDP bereit.

Listing 2: Rust-Bibliothek aya-rs

git clone https://github.com/aya-rs/book/
cd book/examples/xdp-hello
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
rustup install stable
rustup install nightly

# eBPF-Programm bauen
cargo xtask build-ebpf

# Userspace bauen
cargo build

# 2. Terminal
ping o11y.love

# 1. Terminal: Starten, mit sichtbarem Log-Level
RUST_LOG=info cargo xtask run

[2023-08-04T02:15:28Z INFO  xdp_hello] received a packet

Die IT-Umgebungen arbeiten immer langsamer, die Festplatten sind voll und vor lauter Containern ist das Problem nicht mehr zu erkennen. Diese Situation dürfte vielen allzu bekannt vorkommen, denn moderne Infrastrukturen für die Softwareentwicklung und deren Deployment sind hochgradig komplex.

Mastering Observability: Die Online-Konferenz von heise

Die Online-Konferenz Mastering Observability am 11. Juni 2024 zeigt, wie ein ganzheitlicher Observability-Ansatz dabei hilft, Softwaresysteme zu verstehen, zu steuern und zu verbessern. Die von iX und dpunkt.verlag organisierte Online-Konferenz richtet sich an Entwicklerinnen, Entwickler, Ops-Fachleute und DevOps-Teams, die Probleme in CI/CD, Deployment und Operations schneller aufspüren wollen und den Ursachen auf den Grund gehen möchten – mit dem Ziel, Mängel gezielt zu beheben und in Zukunft möglichst zu vermeiden.

Interessierte können sich jetzt für die Mastering Observability anmelden – das Ticket kostet bis 13. Mai 2024 zum Frühbucherpreis 229 Euro, danach dann 279 Euro (alle Preise zzgl. MwSt.). Gruppen ab drei Personen erhalten im Ticketshop darüber hinaus automatisch mindestens 10 Prozent Rabatt.

Wer über den Fortgang der Konferenz Mastering Observability auf dem Laufenden bleiben möchte, kann sich auf der Website für den Newsletter registrieren oder den Veranstaltern auf LinkedIn folgen – der aktuelle Hashtag lautet #masteringobs.

Entwicklerinnen und Entwickler sind zunehmend auf Werkzeuge angewiesen, die detailliertere Einblicke liefern und zur Automatisierung der Arbeit beitragen. Dazu muss nicht jeder eBPF vollständig verstehen oder programmieren können. Wenn allerdings Tools, die eBPF verwenden, nicht korrekt funktionieren, kann dieses Wissen dazu dienen, ihnen wieder auf die Sprünge zu helfen oder bei der Fehlersuche Zeit zu sparen. Manchmal fehlt es lediglich an den Berechtigungen, ein eBPF-Programm in den Kernel zu laden, ein andermal tritt ein Bug nur mit bestimmten Kernel-Versionen auf. Neben den bereits vorgestellten CLI-Tools haben sich in den vergangenen Jahren verschiedene Use-Cases für eBPF entwickelt.