Bei der Beobachtung der Systemeigenschaften wie Last und Speicherverbrauch hatte ich mehrfach festgestellt, dass
die Beobachtung das Experiment verändert hat. Beispielsweise war die durchschnittliche Systemlast der
letzten Minute immer stark geprägt vom SSH-Login und dem Aufruf von uptime
. Das hatte ich
anfangs noch hingenommen, aber spätestens bei der Beobachtung der Wachzustände war das Mist. Als
Lösungsmöglichkeit habe ich mich mit MQTT beschäftigt und inzwischen ein paar Skripte laufen, die
regelmäßig Informationen zu den Betriebsparametern liefern.
Bei MQTT wird ein Server (Broker) bereitgestellt, bei dem sich
verschiedene Clients anmelden können. Jeder Client kann sowohl Senden als auch Empfangen, aber
üblicherweise sind das applikativ getrennte Rollen. Der Sender kippt Informationen ein (publish),
die in Topics strukturiert sind (z.B. system/cpu/temperature
). Der oder die Empfänger
abonnieren (subscriben) die Topics, für die sie sich interessieren, und erhalten die Informationen
als Benachrichtigung. Weiterhin können Informationen so gesendet werden, dass der Broker ihren letzter Wert
speichert und direkt zustellt, wenn sich ein Client neu darauf abonniert (retain).
Als Broker setze ich Eclipse Mosquitto ein, als Docker-Container mit
Volumes auf der SD-Karte (damit ich ihn während der Backups nicht beenden muss). Mosquitto ist erfreulich
sparsam in Bezug auf Arbeitsspeicher, der ganze Container dümpelt die meiste Zeit bei circa 2 Megabyte
herum. Da ich keine Benutzerkonten benötige komme ich fast mit der Standard-Konfiguration aus, es muss
lediglich der anonyme Zugriff von anderen Hosts aus erlaubt werden (allow_anonymous true
). Die
Topics werden bei MQTT nicht eingerichtet oder vorgegeben, sondern entstehen automatisch durch das Senden
darauf.
Auf der Client-Seite habe ich mit mqtt-simple
experimentiert, bin aber relativ schnell auf eigene
Python-Skripte unter Verwendung von paho-mqtt umgestiegen.
Für die Darstellung hatte ich etwas mit Node-RED rumgespielt, habe mir
dann aber meine eigenen Dashboards ebenfalls als Konsolen-Anwendungen mit Python und
prettytable zusammengebaut. Da waren auch so Features wie
"maximaler Arbeitsspeicherverbrauch seit Beobachtung" leicht umsetzbar, was ich zur Bestimmung der
Ressourcen-Limits genutzt habe. Auch die Beobachtung der
Festplatten-Wachzustände erfolgt via MQTT, wobei ich hier auf der Beobachterseite einfach einen Aufruf von
mqtt-simple
in eine Textdatei schreiben lasse (auf dem Pi selbst, damit es rund um die Uhr laufen
kann).
syswatch.py |
svcwatch.py |
|
---|---|---|
HDD state: idle (since 3 hours ago) Load average: 0.22, 0.32, 0.27 Memory usage: 46.7% (536.3 MB available) System uptime: 1 day, 14 hours and 52 minutes Temperature: 47.2 °C Volume usage backup: 2.7% (1.8 TB available) Volume usage live: 5.3% (902.3 GB available) |
+-------------+--------+----------------+---------------+ | service | limit | currently used | highest seen | +-------------+--------+----------------+---------------+ | filebrowser | 262144 | 8888 ( 3.4%) | 11172 ( 4.3%) | | gogs | 262144 | 46308 (17.7%) | 46524 (17.7%) | | linkding | 262144 | 64080 (24.4%) | 64084 (24.4%) | | mosquitto | 8192 | 1552 (18.9%) | 1556 (19.0%) | | mytinytodo | 65536 | 13760 (21.0%) | 13776 (21.0%) | | vaultwarden | 98304 | 16524 (16.8%) | 16608 (16.9%) | +-------------+--------+----------------+---------------+ |
Etwas kniffliger war die eigentliche Datenerhebung. Im ersten Anlauf hatte ich viel aus /proc
gelesen oder externe Programme gestartet und deren Ausgabe geparst (z.B. df -k
oder
docker stats --no-stream
). Nach und nach habe ich diese Aufrufe durch Funktionen aus verschiedenen
Python-Bibliotheken ersetzen können
(shutil,
psutil und
docker). Das Skripte-Ökosystem besteht jetzt aus drei
Datenquellen (hddmon.py
, svcmon.py
und sysmon.py
) sowie zwei Dashboards
(svcwatch.py
und syswatch.py
). Die leichte Asymmetrie ergibt sich daraus, dass die
Erhebung der HDD-Aktivität vergleichsweise komplex ist, die Darstellung des Zustands aber hübsch in
syswatch.py
aufgegangen ist. Das Schöne an MQTT und den Topics ist, dass Informationen zwar
dezentral eingekippt werden können, am Ende aber trotzdem wie aus einer Quelle aussehen. (MQTT kennt kein
Konzept von Eigentümern oder Schreibberechtigten; man tut sich aber selbst einen Gefallen, wenn man die
hierarchische Struktur nutzt, und die Blattknoten konzeptionell somit doch einen definierten Eigentümer
haben, der als einziger darauf schreibt, um Kollisionen zu vermeiden.)
Update: inzwischen habe ich die Langzeiterfassung der Festplattenaktivität auch mit einem
Python-Skript umgesetzt (hddlog.py
), um die Abhängigkeit zu mqtt-simple
zu
verlieren (vorher war hier die Installation eines Perl-Packages via CPAN notwendig).
Update: ich habe die vielen Einzelskripte (svcmon.py
, svcwatch.py
,
sysmon.py
, syswatch.py
und das Hilfsskript mqtthelper.py
) durch zwei
komplexere, aber besser strukturierte Skripts ersetzt: observer.py
und dashboard.py
.
Außerdem habe ich die viele einzelnen Datenpunkte durch zwei Telegramme ersetzt, die jeweils ein
JSON-Objekt beinhalten. Das macht einerseits die Auswertung einfacher, andererseits ist die Datenkonsistenz
sichergestellt (vorher war es Glückssache, ob alle Datenpunkte schon einmal empfangen wurden und ob der
Inhalt zueinander passt). Außerdem habe ich den MQTT-Broker selbst komplett aus filebox4
herausgetrennt und als eigenen Dienst laufen; das war notwendig geworden, weil ich den Broker auch für
andere Projekte nutze und mir die Querabhängigkeit ein Dorn im Auge war...
dashboard.py |
---|
+-------------------+-----------+-------------------+-------------------+ | Service | Limit | Currently used | Highest seen | +-------------------+-----------+-------------------+-------------------+ | filebrowser-app-1 | 256.0 MiB | 10.9 MiB ( 4.3%) | 12.6 MiB ( 4.9%) | | gogs-app-1 | 256.0 MiB | 109.1 MiB (42.6%) | 240.0 MiB (93.8%) | | linkding-app-1 | 256.0 MiB | 125.1 MiB (48.9%) | 127.4 MiB (49.8%) | | mqtt-broker-app-1 | 8.0 MiB | 1.9 MiB (23.4%) | 1.9 MiB (23.5%) | | mytinytodo-app-1 | 64.0 MiB | 10.2 MiB (15.9%) | 10.2 MiB (15.9%) | | vaultwarden-app-1 | 96.0 MiB | 35.9 MiB (37.3%) | 39.0 MiB (40.6%) | +-------------------+-----------+-------------------+-------------------+ +-----------------------+-------------------------------------------+ | Property | Value | +-----------------------+-------------------------------------------+ | Load average | 0.25, 0.22, 0.19 | | Memory usage | 63.0% (372.7 MB available) | | System uptime | 2 months, 14 days, 23 hours and 6 minutes | | Temperature | 46.2 °C | | Volume "backup" usage | 108.1 GB of 2.0 TB used (5.5%) | | Volume "live" usage | 103.3 GB of 1.0 TB used (10.3%) | +-----------------------+-------------------------------------------+ |
Als weitere Verbesserung wird der "Highest seen"-Wert jetzt serverseitig ermittelt und kann somit auch über einen längeren Zeitraum betrachtet werden, als nur während einer Beobachtungssitzung. Allerdings ist die Abtastrate mit (Voreinstellung) 1/Minute etwas gering für eine echte Performance-Messung.