Traffic Shaping mit tc und qdisc: Bandbreite gezielt steuern
AI generated
$
/etc
Linux
Traffic Shaping mit tc und qdisc
Bandbreite gezielt steuern

Ohne aktives Traffic Shaping teilt sich jeder Dienst auf einem Server die verfügbare Bandbreite nach dem Prinzip Wer zuerst kommt, überträgt zuerst, was insbesondere bei nächtlichen Backup-Läufen dazu führt, dass produktive HTTP-Antworten spürbar langsamer werden. Linux Traffic Control mit tc und den passenden qdisc-Typen erlaubt es, Bandbreite gezielt pro Dienst, Port oder IP zu begrenzen und Prioritäten sauber durchzusetzen.

11 Min. Lesezeit Linux Networking Performance

1. Warum ungebremster Backup-Traffic produktiven Verkehr ausbremst

Ein nächtlicher Backup-Job, der mehrere hundert Gigabyte über die Netzwerkverbindung eines Servers an einen entfernten Storage-Server überträgt, konkurriert direkt mit produktivem HTTP- und Datenbank-Verkehr um dieselbe physische Bandbreite. Ohne Priorisierung füllt der Backup-Prozess die Sendewarteschlange der Netzwerkkarte so weit, dass zeitkritische Pakete, etwa Antworten auf eingehende Shop-Anfragen, in derselben Warteschlange feststecken und spürbar verzögert ausgeliefert werden.

Dieses Phänomen wird als Bufferbloat bezeichnet und entsteht, weil viele Netzwerkkarten und Switches großzügig dimensionierte Puffer verwenden, die zwar Paketverluste bei kurzzeitigen Lastspitzen vermeiden, aber bei dauerhaft ausgelasteten Links zu wachsenden Latenzen führen, da Pakete lange in der Warteschlange verharren, bevor sie überhaupt gesendet werden. Linux Traffic Control adressiert genau dieses Problem, indem es die Reihenfolge und Rate, mit der Pakete das System verlassen, aktiv steuert, statt sie unkontrolliert dem Standardverhalten der Netzwerkkarte zu überlassen.

2. Grundlagen: Was tc und eine qdisc überhaupt sind

Das Kommando tc, Traffic Control, ist die Benutzerschnittstelle zu den Queueing-Disziplinen im Linux Kernel, kurz qdisc genannt. Jede Netzwerkschnittstelle besitzt standardmäßig eine root qdisc, die bestimmt, in welcher Reihenfolge und mit welcher Priorität ausgehende Pakete tatsächlich gesendet werden, bevor sie die Netzwerkkarte physisch verlassen. Ohne explizite Konfiguration verwendet der Kernel je nach Version pfifo_fast oder inzwischen häufiger fq_codel als vernünftige Standardeinstellung.

Qdiscs lassen sich in classless und classful unterteilen. Classless qdiscs wie fq_codel oder tbf behandeln den gesamten Verkehr einer Schnittstelle nach einer einzigen Strategie, während classful qdiscs wie HTB eine Baumstruktur aus Klassen aufspannen, denen jeweils eigene Bandbreiten-Limits und Prioritäten zugewiesen werden können. Für gezieltes Shaping, bei dem unterschiedliche Dienste unterschiedlich behandelt werden sollen, ist eine classful qdisc wie HTB in Kombination mit Filtern die passende Wahl.


# Aktuell konfigurierte qdisc einer Schnittstelle anzeigen
tc qdisc show dev eth0

# Statistiken inklusive verworfener Pakete pro qdisc anzeigen
tc -s qdisc show dev eth0

3. HTB: Hierarchisches Bandbreiten-Management mit Klassen

Der Hierarchical Token Bucket, kurz HTB, ist die gebräuchlichste qdisc für differenziertes Bandbreiten-Management, weil sie eine Baumstruktur aus Klassen mit jeweils eigenem rate- und ceil-Wert erlaubt. Der rate-Wert definiert die garantierte Mindestbandbreite einer Klasse, während ceil die maximale Bandbreite festlegt, die eine Klasse nutzen darf, sofern gerade keine andere Klasse ihre garantierte Rate benötigt. Diese Kombination erlaubt es, ungenutzte Bandbreite dynamisch an Klassen mit hohem Bedarf umzuverteilen, statt sie starr zu reservieren.

Innerhalb der HTB-Hierarchie werden Kindklassen für einzelne Dienste angelegt, etwa eine Klasse für produktiven HTTP-Verkehr mit hoher garantierter Rate und eine separate Klasse für Backup-Traffic mit niedriger garantierter, aber flexibler maximaler Rate. Die tatsächliche Zuordnung eines Pakets zu einer Klasse übernimmt dabei nicht HTB selbst, sondern ein nachgeschalteter Filter, üblicherweise auf Basis von u32-Regeln oder, moderner, über Firewall-Marks, die zuvor mit iptables oder nftables gesetzt wurden.


# HTB Root qdisc mit Standardklasse 30 für unklassifizierten Verkehr
tc qdisc add dev eth0 root handle 1: htb default 30

# Elternklasse mit Gesamtbandbreite der Schnittstelle
tc class add dev eth0 parent 1: classid 1:1 htb rate 1000mbit ceil 1000mbit

# Klasse für produktiven HTTP Verkehr, hohe garantierte Rate
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 800mbit ceil 1000mbit prio 1

# Klasse für Backup Traffic, niedrige garantierte, aber begrenzte maximale Rate
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 100mbit ceil 200mbit prio 3

4. fq_codel: Der moderne Standard gegen Bufferbloat

fq_codel kombiniert Fair Queueing, das den Verkehr verschiedener Flows gleichmäßig auf mehrere interne Warteschlangen verteilt, mit dem CoDel-Algorithmus, der Pakete gezielt verwirft, sobald die Verweildauer in der Warteschlange einen bestimmten Schwellenwert überschreitet. Dieser Ansatz reduziert Latenz unter Last spürbar, ohne die maximale Durchsatzrate signifikant zu beeinträchtigen, weshalb fq_codel seit mehreren Kernel-Versionen als Standard-qdisc für viele Distributionen dient.

Anders als HTB bietet fq_codel keine explizite Bandbreiten-Begrenzung, sondern optimiert primär Latenz und Fairness zwischen konkurrierenden Verbindungen. In der Praxis wird fq_codel deshalb häufig als Kindqdisc innerhalb einer HTB-Klasse eingesetzt, sodass die Klasse selbst die harte Bandbreitengrenze für etwa den Backup-Verkehr setzt, während fq_codel innerhalb dieser Grenze für faire Verteilung zwischen einzelnen TCP-Verbindungen und niedrige Latenz sorgt.


# fq_codel als Kindqdisc der Backup Klasse für faire Verteilung einsetzen
tc qdisc add dev eth0 parent 1:20 handle 20: fq_codel

5. tbf: Einfache Ratenbegrenzung ohne Klassenhierarchie

Der Token Bucket Filter, kurz tbf, eignet sich für Szenarien, in denen keine differenzierte Klassenhierarchie benötigt wird, sondern lediglich die Gesamtrate einer Schnittstelle oder eines einzelnen Prozesses auf einen festen Wert begrenzt werden soll. Das Prinzip basiert auf einem virtuellen Eimer, der kontinuierlich mit Token gefüllt wird, wobei jedes gesendete Byte ein Token verbraucht, sodass die effektive Senderate exakt der konfigurierten Rate entspricht, solange genügend Token verfügbar sind.

Der Parameter burst bestimmt, wie viele Token im Eimer gesammelt werden können, bevor überschüssige Kapazität verfällt, und beeinflusst damit, wie tolerant tbf gegenüber kurzen Lastspitzen oberhalb der konfigurierten Rate ist. Für ein einfaches, isoliertes Backup-Interface oder eine dedizierte VPN-Schnittstelle, über die ausschließlich ein einzelner Backup-Prozess läuft, ist tbf oft die unkompliziertere Alternative zu einer vollständigen HTB-Hierarchie.


# Ausgehende Rate auf einer dedizierten Backup Schnittstelle begrenzen
tc qdisc add dev eth1 root tbf rate 100mbit burst 32kbit latency 400ms

6. Verkehr gezielt klassifizieren: Firewall-Marks statt starrer u32-Filter

Klassische tc-Filter mit der u32-Syntax erlauben zwar eine direkte Zuordnung nach IP-Adresse oder Port, gelten aber als fehleranfällig und schwer lesbar, sobald mehrere Kriterien kombiniert werden. In der Praxis hat sich deshalb ein zweistufiger Ansatz etabliert: Zunächst markiert eine iptables- oder nftables-Regel Pakete anhand von Port, Prozess oder Cgroup mit einer Firewall-Mark, anschließend übernimmt ein einfacher tc-Filter vom Typ fw diese Markierung und ordnet das Paket der passenden HTB-Klasse zu.

Dieser Ansatz macht die Klassifikationslogik deutlich wartbarer, weil sie an einer zentralen Stelle im Firewall-Regelwerk gepflegt wird, statt über verstreute tc-Filter-Definitionen, und lässt sich zudem problemlos mit ohnehin vorhandenen Firewall-Regeln kombinieren. Für einen Backup-Prozess, der über einen festen Port oder eine dedizierte Quell-IP kommuniziert, genügt eine einzelne Markierungsregel, um den gesamten zugehörigen Datenverkehr zuverlässig der Backup-Klasse zuzuordnen.


# Backup Traffic anhand des Zielports mit einer Firewall Mark versehen
iptables -t mangle -A OUTPUT -p tcp --dport 873 -j MARK --set-mark 20

# tc Filter, der die Markierung der passenden HTB Klasse zuordnet
tc filter add dev eth0 parent 1: protocol ip prio 1 handle 20 fw classid 1:20

7. Eingehenden Verkehr drosseln: Ingress Policing statt Egress Shaping

Alle bisher gezeigten qdisc-Typen wirken ausschließlich auf ausgehenden Verkehr, weil tc konzeptionell nur die Sendewarteschlange einer Schnittstelle beeinflussen kann, nicht aber Pakete, die bereits über das physische Medium empfangen wurden. Für eingehenden Verkehr, etwa um einen großen Datei-Download eines einzelnen Clients zu begrenzen, bevor er die interne Netzwerkkapazität eines Servers ausschöpft, kommt stattdessen die spezielle ingress qdisc zusammen mit einer police-Aktion zum Einsatz.

Policing unterscheidet sich grundlegend von Shaping: Statt überschüssige Pakete in einer Warteschlange zu verzögern, verwirft Policing Pakete oberhalb der konfigurierten Rate sofort, was zu höheren TCP-Retransmission-Raten führen kann, aber ohne zusätzlichen Speicherbedarf auskommt. Für noch feinere Kontrolle über eingehenden Verkehr, inklusive echtem Queueing statt hartem Verwerfen, lässt sich ein IFB-Gerät, Intermediate Functional Block, einsetzen, das eingehenden Verkehr virtuell umleitet und ihn dadurch wie ausgehenden Verkehr mit vollwertigen qdiscs wie HTB behandelbar macht.


# Einfaches Policing eingehenden Verkehrs auf 500mbit begrenzen
tc qdisc add dev eth0 handle ffff: ingress
tc filter add dev eth0 parent ffff: protocol ip u32 match u32 0 0 \
  police rate 500mbit burst 64k drop flowid :1

# Alternative mit IFB für vollwertiges Shaping eingehenden Verkehrs
modprobe ifb numifbs=1
ip link set dev ifb0 up
tc qdisc add dev eth0 handle ffff: ingress
tc filter add dev eth0 parent ffff: matchall action mirred egress redirect dev ifb0
tc qdisc add dev ifb0 root handle 1: htb default 10

8. Praxisbeispiel: Backup-Traffic drosseln ohne Produktivverkehr zu stören

Ein vollständiges Setup für einen Magento Hosting-Server kombiniert die vorherigen Bausteine zu einer konsistenten Konfiguration: HTB als Root-qdisc mit einer hoch priorisierten Klasse für Web- und Datenbankverkehr sowie einer separat begrenzten Klasse für rsync- oder Borg-Backup-Traffic, gekoppelt an fq_codel innerhalb der Backup-Klasse für faire Verteilung zwischen mehreren parallelen Backup-Streams. Firewall-Marks auf Basis des Backup-Zielports übernehmen die Klassifikation zuverlässig, ohne die Produktivklasse zu beeinflussen.

Entscheidend ist, dass die default-Klasse in der HTB-Hierarchie, im Beispiel Klasse 30, eine sinnvolle Rate erhält, damit unklassifizierter Verkehr weder komplett blockiert noch unbegrenzt priorisiert wird. In der Praxis bewährt es sich, die default-Klasse auf ein moderates Niveau zwischen produktivem Verkehr und Backup-Verkehr zu setzen, sodass neue, noch nicht explizit klassifizierte Dienste weder Backup-Traffic verdrängen noch selbst von ihm gestört werden.

9. Monitoring und Feintuning der Shaping-Konfiguration

Der Befehl tc -s class show dev eth0 liefert pro Klasse detaillierte Statistiken zu übertragenen Bytes, verworfenen Paketen und der Zeit, die eine Klasse oberhalb ihrer garantierten Rate verbracht hat. Ein kontinuierlich hoher Wert an verworfenen Paketen in der Produktivklasse deutet darauf hin, dass die konfigurierten Raten die tatsächliche Lastverteilung nicht mehr korrekt abbilden und angepasst werden sollten, bevor Nutzer die Auswirkungen als Ladezeitprobleme wahrnehmen.

Für die laufende Überwachung empfiehlt sich die regelmäßige Auswertung dieser Statistiken über ein Monitoring-System, kombiniert mit aktiven Latenzmessungen während bekannter Backup-Fenster, um zu verifizieren, dass die Shaping-Konfiguration tatsächlich wie beabsichtigt wirkt. Änderungen an rate- und ceil-Werten sollten dabei schrittweise erfolgen, da zu aggressive Drosselung von Backup-Traffic die Backup-Fenster unnötig verlängern und im schlimmsten Fall mit dem nächsten geplanten Lauf kollidieren kann.


# Detaillierte Klassen Statistiken inklusive Drop Zaehler anzeigen
tc -s class show dev eth0

# Aktuelle Filterzuordnungen zur Kontrolle auflisten
tc filter show dev eth0
qdisc Typ Hauptzweck Typischer Einsatz
pfifo_fast classless Einfache Standard-Warteschlange ohne Priorisierung Kernel-Default ohne explizite Konfiguration
fq_codel classless Fair Queueing plus aktive Latenzreduzierung Moderner Standard gegen Bufferbloat
tbf classless Einfache, harte Ratenbegrenzung Isolierte Backup- oder VPN-Schnittstellen
HTB classful Hierarchische Bandbreiten-Klassen mit rate und ceil Differenziertes Shaping mehrerer Dienste gleichzeitig

Mironsoft

Server-Administration, Docker-Hosts und Performance-Tuning

Linux-Server, die niemand im Team richtig versteht?

Wir übernehmen Setup, Absicherung und Performance-Tuning von Linux-Servern und Docker-Hosts für Magento-Deployments, dokumentiert und nachvollziehbar statt gewachsen und unklar.

Server-Audit

Bestehende Server-Konfiguration auf Sicherheitslücken und Performance-Bremsen prüfen.

Docker-Host-Setup

Produktionsreife Docker-Umgebungen für Magento sauber aufsetzen und absichern.

Monitoring & Tuning

Ressourcenverbrauch messen und Systemd, Kernel und Dienste gezielt optimieren.

10. Zusammenfassung

Traffic Shaping

Kernwerkzeug

tc verwaltet qdisc, Klassen und Filter im Kernel

Für Klassen-Hierarchien

HTB mit rate und ceil pro Dienst

Gegen Bufferbloat

fq_codel als Kindqdisc innerhalb einer HTB-Klasse

Klassifikation

Firewall-Marks plus tc filter Typ fw statt komplexer u32-Regeln

11. FAQ: Traffic Shaping

1Was ist der Unterschied zwischen rate und ceil bei HTB?
rate ist die garantierte Mindestbandbreite einer Klasse, ceil die maximale Bandbreite, die sie nutzen darf, wenn andere Klassen ihre garantierte Rate gerade nicht ausschöpfen. So lässt sich ungenutzte Bandbreite dynamisch verteilen.
2Kann ich fq_codel und HTB gleichzeitig verwenden?
Ja, das ist sogar der übliche Ansatz: HTB setzt die harte Bandbreitengrenze pro Klasse, während fq_codel als Kindqdisc innerhalb dieser Klasse für faire Verteilung und niedrige Latenz zwischen den enthaltenen Verbindungen sorgt.
3Wann sollte ich tbf statt HTB verwenden?
tbf eignet sich für einfache Szenarien mit nur einer Rate ohne Klassenhierarchie, etwa eine dedizierte Backup-Schnittstelle. Sobald mehrere Dienste unterschiedlich priorisiert werden sollen, ist HTB die passendere Wahl.
4Warum werden Firewall-Marks statt direkter u32-Filter empfohlen?
Firewall-Marks lassen sich zentral im ohnehin gepflegten Firewall-Regelwerk verwalten und mit komplexer Logik wie Prozess- oder Cgroup-Zuordnung kombinieren, während u32-Filter bei mehreren Kriterien schnell unübersichtlich und fehleranfällig werden.
5Wie wirkt sich Traffic Shaping auf eingehenden Verkehr aus?
tc qdisc kontrolliert grundsätzlich nur ausgehenden Verkehr einer Schnittstelle. Für eingehenden Verkehr wird typischerweise eine ingress qdisc mit Policing kombiniert, was Pakete oberhalb der Rate direkt verwirft statt sie zu puffern.
6Was passiert mit Paketen, die keiner Klasse zugeordnet werden können?
Sie landen in der default-Klasse der HTB-Hierarchie, die deshalb eine sinnvolle eigene Rate erhalten sollte, damit unklassifizierter Verkehr weder blockiert noch unbegrenzt priorisiert wird.
7Kann ich die Shaping-Konfiguration ohne Neustart des Servers ändern?
Ja, tc-Befehle wirken sofort auf die laufende Konfiguration. Klassen und Filter lassen sich mit tc class change beziehungsweise tc filter replace anpassen, ohne die gesamte qdisc-Hierarchie neu aufzubauen.
8Wie erkenne ich, ob Bufferbloat mein Problem ist?
Ein deutlicher Anstieg der Latenz unter Last, etwa gemessen mit ping während eines aktiven Backup-Laufs, während der Durchsatz selbst normal bleibt, ist ein starkes Indiz für Bufferbloat durch überdimensionierte Puffer.
9Beeinflusst Traffic Shaping die CPU-Last des Servers?
Der Overhead ist bei modernen qdisc-Implementierungen wie HTB und fq_codel gering, sollte bei sehr hohen Paketraten im zweistelligen Gigabit-Bereich aber dennoch im Monitoring beobachtet werden.
10Muss ich die Shaping-Konfiguration bei jedem Boot neu setzen?
Ja, tc-Regeln sind standardmäßig nicht persistent und müssen über ein Startskript, eine systemd-Unit oder ein Netzwerkkonfigurations-Tool beim Systemstart erneut angewendet werden.