Wenn es um cgroups geht, stellen Red Hat-Benutzer häufig die gleiche Frage: „Ich habe eine Anwendung, die hinsichtlich Verzögerungen sehr empfindlich ist. Ist es möglich, cgroups zu verwenden, um diese Anwendung vom Rest zu isolieren, indem sie an bestimmte Prozessorkerne gebunden wird? “

Natürlich kannst du. Andernfalls würden wir dieses Problem nicht als Thema des heutigen Artikels auswählen.
In der Kindheit wurde uns oft gesagt, dass Teilen gut und richtig ist. Im Großen und Ganzen so wie es ist. Es gibt jedoch Ausnahmen.
Wie wir im
ersten Beitrag dieser Serie geschrieben haben , verhält sich Red Hat Enterprise Linux 7 standardmäßig wie eine sphärische Großmutter. In dem Sinne, dass sie versucht, die Systemressourcen fair auf alle zu verteilen, die sie fragen. Im wirklichen Leben haben Großmütter jedoch Haustiere, die mehr bekommen. In sysadmin übersetzt bedeutet dies, dass es Situationen gibt, in denen einige Anwendungen oder Dienste wichtiger sind als andere. Daher sollten sie alle mögliche Aufmerksamkeit erhalten, damit sie so reaktionsschnell wie möglich sind.
Red Hat Enterprise Linux 7 führt dies in zwei Schritten aus:
- Wir isolieren einen Teil der Prozessorkerne, um sie auf die ausschließliche Verwendung einer solchen Anwendung zu übertragen.
- Wir erstellen Gruppengruppen und Einheitendateien, die diese Anwendung an isolierte Kernel binden.
Ein kleiner Exkurs zu den Beispielen aus diesen Beiträgen
Hat Enterprise Linux 7.4 hat die Funktionsweise kurzlebiger Slices geändert, z. B. Benutzersitzungen. Infolgedessen können sie die cgroup-Einstellungen nicht mehr im laufenden Betrieb ändern, dauerhafte Änderungen an der Konfiguration vornehmen oder Drop-In-Dateien mit dem Befehl systemctl set-property erstellen. Ja, es ist eine Schande, aber die Linux-Entwicklergemeinde hat dies entschieden. Die gute Nachricht ist, dass diese Änderungen den Service nicht beeinflusst haben. Das heißt, wenn Anwendungen über Einheitendateien gestartet und gestoppt werden (als Dämonen arbeiten), funktionieren alle unsere Beispiele. Darüber hinaus ist es weiterhin möglich, eigene alte Gruppen mit alten Tools wie cgcreate und cgset zu erstellen und dann Benutzersitzungen und -prozesse in diese Gruppen zu platzieren, um CPU-Bälle und andere Steuerelemente zu verwenden. Im Leben ändert sich alles, so dass wir nur neue Techniken anpassen und erfinden können. Und jetzt wenden wir uns dem heutigen Thema zu.
Separatismus mit Isolcpus aufbauen
Eine der wichtigsten Komponenten im Linux-Kernel ist der Prozessplaner. Wenn etwas tiefer, dann ist ein Prozess ein ausführbarer Code, der Teil einer Anwendung oder eines Dienstes ist. Tatsächlich besteht der Prozess aus einer Reihe von Anweisungen, die der Computer ausführt, um diese oder jene Arbeit auszuführen, unabhängig davon, ob Sie sich Dichtungen oder etwas Ernsthafteres ansehen.
Diese Anweisungen werden vom Zentralprozessor, auch bekannt als CPU, verarbeitet. Auf modernen Computern besteht die CPU normalerweise aus mehreren Prozessoren, die als Kerne bezeichnet werden.
Standardmäßig betrachtet der Scheduler jeden Prozessorkern als eines der ausführenden Module, denen er neue Prozesse zuweist, sobald sie angezeigt werden. In diesem Fall versucht der Scheduler, die entstehenden Prozesse unter Berücksichtigung der Last mehr oder weniger gleichmäßig auf die Kerne zu verteilen. Leider kann dem Scheduler nicht gesagt werden, dass dieser bestimmte Prozess letztendlich zu einer ganzen Gruppe von Prozessen führen wird, und diese Gruppe muss isoliert von anderen Prozessen ausgeführt werden, in dem Sinne, dass sie keine gemeinsamen Prozessorkerne haben sollten.
Daher müssen wir dem Planer irgendwie mitteilen, dass er einen Teil der Prozessorkerne nicht berührt, dh ihnen keine Prozesse gibt, die getroffen werden. Und dann werden wir selbst (oder mit Hilfe eines anderen Prozesses) die Prozesse erzwingen, die wir für notwendig halten, um vom Kernel-Scheduler isoliert zu sein. Dies kann mit dem Parameter isolcpus in der Kernel-Boot-Zeile in der Grub-Konfigurationsdatei erfolgen. Im folgenden Beispiel haben wir einen Computer mit vier Kerneln, auf dem sich zwei Grub-Dateien befinden: einer befindet sich in / etc / default und heißt grub.noiso (dies ist die Standardkonfigurationssicherung), und der zweite liegt dort und wird einfach grub genannt, damit es nahm grub2-mkconfig auf. Diese zweite Datei wurde bearbeitet, um die Kernel 1-3 vom Prozessplaner zu isolieren.

WARNUNG: Unter Red Hat Enterprise Linux 7 müssen Sie die Datei grub.conf im Ordner / boot niemals manuell ändern. Nehmen Sie stattdessen die erforderlichen Änderungen an / etc / default / grub vor und erstellen Sie die Datei grub.conf mit dem entsprechenden Dienstprogramm wie folgt neu:
Bei Verwendung des Parameters isolcpus müssen die freigegebenen Prozessorkerne durch Komma getrennt aufgelistet werden. Die Nummerierung beginnt bei 0. Nach dem Neustart des Systems verwendet der Prozessplaner diese Kerne nur für bestimmte Prozesse auf Systemebene, die auf jedem Kern vorhanden sein MÜSSEN. Um zu überprüfen, ob unsere Methode funktioniert hat, starten wir mehrere Ladevorgänge und untersuchen dann das Laden jedes Kernels mit dem Befehl top.
Wie Sie sehen können, befanden sich alle Ladevorgänge auf CPU 0, anstatt gleichmäßig auf alle vier Kerne verteilt zu sein. Also haben wir den Boot-Parameter korrekt registriert.
Binden Sie Prozesse mit cpuset an Kernel
Jetzt gehen wir zu Dingen über
, die Sie besser nicht tun sollten, wenn Sie nicht verstehen, warum Sie dies tun, und die besser erst nach gründlichen Tests in der Produktion bereitgestellt werden können .
Wofür sind diese Warnungen? Zu der Tatsache, dass wir im Allgemeinen einfache Dinge mit dem libcgroup-Toolkit tun werden, über das in einem früheren Beitrag geschrieben wurde. Wenn Sie sich erinnern, ist dies nur eine Reihe von Befehlen zum Erstellen, Ändern und Zerstören von Gruppen. Tatsächlich sind sie Teil von Red Hat Enterprise Linux 6, können aber auch unter Red Hat Enterprise Linux 7 installiert werden, obwohl es möglich ist, dass diese Möglichkeit in Zukunft verschwindet. Erinnern Sie sich kurz an die wichtigsten Empfehlungen für die Verwendung von libcgroup:
- Verwenden Sie systemd, um die cgroup-Controller zu steuern, die von systemd selbst gesteuert werden (dies sind die CPU, der Speicher und die Block-E / A.).
- Verwenden Sie libcgroup-Tools, um alle anderen cgroup-Controller zu verwalten.
- Seien Sie sehr vorsichtig mit den ungeplanten Folgen Ihrer Handlungen.
Mit dem cpuset-Konzept ist alles einfach - dies ist eine Liste von Prozessorkernen (Nummerierung, Rückruf, Beginn bei 0), die Aufgaben akzeptiert, die NUR auf diesen Kernen ausgeführt werden. Dies sind die am häufigsten verwendeten Prozessorkerne. Sie können entweder von einem Prozessplaner gesteuert werden (so wird das System standardmäßig konfiguriert) oder umgekehrt vom Planer isoliert werden (wie im obigen Beispiel).
Lassen Sie uns anhand unseres Beispiels das Dateisystem Verzeichnis / sys / fs / cgroup auf dem System überprüfen. Wie Sie sehen können, ist das Verzeichnis cpuset bereits vorhanden, da dieser Controller Teil des Kernels ist (obwohl er nicht unter der Kontrolle von systemd steht). Es gibt jedoch noch keine cgroups, sodass nur die Standardeinstellungen in diesem Verzeichnis angezeigt werden.
Überprüfen Sie, ob das libcgroup-Toolkit auf unserem Computer installiert ist:
Wenn nicht installiert, kann dies einfach mit dem Befehl yum install libcgroup behoben werden, selbst ein Neustart ist nicht erforderlich.
Erstellen Sie nun cpuset. Zu diesem Zweck verwenden wir die folgenden Befehle, um eine neue cgroup für cpuset zu erstellen und deren Eigenschaften zu registrieren:
Der Befehl Cgcreate erstellt eine cgroup namens testset und platziert sie im cpuset-Controller. Dann weisen wir diesem neuen cpuset den dritten Kern unserer VM zu und weisen ihm die NUMA-Zone 0 zu. Auch wenn Ihr System NUMA nicht verwendet (und unser System es einfach nicht verwendet), müssen Sie die Zone trotzdem registrieren, andernfalls können Sie der cgroup-Gruppe keine Aufgaben zuweisen . Überprüfen Sie nun, ob das Testset-Verzeichnis im Dateisystem erstellt wurde, und prüfen Sie, was sich darin befindet.
Wie Sie sehen können, sind unsere Änderungen vorhanden, aber bisher wurde auf diesem cpuset kein Prozess ausgeführt. Wie pflanzt man hier einen Prozess?
Es gibt verschiedene Möglichkeiten, dies zu tun:
- Sie können die PID eines vorhandenen Prozesses in die Aufgabendatei eingeben. Es funktioniert, aber nicht sehr hübsch.
- Sie können cgexec verwenden und die Gruppe angeben, wenn der Prozess startet. Dies funktioniert, wenn die Anwendung kein Daemon ist. Darüber hinaus kann all dies wunderschön im Anwendungsstart-Skript geschrieben werden.
- Für eine Anwendung, die als Daemon ausgeführt wird, auf dem systemd ausgeführt wird, können Sie eine Servicedatei erstellen.
Sehen wir uns die Option cgexec an.
Wir haben foo.exe gestartet, es hat wiederum einen untergeordneten Prozess gestartet, der nur den Prozessor aktiv lädt. Die Option --sticky im Befehl cgexec besagt, dass "jeder untergeordnete Prozess in derselben cgroup wie der übergeordnete Prozess bleiben muss". Dies ist also eine wichtige Option, an die man sich erinnern muss. Jetzt sehen wir, dass sich in unserer Gruppe zwei Prozesse drehen, und wir kennen ihre PIDs. Schauen Sie sich oben an:
Wie Sie sehen können, ist die CPU 3 jetzt in die Augäpfel geladen, und der Rest kühlt ab.
Und so sieht eine Einheitendatei aus, um dieselbe Anwendung wie ein systemd-Dienst auszuführen:
Die Unit-Datei enthält drei ExecStartPre-Befehle, die die Einstellungen ausführen, die wir bereits mit unseren Händen vorgenommen haben. Dann kommt der ExecStart-Befehl, der die Anwendung startet. Wenn die Anwendung beendet wird, wird der Befehl ExecStopPost nach sich selbst bereinigt und cgroup entfernt.
Wie Sie sehen können, haben wir im letzten Beispiel eine neue cgroup mit dem Namen set1 erstellt. Wir haben dies getan, um zu zeigen, dass Sie mehrere aktive Gruppen haben können, die dieselbe CPU verwenden. Wem es nützlich erscheinen mag, aber im Gegenteil, jemanden zu verwirren.
Nun, funktioniert es? Es scheint so!
Und jetzt werden wir die Arbeit unseres Dienstes abschließen und überprüfen, ob cgroup zerstört ist:
ACHTUNG: Mit cgcreate erstellte Gruppengruppen werden nach dem Neustart nicht gespeichert. Daher muss die Erstellung solcher Gruppen in Startskripten und Einheitendateien vorgeschrieben werden.
In Ihrem Arsenal gibt es jetzt noch ein paar weitere Tools für die Arbeit mit Gruppen. Wir hoffen, dass sie nützlich sind!
Weitere Beiträge von cgroups aus unserer Resource Fight-Reihe finden Sie unter: