Ciliums Fallstudie zur Verbesserung der Netzwerkstabilität: Erstaunliche Wirkung durch eine kleine Code-Änderung
(gosuda.org)- Vorstellung eines PR-Falls, bei dem eine kleine Code-Änderung (das Hinzufügen nur einer einzigen
if-Anweisung) erheblich zur Systemstabilität beigetragen hat - Einfluss und Bedeutung des PR „bpf:nat: Restore ORG NAT entry if it's not found“
Grundprinzip von NAT (Network Address Translation)
- NAT ist eine Technologie, mit der mehrere Geräte sich eine einzige öffentliche IP teilen können
- Sie ermöglicht die Kommunikation zwischen internen Geräten (Private IP:Port) und dem externen Internet
- Die NAT-Tabelle speichert Mapping-Informationen zwischen Originaladresse und übersetzter Adresse
- Ablauf:
- Ein internes Gerät versucht, eine Verbindung zu einem externen Server aufzubauen
- Das NAT-Gerät wandelt die Quell-IP/den Quell-Port in eine öffentliche IP/einen öffentlichen Port um (SNAT)
- Antworten des externen Servers werden wieder zum internen Gerät zurückübersetzt (DNAT)
Einsatz von NAT in Kubernetes
- In Kubernetes gibt es zwei zentrale Einsatzszenarien, in denen NAT besonders wichtig ist:
- Kommunikation von Pods nach außerhalb des Clusters: Die interne IP des Pods wird in die öffentliche IP des Nodes übersetzt
- Kommunikation von außen zu Pods über NodePort: Externe Anfragen werden zu einem bestimmten Pod geroutet
Wie Cilium NAT implementiert
- Unter Linux wird NAT üblicherweise mit conntrack und iptables verarbeitet
- Cilium nutzt eBPF und umgeht damit den traditionellen Linux-Netzwerk-Stack
- Cilium verwaltet die NAT-Tabelle direkt mithilfe einer LRU-Hash-Map (
BPF_MAP_TYPE_LRU_HASH)
Ursache des Problems
- Lookup-Problem: Für die bidirektionale Verarbeitung (ausgehende/eingehende Pakete) werden dieselben Daten zweimal gespeichert (RevSNAT)
- Grenzen von LRU: Wegen begrenzter Ressourcen werden selten genutzte Einträge entfernt
- **Verbindungsverlust # Ein Fall, in dem Cilium durch eine kleine Code-Änderung die Netzwerkstabilität deutlich verbessert hat
Einführung: Große Wirkung einer kleinen Code-Änderung
- Ein Fall, in dem allein das Hinzufügen eines einzigen
if-Blocks enorm zur Systemstabilität beigetragen hat - Der betreffende PR: „bpf:nat: Restore ORG NAT entry if it's not found“
- Erklärung so aufbereitet, dass auch Menschen ohne Spezialisierung im Netzwerkbereich sie verstehen können
Grundprinzip von NAT (Network Address Translation)
- NAT ist eine Technologie, mit der mehrere Geräte sich eine einzige öffentliche IP teilen können
- Sie funktioniert, indem interne Kombinationen aus Private IP:Port auf externe Public IP:Port abgebildet werden
- Funktionsweise:
- Ein internes Gerät versucht, auf einen externen Server zuzugreifen
- Das NAT-Gerät wandelt die interne Kommunikation in externe Kommunikation um (SNAT)
- Wenn die Antwort zurückkommt, wird sie wieder in die ursprüngliche interne Kommunikation zurückübersetzt (DNAT)
- Die Übersetzungsinformationen werden in der NAT-Tabelle gespeichert
Einsatz von NAT in Kubernetes
- Kubernetes hat eine komplexe Netzwerkstruktur und nutzt NAT an vielen Stellen
- Wichtige Anwendungsfälle für NAT:
- Kommunikation von Pods nach außerhalb des Clusters: Die private IP des Pods wird in die öffentliche IP des Nodes übersetzt (SNAT)
- Kommunikation von außen zu Pods über NodePort: Damit externer Traffic an den passenden Pod weitergeleitet wird, werden DNAT und SNAT gleichzeitig ausgeführt
Ciliums besonderer Ansatz
- In typischen Linux-Systemen wird NAT über das conntrack-Subsystem und iptables verwaltet
- Cilium nutzt eBPF und umgeht damit den traditionellen Linux-Netzwerk-Stack
- Für SNAT verwaltet es die SNAT-Tabelle direkt in Form einer LRU-Hash-Map (
BPF_MAP_TYPE_LRU_HASH)
Ursache und Symptome des Problems
-
Lookup-Problem:
- Zur Verifikation der NAT-Verarbeitung ist ein Lookup in der Hash-Tabelle nötig
- Für schnelle Lookups werden dieselben Daten mit vertauschten
src- unddst-Werten als RevSNAT zweimal in die Tabelle eingefügt
-
LRU-Problem (Least Recently Used):
- Aufgrund von Ressourcenbeschränkungen können Daten durch die LRU-Logik entfernt werden
-
Kombiniertes Problem:
- Für eine einzelne TCP-Verbindung werden dieselben Daten zweimal gespeichert
- Wenn auch nur einer der beiden Einträge durch LRU entfernt wird, kann die gesamte Verbindung abbrechen
Eine einfache, aber effektive Lösung
- Kernidee: Wenn Pakete in einer Richtung beobachtet werden, wird auch der Eintrag für die Gegenrichtung gemeinsam aktualisiert
- Durch diesen einfachen Ansatz:
- werden beide bidirektionalen Einträge aktualisiert und rücken in der LRU-Entfernungsreihenfolge nach hinten
- sinkt die Wahrscheinlichkeit eines Szenarios, in dem nur ein Eintrag gelöscht wird und dadurch die gesamte Kommunikation abbricht
- zeigte sich in Benchmark-Tests eine deutlich verbesserte Netzwerkstabilität
Fazit und Lehren
- Dieser Fall zeigt, dass selbst in komplexen Systemen einfache Ideen große Veränderungen bewirken können
- Das Problem wurde auf Basis grundlegenden CS-Wissens über die Funktionsweise von NAT gelöst
- Eine andere Möglichkeit zur Umgehung des Problems: die NAT-Tabellengröße erhöhen
- Anerkennung für die Leidenschaft des Entwicklers, der das Problem mithilfe objektiver Evidenzdaten gründlich analysiert und dazu beigetragen hat
Wert des technischen Ansatzes
- Die Bedeutung, die eigentliche Ursache eines Problems zu verstehen und zu beheben
- Die Lehre, dass eine einfache Code-Änderung die Stabilität eines gesamten Systems stark verbessern kann
- Die Bedeutung, auch in komplexen Systemen die Grundprinzipien zu verstehen
1 Kommentare
Vielen Dank, dass Sie diese großartige Erfahrung mit uns geteilt haben!