Letzten Monat habe ich auf der ApacheCon gesprochen über Cgroups. Es scheint, dass nur sehr wenige Linux-Benutzer (einschließlich meiner Wenigkeit bis vor nicht allzu langer Zeit) mit Cgroups und ihrer Leistungsfähigkeit vertraut sind. Das ist schade, denn Cgroups sind sehr leistungsstark und ermöglichen es Ihnen, Ressourcen auf Ihren Servern weitaus feingranularer zuzuweisen als mit jedem anderen im Linux-Toolkit verfügbaren Tool. Darüber hinaus ist es direkt in den Kernel integriert und wird bei den meisten Linux-Distributionen standardmäßig mitgeliefert.
In diesem Artikel werde ich beschreiben, wie man Cgroups mit Docker verwendet, quasi als Fortsetzung eines anderen Vortrags, den ich beim Docker Meetup in Austin, Texas, gehalten habe.
Dieser Artikel erfordert ein gewisses grundlegendes Verständnis von Cgroups. Wenn Sie völlig neu bei Cgroups sind, empfehle ich Ihnen, sich meine Präsentationsfolien von der ApacheCon sowie die Ressourcen am Ende anzusehen. Keine Sorge, wir werden nicht zu tief eintauchen. Wenn Sie die Folien nur überfliegen, sollten Sie die grundlegenden Konzepte verstehen können.
Docker und Cgroups
Docker wird mit zwei verschiedenen Treibern ausgeliefert: LXC und libcontainer. Der LXC-Treiber ist der veraltete Treiber, und libcontainer ist der neue Standardtreiber. In den meisten Fällen ist libcontainer der bevorzugte Treiber, da dort die Innovationen stattfinden (zum Beispiel funktioniert docker exec nicht mit dem LXC-Treiber).
Es ist jedoch wichtig zu beachten, dass es zwei verschiedene Treiber gibt, da noch nicht alle Cgroup-Funktionen auf libcontainer portiert (oder zumindest für Docker freigegeben) wurden. Wenn Sie den LXC-Treiber verwenden, übergeben Sie die LXC-Argumente einfach direkt, während bei libcontainer explizite Cgroup-Richtlinienargumente für Docker bereitgestellt werden. Sie müssen beim Starten des Docker-Daemons explizit einen Treiber festlegen, sodass Sie die beiden Treiber nicht gleichzeitig ausführen können.
Hier ist ein Beispiel, wie Sie das überprüfen können:
[bash light=”true”] # Mit dem LXC-Treiber$ docker run -d –name=’lxc_test’ \
–lxc-conf="lxc.cgroup.cpu.shares=50" \
busybox
# Mit dem libcontainer-Treiber
$ docker run -d –name=’libcontainer_test’ \
–cpu-shares=50 \
busybox
[/bash]
Hier ist eine Übersicht über einige der Cgroup-Funktionen und wie sie sich zwischen den beiden Treibern verhalten:
| Funktion | Libcontainer | LXC |
|---|---|---|
| Relativer CPU-Anteil | -c, –cpu-shares | –lxc-conf=”lxc.cgroup.cpu.shares” |
| An einen CPU-Kern binden | –cpuset-cpus | –lxc-conf=”lxc.cgroup.cpuset.cpus” |
| Arbeitsspeicher begrenzen | -m, –memory | –lxc-conf=”lxc.cgroup.cpuset.mems” |
LXC
Wenn Sie den LXC-Treiber für Docker verwenden möchten, müssen Sie ihn zuerst aktivieren. Die Methode hierfür unterscheidet sich je nach Linux-Distribution, aber hier sind die Anweisungen, wie Sie den LXC-Treiber unter Ubuntu 14.04 aktivieren.
Wie oben erwähnt, verzichten Sie dabei auf eine Reihe von Funktionen. Sofern Sie also nicht wirklich eine Funktionalität benötigen, die in Docker mit libcontainer noch nicht freigegeben ist, sollten Sie unbedingt beim Standardtreiber bleiben.
Einige nützliche Cgroup-Richtlinien, die in libcontainer noch nicht freigegeben sind, umfassen die E/A-Drosselung (im Präsentationsdeck behandelt), was für bestimmte Anwendungen sehr praktisch sein kann.
Wenn Sie sich für die Verwendung des LXC-Treibers entschieden haben, ist das Hinzufügen von Argumenten unkompliziert. Sie müssen lediglich das Argument --lxc-conf hinzufügen und die Cgroup-Richtlinie übergeben, die Sie festlegen möchten.
Libcontainer
Wie Sie in der Tabelle oben sehen können, sind die grundlegenden Cgroup-Richtlinien in der aktuellen Version von Docker (1.6 zum Zeitpunkt des Schreibens) bereits freigegeben.
Die Verwendung dieser Richtlinien ist sehr einfach. Wenn Sie beispielsweise einen Docker-Container auf den ersten CPU-Kern beschränken möchten, hängen Sie --cpuset-cpus=0 an Ihren docker run-Befehl an.
Sie können auch das Argument --cgroup-parent mit libcontainer verwenden und manuell feingranularere Ressourcenbeschränkungen festlegen. Sie würden es dann mithilfe dieses Arguments dieser Gruppe zuordnen.
Demo: Docker mit Cgroups
Im folgenden Screencast verwenden wir zwei Docker-Container (‘low_prio’ und ‘high_prio’). Wir verwenden den ‘busybox’-Basis-Container und führen md5sum /dev/urandom aus, um einen CPU-intensiven Prozess zu simulieren. Standardmäßig würde dies alle verfügbaren CPU-Ressourcen verbrauchen. Wir werden jedoch zwei Cgroup-Richtlinien anwenden, um die Ressourcen zu verwalten. Zuerst verwenden wir ‘cpuset.cpus’, um die Container auf denselben CPU-Kern (Kern 0) zu beschränken.
Als Nächstes verwenden wir ‘cpu.shares’, um einen relativen CPU-Anteil zuzuweisen. Wir geben dem ‘low_prio’-Container den Wert 20 und ‘high_prio’ den Wert 80. Das bedeutet, dass dem ‘low_prio’-Container 20 % der CPU und dem ‘high_prio’-Container 80 % der CPU zugewiesen werden. Bitte beachten Sie jedoch, dass der relative Anteil eine willkürliche Skala ist (wir hätten ebenso gut die Werte 2 und 8 verwenden können).
Nachdem wir gezeigt haben, dass die Ressourcenverwaltung tatsächlich funktioniert, starten wir dieselben Container ohne Cgroup-Richtlinien, um zu sehen, wie sie sich verhalten.
Als Referenz sind hier die Befehle aufgeführt, die zum Starten der Container verwendet wurden.
[bash light=”true”] $ docker run -d \–name=’low_prio’ \
–cpuset-cpus=0 \
–cpu-shares=20 \
busybox md5sum /dev/urandom
$ docker run -d \
–name=’high_prio’ \
–cpuset-cpus=0 \
–cpu-shares=80 \
busybox md5sum /dev/urandom
[/bash]
Zusammenfassung
Wenn Sie mehrere Docker-Container auf demselben Host verwalten, ist die Verwendung von Cgroups zur Verwaltung der Ressourcen zwischen den Containern sehr sinnvoll. Beispielsweise führen Sie vielleicht in einem Container Hintergrundprozesse aus, während ein anderer Container Benutzerinhalte bereitstellt. In diesem Fall können Sie Ihr neu gewonnenes Wissen nutzen, um sicherzustellen, dass Sie die benutzerorientierten Container gegenüber den Hintergrundaufgaben priorisieren.
Kommentare
Noch keine Kommentare. Schreiben Sie den ersten.