Die versteckten Linux-Defaults, die Ihren Ceph-Cluster ausbremsen
Fünf Kernel-Einstellungen, die 2026 den Unterschied zwischen mittelmäßiger und herausragender Ceph-Performance machen — und warum die Defaults für Storage-Cluster die falsche Wahl sind.
Wer 2026 einen Ceph-Cluster betreibt — ob als Backend für Proxmox-VMs, Kubernetes Persistent Volumes oder als souveräner S3-Ersatz — investiert in gute Hardware: NVMe-SSDs, 25-Gbit-Netzwerke, genügend RAM pro OSD. Dann wundert man sich, warum die Latenz trotzdem schwankt — warum die P99-Werte sporadisch in die Höhe schießen, obwohl die Hardware eigentlich mitspielt.
Die Ursache liegt oft nicht in Ceph selbst, sondern eine Ebene tiefer: im Linux-Kernel. Jede Distribution liefert Defaults aus, die für den allgemeinen Einsatz optimiert sind — Webserver, Datenbanken, Batch-Verarbeitung. Linux maximiert dabei den Durchsatz, nicht die Latenz. Für Ceph ist das ein Problem: Ein Storage-Cluster, der VMs, Container und Datenbanken bedient, braucht vorhersagbare, niedrige Antwortzeiten bei jeder einzelnen I/O-Operation.
Dieser Artikel zeigt fünf Kernel-Einstellungen, die auf jedem Ceph-Node geprüft und angepasst werden sollten — inklusive der Hintergründe, warum die Defaults problematisch sind. Die Empfehlungen gelten für aktuelle Ceph-Releases (Squid 19.2.x, Tentacle 20.2.x) auf aktuellen Linux-Distributionen (Debian 12, Ubuntu 24.04, Rocky Linux 9) gleichermaßen.
Einstellung | Default | Auswirkung auf Ceph | Ursache |
|---|---|---|---|
| 60 | 10–100 µs pro Page Fault, bei Swap auf NVMe; 1–5 ms bei Netzwerkspeicher | OSD-Heap wird auf Disk verdrängt |
Transparent Huge Pages |
| 10–50 ms Compaction-Stalls |
|
CPU-Governor |
| 10–50 µs Frequency-Ramp | DVFS-Übergänge bei wechselnder Last |
C-States | alle aktiviert | 50–100 µs Wake-Latenz | CPU muss Spannung und Takt wiederherstellen |
I/O-Scheduler |
| unnötiger Overhead bei NVMe | Scheduling-Logik, die NVMe nicht braucht |
Diese Defaults existieren aus gutem Grund: Sie sparen Strom und maximieren den Gesamtdurchsatz. Für 99 % aller Workloads ist das richtig. Ein Ceph-Cluster, der konsistente IOPS bei niedriger Latenz liefern soll, gehört zum anderen Prozent.
1. Swappiness auf 0 setzen
Warum das für Ceph kritisch ist
Mit vm.swappiness = 60 behandelt der Kernel File-backed Pages (Page Cache) und Anonymous Pages (Heap, Stack) ungefähr gleich, wenn Speicher knapp wird. Das bedeutet: Der Heap eines OSD-Prozesses kann auf Disk geswappt werden, obwohl es Page-Cache-Einträge gibt, die problemlos verworfen werden könnten.
Ceph OSD-Daemons halten BlueStore-Caches, RocksDB-Block-Caches und diverse interne Datenstrukturen im Heap. Wenn dieser Heap auf Disk wandert und dann per Page Fault wieder geladen werden muss, steht der OSD-Thread still — mitten in einer Client-I/O-Operation. Auf NVMe dauert ein Swap-Read 10–100 µs. Auf langsamerem Storage deutlich länger.
Besonders kritisch wird das bei Recovery-Operationen: Ceph-OSDs verbrauchen während Backfill und Recovery deutlich mehr Speicher als im Normalbetrieb. Die Ceph-Dokumentation empfiehlt, mindestens 8 GB RAM pro OSD einzuplanen — gerade weil dieser Overhead in Spitzenzeiten anfällt. In hyper-konvergenten Setups mit Proxmox VE 9 oder Kubernetes auf denselben Nodes ist das Risiko von Speicherdruck zusätzlich erhöht.
Die Lösung
# Aktuellen Wert prüfen
sysctl vm.swappiness
# Persistent setzen
echo 'vm.swappiness = 0' | sudo tee /etc/sysctl.d/90-ceph.conf
sudo sysctl -p /etc/sysctl.d/90-ceph.confMit swappiness=0 werden Anonymous Pages erst dann geswappt, wenn das System kritisch wenig Speicher hat. Der Page Cache wird zuerst verworfen — das ist sicher, weil Datei-Inhalte jederzeit von Disk nachgeladen werden können.
Verifizierung
# Swap-Aktivität beobachten (si/so sollten bei 0 liegen)
vmstat 1 | awk '{print $7, $8}'
# Aktuellen Swap-Verbrauch prüfen
free -hWichtig: Swappiness auf 0 bedeutet nicht, dass Swap deaktiviert ist. Es bedeutet, dass der Kernel den Heap so lange wie möglich im RAM behält. Bei ernsthaftem Speichermangel wird trotzdem geswapt — besser als ein OOM-Kill.
2. Transparent Huge Pages deaktivieren
Warum THP und Ceph nicht zusammenpassen
Transparent Huge Pages (THP) fassen automatisch 4-KB-Pages zu 2-MB-Pages zusammen, um TLB-Misses zu reduzieren. Das klingt gut, aber der Mechanismus hat einen Preis: Der Kernel-Thread khugepaged scannt kontinuierlich den Speicher auf der Suche nach zusammenlegbaren Pages. Dafür muss er Memory Compaction durchführen — physische Pages verschieben, um zusammenhängende 2-MB-Bereiche zu schaffen.
Während dieser Compaction hält der Kernel Locks, die Memory-Allokationen blockieren können. Ein OSD-Thread, der gerade Speicher anfordert, wartet dann 10–50 Millisekunden. Nicht Mikrosekunden — Millisekunden. Das sind Größenordnungen, die aus einem normalen P99-Wert einen Ausreißer machen.
Ceph hat dieses Problem offiziell adressiert: Seit 2019 existiert ein Tracker-Eintrag, der THP für Ceph-Daemons als problematisch einstuft. Die Empfehlung lautet, THP systemweit zu deaktivieren, bis eine selektive Nutzung über madvise implementiert ist. Auch ceph-ansible und cephadm setzen disable_transparent_hugepage standardmäßig auf True — an dieser Empfehlung hat sich auch mit Ceph Tentacle (2025) und den aktuellen Kernel-Versionen nichts geändert.
Ein zusätzliches Problem: THP interagiert schlecht mit den Memory-Allocators, die Ceph nutzt (tcmalloc, jemalloc). Berichte aus der Ceph-Community zeigen, dass THP mit tcmalloc zu unkontrolliertem Speicherwachstum führen kann — der RSS-Verbrauch steigt über das konfigurierte osd_memory_target hinaus, im schlimmsten Fall bis zum OOM-Kill.
Die Lösung
# Status prüfen
cat /sys/kernel/mm/transparent_hugepage/enabled
# Ausgabe: [always] madvise never
# Sofort deaktivieren
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
# Persistent machen via systemd-Service
cat <<'EOF' | sudo tee /etc/systemd/system/disable-thp.service
[Unit]
Description=Disable Transparent Huge Pages
DefaultDependencies=no
After=sysinit.target local-fs.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled && echo never > /sys/kernel/mm/transparent_hugepage/defrag'
[Install]
WantedBy=basic.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable disable-thp.serviceVerifizierung
# Compaction-Aktivität beobachten (sollte nicht steigen)
watch -n1 'grep -E "compact_|thp_" /proc/vmstat'
# Huge-Page-Nutzung prüfen
grep AnonHugePages /proc/meminfoTrade-off: Ohne THP verliert man die automatische Huge-Page-Optimierung. Für Ceph ist das kein Verlust — BlueStore verwaltet seinen eigenen Cache und profitiert nicht von transparenten Huge Pages.
3. CPU-Governor auf Performance setzen
Warum Frequency Scaling Ceph-Latenzen verursacht
Moderne CPUs nutzen Dynamic Voltage and Frequency Scaling (DVFS), um Strom zu sparen. Der ondemand-Governor (häufiger Default) überwacht die CPU-Auslastung und erhöht die Frequenz erst, wenn die Last steigt.
Das Problem für Ceph: OSD-Workloads sind bursty. Ein OSD ist kurz idle, dann kommt ein Client-Request, dann ist er wieder idle. Der Governor sieht niedrige Auslastung und hält die Frequenz niedrig. Die ersten Instruktionen eines eingehenden I/O-Requests laufen mit reduzierter Taktfrequenz — der Frequenz-Ramp dauert 10–50 µs.
Dieser Effekt wurde in der Ceph-Community konkret gemessen: In einem Benchmark mit NVMe-SSDs lag die Performance mit dem powersave-Governor signifikant unter der mit dem performance-Governor, weil die CPU bei moderater Auslastung (um die 27 %) gar nicht hochskalierte. Erst der Wechsel auf performance brachte die erwarteten IOPS.
Auch das Ceph-Blog empfiehlt für All-Flash-Deployments explizit das network-latency- oder latency-performance-Profil von TuneD, das unter anderem den CPU-Governor auf performance setzt.
Die Lösung
# Aktuellen Governor prüfen
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# Auf allen Cores setzen
for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
echo performance | sudo tee "$cpu"
done
# Oder via TuneD (empfohlen für Ceph-Nodes)
sudo tuned-adm profile latency-performanceVerifizierung
# Frequenz prüfen (sollte konstant am Maximum liegen)
grep MHz /proc/cpuinfo | sort -t: -k2 -n | tail -4
# Über turbostat (falls installiert)
turbostat --interval 1 --show Core,CPU,Bzy_MHzTrade-off: Höherer Stromverbrauch. In einem Rechenzentrum, in dem Ceph-Nodes ohnehin 24/7 laufen, ist das ein akzeptabler Preis für konsistente Latenzen.
4. Tiefe C-States einschränken
Warum idle CPUs zum Latenz-Problem werden
Selbst mit dem performance-Governor gehen idle CPU-Cores in Schlafzustände (C-States), um Strom zu sparen:
C-State | Was passiert | Wake-Latenz |
|---|---|---|
C0 | Aktiv | 0 |
C1 | Clock gestoppt | 1–5 µs |
C1E | Clock + Spannung reduziert | 5–10 µs |
C3 | L1/L2-Cache kalt | 30–50 µs |
C6 | Spannung abgeschaltet, State in RAM gesichert | 50–100 µs |
Ein Ceph-OSD wartet auf den nächsten Client-Request. Die CPU fällt in C6. Der Request kommt — und die CPU braucht 50–100 µs, um wieder voll aktiv zu sein. Diese Latenz addiert sich zu jeder I/O-Operation.
Dieser Effekt ist bei Ceph besonders relevant, weil die Ceph-Mailing-Liste einen konkreten Fall dokumentiert: Nach dem Setzen von cpu_dma_latency=0 auf allen OSD-Nodes stieg der Recovery-Durchsatz um konservativ 30 % — von ~16 GB/s auf ~22 GB/s. Die CPUs liefen danach in Turbo statt in niedrigen C-States.
Die Lösung
Option 1: Kernel-Boot-Parameter (empfohlen)
# In /etc/default/grub zu GRUB_CMDLINE_LINUX hinzufügen:
processor.max_cstate=1 intel_idle.max_cstate=0
# GRUB aktualisieren
sudo update-grub # Debian/Ubuntu
# oder
sudo grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL/RockyOption 2: Zur Laufzeit (temporär)
# C-States > C1 deaktivieren
for state in /sys/devices/system/cpu/cpu*/cpuidle/state[2-9]/disable; do
echo 1 | sudo tee "$state"
doneOption 3: Via /dev/cpu_dma_latency (wie im Ceph-Mailing-List-Case)
# Hält CPUs in C0/C1 solange der File-Descriptor offen ist
exec 3>/dev/cpu_dma_latency
echo -ne '\x00\x00\x00\x00' >&3Verifizierung
# C-State-Residency prüfen
turbostat --interval 1 --show Core,C1%,C3%,C6%
# C3% und C6% sollten bei 0 liegenHinweis für AMD-Systeme: AMD-Rome-Prozessoren (EPYC 7002-Serie) und neuer scheinen weniger empfindlich gegenüber C-State-Übergängen zu sein. Trotzdem empfehlen die offiziellen Ceph-Benchmarks, C-States einzuschränken.
5. I/O-Scheduler für NVMe anpassen
Warum NVMe-Drives keinen Scheduler brauchen
Für traditionelle HDDs und SATA-SSDs verwaltet der Linux-I/O-Scheduler die Reihenfolge der Requests, um Seek-Zeiten zu minimieren. Der Default mq-deadline priorisiert Reads und ordnet Writes zusammenhängend an.
NVMe-Drives haben eigene Controller mit tiefen internen Queues und brauchen diese Optimierung nicht. Jeder Request, den der Kernel umordnet oder verzögert, ist verschwendete CPU-Zeit und zusätzliche Latenz. Für NVMe-Drives sollte der Scheduler auf none stehen — das ist ein reiner Pass-through.
Dies wird auch in der Ceph-Community und von Enterprise-Distributionen wie Red Hat empfohlen: Enterprise-NVMe-SSDs mit eigenen Power-Safe-Caches und Controllern fahren am besten mit none.
Die Lösung
# Aktuellen Scheduler prüfen
cat /sys/block/nvme0n1/queue/scheduler
# Auf none setzen (pro NVMe-Device)
echo none | sudo tee /sys/block/nvme0n1/queue/scheduler
# Persistent via udev-Regel
cat <<'EOF' | sudo tee /etc/udev/rules.d/60-ceph-scheduler.rules
# NVMe: kein Scheduler
ACTION=="add|change", KERNEL=="nvme*", ATTR{queue/scheduler}="none"
# SATA/SAS SSD: mq-deadline
ACTION=="add|change", KERNEL=="sd*", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"
# HDD: mq-deadline
ACTION=="add|change", KERNEL=="sd*", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="mq-deadline"
EOF
sudo udevadm control --reload-rulesVerifizierung
# Für alle Block-Devices prüfen
for dev in /sys/block/*/queue/scheduler; do
echo "$dev: $(cat $dev)"
doneBonus: Ceph-spezifische Einstellungen
Neben den Kernel-Tunings gibt es einige Ceph-interne Stellschrauben, die in Kombination mit den obigen Änderungen relevant werden:
BlueStore-Memory-Target: Mit den Kernel-Tunings (kein Swap, kein THP) kann BlueStore seinen Cache effektiver nutzen. Der Default von 4 GB pro OSD ist ein Kompromiss; bei NVMe-Deployments lohnt es sich, auf 8 GB oder mehr zu gehen:
ceph config set osd osd_memory_target 8589934592 # 8 GBNUMA-Pinning: Auf Dual-Socket-Systemen sollten OSD-Prozesse auf denselben NUMA-Node gepinnt werden, auf dem die zugehörigen NVMe-Drives und NICs sitzen. Jeder Zugriff über den QPI/UPI-Link zwischen den Sockets kostet zusätzliche Latenz.
Netzwerk: Für Ceph-Cluster mit 10 Gbit oder mehr sollte Jumbo Frames (MTU 9000) aktiviert sein, sofern alle Switches im Storage-Netzwerk das unterstützen. Bei modernen Linux-Kernels (6.x) sind die TCP-Defaults bereits gut gewählt — viele der älteren Tuning-Guides mit angepassten Buffer-Größen sind für aktuelle Kernel nicht mehr sinnvoll oder sogar kontraproduktiv.
Alles auf einen Blick: Quick-Audit
#!/bin/bash
echo "=== Swappiness ==="
sysctl vm.swappiness
echo "=== Transparent Huge Pages ==="
cat /sys/kernel/mm/transparent_hugepage/enabled
echo "=== CPU Governor ==="
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || echo "N/A"
echo "=== C-States (C3+) ==="
for state in /sys/devices/system/cpu/cpu0/cpuidle/state[2-9]/disable; do
[ -f "$state" ] && echo "$(dirname $state | xargs basename): disabled=$(cat $state)"
done
echo "=== I/O Scheduler (NVMe) ==="
for dev in /sys/block/nvme*/queue/scheduler; do
[ -f "$dev" ] && echo "$(echo $dev | grep -o 'nvme[^/]*'): $(cat $dev)"
doneDesign-Philosophie: Wann diese Tunings sinnvoll sind
Jede der beschriebenen Optimierungen tauscht Durchsatz oder Stromverbrauch gegen Latenz:
Optimierung | Was wir aufgeben | Was wir gewinnen |
|---|---|---|
| Page-Cache-Effizienz bei Speicherdruck | OSD-Heap bleibt im RAM |
THP deaktiviert | Automatische Huge Pages | Keine Compaction-Stalls |
Performance-Governor | Stromsparfunktion | Keine Frequency-Ramp-Verzögerungen |
C-State-Limits | Stromverbrauch im Idle | Vorhersagbare Wake-Latenzen |
I/O-Scheduler | Request-Umordnung | Direkter NVMe-Zugriff |
Diese Tunings sind nicht für jeden Einsatzzweck richtig. Auf einem Entwicklungssystem, einem reinen Batch-Processing-Server oder einem speicherknappen System können die Defaults die bessere Wahl sein.
Für einen produktiven Ceph-Cluster, der konsistente IOPS und niedrige Latenzen für VMs, Container oder Datenbank-Backends liefern soll, sind sie dagegen ein Muss. Gerade in All-Flash-Deployments mit NVMe ist die Hardware oft nicht der Engpass — sondern der Kernel, der für einen anderen Anwendungsfall optimiert wurde. Wer souveräne Open-Source-Infrastruktur im eigenen Rechenzentrum betreibt, hat hier den Vorteil, dass er diese Stellschrauben selbst kontrolliert — anders als bei proprietären Storage-Appliances oder Cloud-Storage-Diensten, bei denen diese Ebene unsichtbar bleibt.
Ausblick 2026: Was sich in Ceph ändert — und was bleibt
Ceph Tentacle (20.2.x) — das aktuelle Stable-Release
Mit Ceph Tentacle, dem aktuellen Stable-Release seit November 2025, hat sich auf der Storage-Engine-Ebene einiges getan. BlueStore hat ein schnelleres Write-Ahead-Log (WAL) bekommen, und die OMAP-Iteration wurde beschleunigt — das verbessert vor allem RGW-Bucket-Listings und Scrub-Operationen. Außerdem wurde der hybrid_btree2-Allocator aus Squid zurückportiert, der bei fragmentiertem Speicher deutlich bessere Allokationszeiten liefert als der ältere Hybrid-Allocator.
Für die hier beschriebenen Kernel-Tunings ändert sich durch Tentacle nichts: BlueStore nutzt nach wie vor den Linux-Kernel für I/O, Memory-Management und CPU-Scheduling. Die Empfehlungen zu Swappiness, THP, CPU-Governor, C-States und I/O-Scheduler gelten unverändert.
Crimson und SeaStore — der OSD-Neustart
Das spannendste Projekt für die Ceph-Performance der nächsten Jahre ist Crimson — ein von Grund auf neu geschriebener OSD-Daemon, der den klassischen ceph-osd langfristig ablösen soll. Crimson basiert auf dem Seastar-Framework und verfolgt eine konsequente Shared-Nothing-Architektur: Jeder CPU-Core arbeitet in seinem eigenen Reactor, ohne Locks und mit minimalem Cross-Core-Traffic.
Mit Tentacle liegt die erste technisch nutzbare Tech Preview vor: Crimson-OSD mit SeaStore (dem neuen, nativen Object Store für NVMe) kann jetzt über cephadm deployed werden. Die aktuellen Benchmarks vom Ceph-Blog zeigen, dass SeaStore bei 4K Random Reads bereits den klassischen OSD deutlich übertrifft — mit bis zu 400K IOPS gegenüber 130K IOPS auf derselben Hardware. Bei sequentiellen Workloads liegen beide auf vergleichbarem Niveau. Random Writes sind noch ein aktives Optimierungsfeld.
Was bedeutet das für Linux-Kernel-Tuning? Crimson mit SeaStore wird perspektivisch weniger vom Kernel abhängen: SeaStore kann direkt über SPDK auf NVMe-Drives zugreifen (Kernel-Bypass), und die Seastar-Architektur vermeidet viele der Thread-Synchronisationsprobleme, die den klassischen OSD bei THP-Compaction und C-State-Übergängen ausbremsen. Allerdings ist Crimson noch nicht produktionsreif — das Ceph-Projekt selbst empfiehlt ausdrücklich nur Testing und Experimentation. Bis Crimson GA wird, rechnet die Community mit einem ähnlichen Zeitrahmen wie bei BlueStore: mehrere Jahre von der Tech Preview bis zur Produktionsreife.
Was das für 2026 heißt
Für alle, die heute Ceph in Produktion betreiben — und das betrifft die überwiegende Mehrheit der Installationen auf Squid oder Tentacle mit dem klassischen OSD und BlueStore — bleiben die in diesem Artikel beschriebenen Kernel-Tunings der effektivste Hebel für konsistente, niedrige Latenzen. Die Optimierungen kosten nichts außer etwas Strom und sind in wenigen Minuten auf jedem Node umgesetzt.
Parallel lohnt es sich, die Crimson-Entwicklung im Auge zu behalten. Wer einen neuen Cluster plant und NVMe-only fährt, kann Crimson bereits in einer Testumgebung evaluieren — mit dem Wissen, dass die Architektur langfristig viele der hier beschriebenen Kernel-Limitierungen obsolet machen wird. Die nächste Ceph-Release nach Tentacle (Codename: Umbrella) wird zeigen, wie weit Crimson bis dahin gekommen ist.
Haben Sie Fragen zu diesem Thema?
Unsere Experten beraten Sie gerne zu Ihrer individuellen Strategie.
Beratungsgespräch vereinbaren