Ressourcen-Limits

Eine Erkenntnis aus der Untersuchung der Stabilitätsprobleme war, dass Docker-Container beliebig viel Arbeitsspeicher beanspruchen und (vermutlich auf Grund der hohen Berechtigung mit der Docker läuft) damit das System in den Abgrund reißen können. Normalerweise kenne ich es so, dass zu speicherhungrige Programme vom System getötet werden, bevor sie die Stabilität gefährden.

Docker bietet die Möglichkeit, für jeden Container individuelle Ressourcen-Limits festzulegen. Dies kann die Rechenzeit betreffen, aber eben auch den Arbeitsspeicher. Dazu wird in der docker-compose.yaml ein Abschnitt deploy eingefügt (siehe auch hier). Ein Beispiel:

services:
  app:
    image: ...
    ports: ...
    volumes: ...
    deploy:
      resources:
        limits:
          memory: 256M

Hier wird für den Container mit Namen app ein Limit von 256 MB Arbeitsspeicher festgelegt. Mehr sieht dieser Container nicht, d.h. auch die Menge an Arbeitsspeicher, der für Buffers und Caches der Prozesse innerhalb dieses Containers aufgewendet wird, ist dadurch nach oben hin begrenzt.

Ich hätte nun den verfügbaren Arbeitsspeicher von ca. 950 MB einfach durch die Anzahl der Dienste teilen und jedem seinen Anteil zukommen lassen können. Dies hätte aber den Nachteil, dass jedes gesparte Megabyte "verloren" wäre, weil die anderen Dienste es nicht nutzen könnten. Stattdessen habe ich die einzelnen Dienste genau beobachtet und mir plausible Limits überlegt, die einerseits dem Bedarf der Dienste gerecht werden, andererseits aber ein Davonlaufen verhindern. Mein Gedanke: wenn ich z.B. insgesamt 1200 MB "austeile", aber kein Dienst mehr als 400 MB für sich selbst beanspruchen kann, ist das System vor einem einzelnen Amokläufer sicher und könnte zwei gleichzeitig durchgehende Container evtl. auch noch überleben.

In der Praxis hat sich gezeigt, dass ein Container, der viel Arbeitsspeicher zur Verfügung hat, auch viel beansprucht. Insbesondere filebrowser scheint nahezu beliebig viel Speicher zu konsumieren, allerdings eher im Sinne von Caching; ich konnte in der Bedienbarkeit keinen nennenswerten Unterschied feststellen zwischen einem Limit von 250 MB und einem Limit von 400 MB.

Die festgelegten Grenzen sieht man auch in der Anzeige von docker stats:

CONTAINER ID   NAME              CPU %     MEM USAGE / LIMIT   MEM %     NET I/O           BLOCK I/O        PIDS
69aeba43d2cc   linkding-app-1    0.02%     57.33MiB / 256MiB   22.40%    84.3kB / 1.34kB   4.81MB / 4.1kB   7
29201395c135   mosquitto-app-1   0.13%     1.438MiB / 8MiB     17.97%    42.4MB / 29.2MB   897kB / 0B       1

Die kleinste Menge, die als Limit angegeben werden kann, beträgt übrigens 6 MB und wäre für mosquitto wahrscheinlich immer noch genug.

Hinweis: damit das hier beschriebene Docker-Feature funktioniert muss eine Funktion des Linux-Kernels aktiviert werden, die beim Raspberry Pi OS per Default nicht aktiv ist. Dazu editiert man die Datei /boot/cmdline.txt und fügt die Anweisung cgroup_enable=memory hinzu.


Zurück zur Hauptseite