Linux Control Groups, kurz Cgroups, sind ein mächtiges Werkzeug, um Prozesse innerhalb eines Linux-Systems präzise zu verwalten und deren Ressourcenverbrauch zu steuern. Diese Technologie ermöglicht die Einschränkung und Überwachung der verwendeten CPU-Zeit, des Speichers, der Netzwerkbandbreite und anderer wichtiger Systemressourcen. Die Einführung von Cgroups Version 2 im Linux-Kernel 4.5 hat das Konzept deutlich vereinfacht und die Handhabung grundlegend verbessert. Für alle, die sich tiefgründig mit den Mechanismen hinter Cgroups auseinandersetzen wollen, bietet sich hier ein verständlicher Einstieg.
Grundlegend beruhen Cgroups auf der Unix-Philosophie, dass „alles eine Datei ist“. Dies erleichtert die Interaktion mit dem Kernel über einfache Dateioperationen. Das bedeutet, dass durch Lesen und Schreiben in Systemdateien die Kontrolle über Systemressourcen erfolgen kann. Der zentrale Ort für Cgroups im Dateisystem ist das Verzeichnis /sys/fs/cgroup, das als Root-Cgroup bezeichnet wird. Innerhalb dieses Verzeichnisses können hierarchische Gruppen erstellt werden, die jeweils separate Ressourcenbeschränkungen erhalten können.
Jede Cgroup besteht aus einer oder mehreren Untergruppen, die spezialisierte Steuerungsdateien enthalten, um verschiedene Ressourcen zu managen. So können zum Beispiel individuelle Speicherlimits über die Datei memory.max gesetzt werden, welche die maximale Speicherzuweisung für alle Prozesse in dieser Gruppe bestimmt. Neben den Beschränkungsdateien existieren sogenannte Event- und Statusdateien, welche Echtzeitinformationen über den Ressourcenverbrauch liefern und Ereignisse wie Speicherüberschreitungen melden. Ein praktisches Beispiel: Angenommen, man möchte ein Programm daran hindern, mehr als 5 Megabyte Arbeitsspeicher zu verwenden.
Zuerst wird dazu eine Cgroup mit einem passenden Namen erstellt, beispielsweise /sys/fs/cgroup/demo/memory-limited. Anschließend aktiviert man den Speicher-Controller für diese Gruppe, indem man in der übergeordneten Gruppe die Datei cgroup.subtree_control mit dem Steuerungsnamen memory beschreibt. Danach schreibt man den Grenzwert, also 5242880 Bytes, in memory.max.
Werden nun Prozesse in dieser Gruppe gestartet oder durch Transfer in die Cgroup verschoben, können sie den gesetzten Speicherverbrauch nicht überschreiten. Eine wichtige Eigenschaft von Cgroups ist die sogenannte „no internal process“-Regel. Das bedeutet, eine Cgroup darf entweder direkt Prozesse beinhalten oder Untergruppen besitzen, aber nicht beides gleichzeitig – Ausnahme ist die Root-Cgroup. Dies sorgt für eine klare und konsistente Hierarchie, die die Verwaltung und das Ressourcen-Accounting vereinfacht. Um einen Prozess einer bestimmten Cgroup zuzuordnen, schreibt man dessen PID in die Datei cgroup.
procs der entsprechenden Gruppe. Neben Speicher kann die CPU-Nutzung präzise eingeschränkt werden. Im Rahmen des CPU-Controllers lassen sich sogenannte Quotas definieren, die festlegen, wie lange Prozesse in einem Beispielzeitraum die CPU beanspruchen dürfen. Dies wird über die Datei cpu.max umgesetzt, in der zwei Werte hinterlegt werden: die erlaubte Ausführungszeit in Mikrosekunden und die Länge des Beobachtungszeitraums.
Dadurch können sehr feine Einstellungen getroffen werden, etwa um nur 10 Prozent CPU-Zeit innerhalb eines bestimmten Intervalls zu erlauben. Für Entwickler und Systembetreiber ist das ideal, um ressourcenintensive Prozesse zu drosseln und eine faire Verteilung der CPU-Ressourcen sicherzustellen. Der Zugriff auf die Cgroup-Dateien erfolgt per root oder mit ausreichenden Rechten. Manchmal ist es notwendig, die Besitzverhältnisse der Verzeichnisse anzupassen, damit auch Nicht-Root-Anwender Prozesse in Cgroups managen können. Dennoch erfordert das Verschieben von Prozessen in Cgroups insbesondere dann root-Rechte, wenn gemeinsame Vorfahren keine passenden Schreibberechtigungen bieten.
Diese Sicherheitsschranken schützen das System vor unerwünschten Eingriffen. Die praktische Handhabung von Cgroups kann durch Werkzeuge wie cgexec erleichtert werden. Dieses Kommando startet Prozesse direkt innerhalb einer definierten Cgroup, ohne dass der Anwender selbst tief in die Verwaltung der cgroup.procs eingreifen muss. Dies ist besonders hilfreich bei Tests und beim experimentellen Arbeiten mit Ressourcenbeschränkungen.
Das Konzept der Control Groups eröffnet vielseitige Einsatzmöglichkeiten: sei es zur Isolation von Programmen in Containersystemen, zur Kontrolle der Ressourcenverteilung in Multi-User-Umgebungen oder zum Testen von Anwendungen unter limitierten Bedingungen. Insbesondere in der Cloud- und Containerwelt bilden Cgroups die technische Basis vieler Orchestrierungstools. Darüber hinaus ist die Cgroup-Technologie nicht nur eine einfache Begrenzung der Ressourcen, sondern auch ein Instrument zur Beobachtung und Fehleranalyse. Monitoring-Tools können die zahlreichen Statusdateien auswerten und so detaillierte Einblicke in die Leistung und Auslastung einzelner Prozessgruppen geben. Damit erfolgt eine granularere Steuerung und ein besseres Verständnis komplexer Systeme.
Wer sich tief in das Thema einarbeiten möchte, profitiert von ausführlicher Dokumentation und Beispielen. So bietet Facebooks Microsite zu Cgroup2 wertvolle Erklärungen und Anwendungsfälle. Auch das eigenständige Experimentieren mit den direkt im System verfügbaren Dateien erweitert das Verständnis und hilft, die oft als komplex wahrgenommene Thematik zu entmystifizieren. Dennoch stößt man gelegentlich auf Herausforderungen. So sind etwa Fehlermeldungen bei Verstößen gegen die Cgroup-Regeln oft wenig aussagekräftig.