CPU Limits: Weight vs. Quota (Artikel 375)
Tiefgehende Analyse der CPU-Ressourcensteuerung unter Linux. Erfahren Sie den Unterschied zwischen relativer Gewichtung und harten Zeitkontingenten sowie die Diagnose von Throttling.
# CPU Quotas Deep Dive: Performance-Drosselung verstehen
TL;DR / Management Summary Wer CPU-Limits in Containern oder Cgroups setzt, muss zwei Konzepte unterscheiden: Weight (Weights/Shares) regelt die Verteilung bei Überlastung (“Wer bekommt wie viel vom Rest?”), während Quotas (Max) harte Zeitlimits setzen (“Egal wie viel frei ist, du bekommst nicht mehr als X”). Ein Senior Admin nutzt Quotas, um Kosten und Kapazitäten zu planen, muss aber das Throttling überwachen – den Moment, in dem der Kernel einen Prozess künstlich anhält, weil sein Zeitkontingent abgelaufen ist.
# 1. Einführung & Architektur
Shares vs. Quotas.
- Weight / Shares (Relativ): Garantierte Mindestleistung. Wenn das System im Leerlauf ist, darf der Prozess 100% nutzen. Wenn alle Kerne voll sind, bekommt er seinen Anteil (z.B. 50%).
- Quota / Max (Absolut): Hartes Limit. Wenn ein Prozess auf 1 Kern limitiert ist, wird er bei Erreichen dieses Limits gestoppt, auch wenn 63 andere Kerne im System schlafen.
# Die Throttling-Logik (Mermaid)
graph TD
A[Process Execution] --> B{Quota Period: 100ms}
B --> C[Consumed: 50ms]
C --> D{Is Quota reached?}
D -->|No| E[Continue Execution]
D -->|Yes| F[THROTTLED: Process Paused]
F --> G[Wait for next Period]
G --> B
subgraph "Kernel Stats"
F --> H[nr_throttled +1]
F --> I[throttled_time +ms]
end
# 2. Implementierung in Cgroups v2
Die moderne Steuerung.
In v2 heißt die Datei cpu.max. Die Syntax ist: QUOTA PERIOD (in Mikrosekunden).
# Beispiel: Limit auf 2 CPUs setzen (200ms pro 100ms Periode)
echo "200000 100000" | sudo tee /sys/fs/cgroup/myapp/cpu.max
# Relative Gewichtung
# Standard ist 100. Höherer Wert = mehr Prio.
echo 200 | sudo tee /sys/fs/cgroup/myapp/cpu.weight
# 3. Diagnose: Das Throttling-Problem
Warum ist die App so langsam?
Eine Applikation kann sich langsam anfühlen, obwohl die CPU-Last laut top nur bei 50% liegt. Wenn sie auf 50% gedrosselt ist, wartet sie die halbe Zeit auf den Kernel.
# Throttling-Stats auslesen
cat /sys/fs/cgroup/myapp/cpu.stat
# Achten Sie auf:
# nr_throttled: Wie oft wurde gebremst?
# throttled_usec: Wie viele Mikrosekunden wurde insgesamt gewartet?
Profi-Tipp: Wenn throttled_usec stetig steigt, ist Ihr Limit zu niedrig für die Lastspitzen der Applikation.
# 4. Day-2 Operations: Burst-Management
Kurze Lastspitzen erlauben.
Moderne Kernel (ab 5.14) unterstützen CPU Bursting. Dies erlaubt es Prozessen, “Guthaben” aus ungenutzten Perioden anzusparen, um kurze Spitzen über das Quota-Limit hinaus abzufangen.
# In cpu.max einen dritten Wert für Burst hinzufügen (in Mikrosekunden)
echo "200000 100000 50000" > cpu.max
# 5. Troubleshooting & “War Stories”
Wenn der Scheduler zu streng wird.
# Story 1: “Das Java-GC Dilemma”
Symptom: Eine Java-Applikation hat massive Latenz-Spikes beim Garbage Collection (GC). Die CPU-Last ist im Schnitt niedrig.
Ursache: Der GC startet viele Threads gleichzeitig, um den RAM zu bereinigen. Diese Threads verbrauchen das 100ms-Quota in den ersten 10ms der Periode. Die App wird für die restlichen 90ms komplett eingefroren.
Lösung: Erhöhen Sie das Quota oder verringern Sie die Anzahl der GC-Threads in der JVM (-XX:ParallelGCThreads).
# Story 2: “Der Multi-Core Trugschluss”
Symptom: Ein Prozess ist auf cpu.max=100000 (1 Kern) limitiert, läuft aber auf einem 64-Kern-System trotzdem in Throttling, obwohl er nur 10% CPU-Last anzeigt.
Ursache: Die Applikation ist Multi-threaded. 10 Threads verbrauchen jeweils 10ms -> Quota von 100ms ist sofort erreicht.
Lösung: Berechnen Sie Quotas immer basierend auf: Kern-Anzahl * Auslastung. Für eine Multi-Threaded App ist ein Limit von 1 Kern oft zu wenig.
# 6. Fazit & Empfehlung
- Wahl: Nutzen Sie Weights für faire Verteilung. Nutzen Sie Quotas nur für harte Abrechnungs-Limits (Cloud/Hosting).
- Monitoring: Überwachen Sie
nr_throttledin Ihrem SIEM/Monitoring (Artikel 311). - Best Practice: Setzen Sie die Periode (
cpu.maxzweiter Wert) niemals zu niedrig. 100ms (100000) ist ein bewährter Standard.
# Anhang: Cheatsheet
| Aufgabe | Pfad / Befehl |
|---|---|
| v2 Limit (2 Kerne) | echo "200000 100000" > cpu.max |
| v2 Gewichtung | echo 500 > cpu.weight |
| v1 Quota setzen | echo 20000 > cpu.cfs_quota_us |
| v1 Shares setzen | echo 1024 > cpu.shares |
| Stats prüfen | cat cpu.stat |
| Throttling finden | grep throttled cpu.stat |
| systemd Slice Limit | CPUQuota=200% |
| systemd Weight | CPUWeight=500 |