In professionellen Umgebungen weist man Containern stets feste Ressourcen zu. So wird nämlich verhindert, dass ein Docker-Host von nur einem einzigen Container und dessen Ressourcenwünschen vollkommen unter Beschlag genommen wird. Allerdings sollte man die Limits nicht auf gut Glück festlegen. Man kann nämlich ganz leicht prüfen, wie ressourcenhungrig ein Container ist.
Um dessen genauen Verbrauch zu ermitteln, gibt es verschiedene Anwendungen. Eines der beliebtesten Tools ist dabei Docker Stats. Mit dem in Docker integrierten Befehl kannst du Informationen über CPU-Auslastung, Speicherbedarf, Netzwerkverkehr und vieles mehr abrufen. Wie das genau funktioniert und welche Best Practices es dabei gibt, verrate ich dir in diesem Artikel.
Docker Stats: Das integrierte CLI-Tool
Standardmäßig in Docker integriert ist der Befehl docker stats. Mit ihm kann man sich aussagekräftige Statistiken zur RAM-Benutzung oder CPU-Auslastung von Containern anzeigen lassen. Besonders gut gemacht ist dabei die Formatierungs- und Filterfunktion. Um Docker Stats zu verwenden, musst du einfach den folgenden Befehl im Terminal ausführen:
docker stats <container-name>
Nun erhältst du Echtzeitinformationen über den Ressourcenverbrauch deines Containers. Allerdings ist die Ausgabe recht umfangreich und gerade in Skripten braucht man häufig nur einen bestimmten Parameter. Eine Filterung nach bestimmten Werten kannst du daher wie folgt vornehmen:
docker stats --format "{{.Container}} {{.CPUPerc}}"
Du kannst den Docker Stats Befehl zum Beispiel alle 5 Minuten den aktuellen Ressourcenverbrauch mithilfe eines Cronjobs abfragen lassen. Die Ausgabe leitest du dann direkt in eine HTML-Datei für einen Webserver-Container um. Damit kannst du die Werte direkt im Browser überwachen.
cAdvisor: Wenn es grafisch sein darf
Ich selbst bin ein großer Fan von Kommandozeilenprogrammen. Allerdings möchte nicht jeder auf weiße Schrift im schwarzen Terminal-Fenster blicken. Daher möchte ich dir noch ein Open-Source-Tool von Google vorstellen. cAdvisor wurde zur Überwachung von Docker-Containern entwickelt. In einem Web-Dashboard bekommt man detaillierte Informationen über die Ressourcennutzung.
cAdvisor selbst arbeitet dabei als Agent innerhalb jedes Docker-Hosts und sammelt so kontinuierlich Informationen über die Ressourcennutzung. Unter anderem kann man sich so die CPU-Auslastung, den Speicherbedarf, den Netzwerkverkehr und die I/O-Aktivitäten grafisch anzeigen lassen. Wer cAdvisor einmal ausprobieren möchte, kann das mit folgendem Docker Run Befehl tun:
docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:ro \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
google/cadvisor:latest
Ressourcen: Wie man sie fest zuteilt
Docker ermöglicht es uns, CPU- und Speicherressourcen für unsere Container festzulegen. Einerseits können wir das beim Docker Run Kommando machen oder wir legen die Limits in einer Docker-Compose.yml fest. Zu Beginn möchte ich dir exemplarisch zeigen, wie man bei docker run vorgehen kann. 2 CPU-Kerne lassen sich so vergeben:
docker run --cpus=2 <image-name>
Arbeitet man hingegen deklarativ, braucht man auch nicht allzu viel Aufwand zu betreiben. Bei Docker Compose lassen sich Ressourcen wie CPUs oder RAM in 2 Codezeilen zuteilen. Im folgenden Beispiel erhält der Dienst „my-service“ 2 CPUs und 1 GB an Arbeitsspeicher:
version: "3"
services:
my-service:
image: my-image
cpus: "2"
mem_limit: "1g"
Natürlich gibt es nicht nur einzelne Docker-Nodes auf der Welt. Zwar ist Docker Swarm ein absolutes Nischenprodukt und wird im Vergleich zu Kubernetes fast gar nicht eingesetzt, aber mein Artikel soll vollständig sein. Daher möchte ich dir auch noch zeigen, wie man in einem Schwarm den Ressourcenverbrauch bestimmen kann. Vorgehensweisen gibt es dabei 2.
Du kannst entweder die globale Ressourcenzuweisung konfigurieren, die für alle Dienste im Swarm-Cluster gilt, oder einfach die Ressourcen auf Dienstebene zuweisen. Letzteres ist dabei natürlich die sinnvollere Variante. Möchtest du festsetzen, dass alle vorhandenen Dienste maximal 4 CPUS nutzen dürfen, gehst du so vor:
docker swarm update --global-resources cpus=4
Soll stattdessen nur ein bestimmter Service limitiert werden, kannst du dessen maximalen Ressourcenverbrauch direkt bei der Erstellung festlegen. Das folgende Beispiel weist dem Dienst „my-service“ 2 CPUs und 1 GB Speicher zu.
docker service create --name my-service --limit-cpu 2 --limit-memory 1g <image-name>