Lange Neustarts von Stateful-Services erscheinen selten als ein Problem der Sicherheitskonfiguration. Doch genau so verwandelte sich das sichere Default in Kubernetes in 30 Minuten Ausfallzeit pro Neustart.
Das Problem trat im großen Maßstab auf. Atlantis, das Terraform über GitLab MR verwaltet, funktioniert als Singleton StatefulSet und speichert den Zustand in einem PersistentVolume. Jeder Neustart – sei es zur Aktualisierung von Anmeldeinformationen oder zur Einarbeitung – blockiert alle Plan-/Anwendungsoperationen. Bei ~100 Neustarts pro Monat führte dies zu über 50 Stunden Ausfallzeit. Das Symptom sah seltsam aus: Der Pod wurde schnell erstellt, hing jedoch bis zum Start des Init-Containers. Kubernetes-Events gaben keine Erklärung. Die Degradierung wurde erst nach dem Wachstum des PV auf Millionen von Dateien und dem Erschöpfen der Inodes bemerkbar.
Die Analyse zeigte, dass der Engpass nicht im Netzwerk und nicht im Pull von Images lag. Kubelet montierte das PV schnell, aber dann fand eine versteckte Operation statt: eine rekursive Änderung der Zugriffsrechte (chgrp -R) im gesamten Dateibaum. Dies ist eine Folge der Einstellung des securityContext mit fsGroup. Kubernetes garantiert standardmäßig (fsGroupChangePolicy: Always) den Zugriff, indem es den Besitz jeder Datei bei jedem Mountvorgang ändert. Bei großen Volumes verwandelt sich dies in eine O(n)-Operation in Bezug auf die Anzahl der Dateien. Ohne diese Einstellung könnte Atlantis nicht als Non-Root arbeiten, daher kann man nicht vollständig auf fsGroup verzichten – es ist ein Kompromiss zwischen Sicherheit und Startzeit.
Die Lösung stellte sich als punktuell heraus. In Kubernetes gibt es eine Alternative – fsGroupChangePolicy: OnRootMismatch. In diesem Modus überprüft kubelet nur das Wurzelverzeichnis des Volumes und führt kein rekursives chgrp aus, wenn die Berechtigungen bereits korrekt sind. Vor der Änderung überprüften wir, dass die Prozesse den Gruppenbesitz innerhalb des PV nicht ändern. Das ist wichtig: Bei inkonsistenten Berechtigungen können zur Laufzeit Zugriffsfehler auftreten. Danach fügten wir eine Zeile in spec.securityContext hinzu.
Das Ergebnis – die Reduzierung der Neustartzeit von ~30 Minuten auf ~30 Sekunden. Die CPU- oder I/O-Metriken änderten sich nicht – die Beschleunigung war ausschließlich auf die Beseitigung überflüssiger Dateioperationen zurückzuführen. Insgesamt brachte dies etwa 50 Stunden Ingenieurzeit pro Monat zurück.
Dieser Fall zeigt ein typisches Muster: Sichere Defaults von Kubernetes funktionieren gut bei kleinen Volumina, aber im großen Maßstab werden ihre linearen Operationen bemerkbar. Wenn Sie große PersistentVolumes und lange Neustarts haben, sollten Sie überprüfen:
- Wird fsGroup verwendet?
- Welchen Wert hat fsGroupChangePolicy?
- Gibt es rekursive Operationen beim Mount?
Wenn keine Daten über das Verhalten des Dateisystems vorliegen, erfordert der Wechsel zu OnRootMismatch Vorsicht. Aber bei einem kontrollierten Schreibmodell ist dies eine pragmatische Verbesserung, die die versteckte O(n)-Kosten aus dem kritischen Startpfad entfernt.