Als in einer Flotte von Ceph‑Storage‑Servern PID 1 plötzlich einen Großteil des Arbeitsspeichers beanspruchte, führte die Spur über mehrere Systemschichten. Was zunächst wie ein klassischer Speicherleck‑Fall aussah, entpuppte sich als komplexes Zusammenspiel einer fehlerhaften Orchestrierung, eines Kernel‑Race‑Bugs und der Art, wie glibc Speicher behält. Canonical Support analysierte das Problem bis zur Root‑Ursache, lieferte einen minimalen Reproducer und trug so zu einer upstream Kernel‑Korrektur bei.
Das auffällige Symptom
In mehreren Knoten einer Ceph‑Umgebung zeigte /sbin/init — ein Symlink auf systemd, also PID 1 — einen unerwartet hohen Speicherverbrauch. Auf Maschinen mit 125 GiB RAM nahm PID 1 etwa 70 GiB ein; erwartet waren nur rund 8 GiB. Die Systeme litten unter OOM‑Kills, weil der Kernel Prozesse beendete, um Speicher freizugeben.
Erste Analyse: sos‑report reichte nicht
Die Support‑Ingenieure begannen mit den üblichen Diagnosen, einschließlich sos‑reports. Diese umfassenden Systemberichte lieferten zwar Hinweise auf den Zustand der Maschinen, erklärten aber nicht, warum PID 1 plötzlich so viel Speicher reservierte. Um detailliert zu sehen, was sich im Adressraum von PID 1 befand, forderte das Team einen Core‑Dump der Init‑Prozess‑Speicherabbildung an (gcore 1).
Ein Core‑Dump von PID 1 ist ein riskantes und ressourcenintensives Artefakt auf Produktionssystemen, denn PID 1 ist zentral für die Nutzerebene. Im vorliegenden Fall komprimierte sich der Dump von rund 70 GiB auf unter 10 GiB, was darauf hindeutete, dass sich große, sich wiederholende Datenmengen im Speicher befanden.
Was der Core‑Dump offenbarte
Die Analyse der Speicherabbilddatei zeigte, dass die große Belegung mit Mount‑Tabelleneinträgen zusammenhing. Konkret stammten viele Einträge von wiederholten Ausführungen eines ceph‑volume Docker‑Containers. systemd überwacht /proc/self/mountinfo und parsed die Liste bei jeder Änderung erneut. Bei normaler Größe der Mount‑Tabelle ist das unkritisch; wuchs die Tabelle jedoch auf Millionen von Einträgen an, wurde das ständige Neupopulieren teuer.
Warum Speicher nicht zurückkam: das Zusammenspiel mit glibc
Beim wiederholten Einlesen der stark angewachsenen Mountliste reservierte glibc Speicher über den Allocator und gab ihn nicht unmittelbar an das System zurück. Das führte dazu, dass systemd zwar seine internen Strukturen freigab, die vom Allocator gehaltenen Speicherblöcke aber vom Rest des Systems nicht mehr benutzt werden konnten. Effektiv erschien das System „ausgelastet“, auch wenn der Speicher technisch nicht verloren war.
Die eigentliche Ursache: cephadm zappte eine nicht existierende OSD
Die Suche nach dem Auslöser für die andauernden mount‑Operationen führte tiefer in die Ceph‑Orchestrierung. Ein cephadm‑Prozess versuchte wiederholt, eine OSD zu „zappen“ — eine Aktion, die ein Laufwerk vollständig löscht und zurücksetzt. Allerdings gab es für die betreffenden Geräte kein zugeordnetes Logical Volume mehr; die Aktion schlug still fehl und wurde wiederholt.
Jeder fehlgeschlagene Versuch erzeugte einen ceph‑volume‑Container, der an‑ und abgeschaltet wurde. Dieses ständige Mount/Unmount‑Thrashing vergrößerte die Mount‑Tabelle immer weiter und erzeugte so die Bedingungen, unter denen systemd und der Allocator ineffizient zusammenwirkten.
Workaround und Stabilisierung
Als erste Maßnahme stoppte die Behebung der fehlerhaften Orchestrierung (das Unterbinden der wiederholten Zap‑Versuche) die Wiederholungen. Mit dem Ende des Thrashings stabilisierte sich die Mount‑Tabelle, die ständigen Reparses hörten auf, und der Speicherverbrauch kehrte auf normale Werte zurück. Die Sofortmaßnahme beseitigte das akute Problem und erlaubte den Support‑Ingenieuren, an einer dauerhaften Lösung zu arbeiten.
Vom Produktionsfall zum reproduzierbaren Testfall
Um den Fehler verlässlich zu beschreiben und upstream‑fähig zu machen, reduzierte das Team den Vorfall auf einen minimalen Reproducer: das schnelle Mounten und Unmounten eines tmpfs in einer Schleife. Mit dieser Reduktion liess sich das Verhalten zuverlässig nachstellen und das eigentliche Problem eingrenzen: ein Race‑Zustand im Kernel, der dazu führen konnte, dass die Mount‑Tabelle temporär auf Millionen Einträge anwuchs.
Upstream‑Fix und Ausrollen
Mit einem klar dokumentierten Trigger und einem verifizierten Reproducer konnte Canonical den Bug bei Kernel‑Maintainers platzieren. Die Korrektur wurde in den mainline Kernel aufgenommen. Nach dem Stable Release Update‑Prozess (SRU) fand der Fix seinen Weg in mehrere Ubuntu‑Kernel‑Releases, sodass die breite Nutzerbasis von der Korrektur profitierte.
Wesentliche Erkenntnisse für Betreiber
- Großer Speicherverbrauch von PID 1 kann ein Indikator für ein vielschichtiges Problem sein, das mehrere Ebenen (Orchestrierung, Kernel, Laufzeitbibliotheken) umfasst.
- Sorgfältiges Sammeln von Artefakten ist entscheidend: sos‑reports liefern Kontext, ein Core‑Dump von PID 1 kann aber den entscheidenden Einblick in den Adressraum geben — mit erheblichem Aufwand und Risiko.
- Ein reproduzierbarer Minimalkörper erleichtert die Kommunikation mit Upstream‑Projekten und beschleunigt Bugfixes.
- Kurzfristige Workarounds (z. B. das Stoppen einer fehlerhaften Orchestrierungsaktivität) können eine akute Entlastung bringen, sollten aber durch langfristige, upstream‑geprüfte Korrekturen ergänzt werden.
Fazit
Der Vorfall zeigt exemplarisch, wie ein vermeintliches Speicherleck sich aus dem Zusammenwirken mehrerer Komponenten ergeben kann. Nur durch schichtübergreifende Analyse — von der Orchestrierung über den Kernel bis zur Laufzeitbibliothek — entstand ein vollständiges Bild. Die Kombination aus präziser Diagnose, Reproducer und enger Zusammenarbeit mit der Kernel‑Community führte zu einer dauerhaften Behebung, die allen betroffenen Systemen zugutekommt.