Docker image braucht healthcheck oder ähnliches

Ich hatte es jetzt zweimal, dass sich homegear im docker aus irgendwelchen, mir unbekannten Gründen beendete:

03/23/21 14:55:44.115 RPC Server (Port 2001): Info: Client number 16530 is calling RPC method: listBidcosInterfaces (2) Parameters:
03/23/21 14:55:53.903 Connection to IPC server closed (2).
03/23/21 14:55:53.914 Connection to IPC server closed (2).
03/23/21 14:55:53.916 Info: Connection to Homegear closed.
03/23/21 14:55:53.916 Info: Stopping lifetick thread...

Das Problem ist, dass anscheinend der start-Prozess (start.sh) weiterhin läuft, so dass Docker nicht mitbekommt, dass Homegear ausgestiegen ist. Daher startet es auch nicht den Container automatisch neu.

Folgende Ideen, um das Problem zu lösen:

  • Aufteilung der gestarteten Prozesse im start.sh Skript auf mehrere Container, so dass ein beendeter Prozess auch den start.sh stoppt und docker so den ganzen Container neustarten kann. Das würde aber bedeuten, dass man ggf mehrere Container braucht (homegear, webssh, influxdb, …). Dann bräuchte es docker-compose zum starten.
  • Einen Prozessmanager im Container starten, der ggf. Prozesse neustarten kann, wenn die unerwartet aussteigen
  • Die einzelnen Prozesse selber im start.sh überwachen und ggf neustarten
  • Einen Healthcheck implementieren, der Docker mitteilt, ob ggf. ein Prozess nicht mehr korrekt läuft, so dass docker den Container neustarten kann

Weitere Vorschläge?

Michael

1 Like

Ich habe mal eine provisorische Lösung erstellt. Als Swarm service könnte man folgenden Teil in die Servicedefinition übernehmen:

    healthcheck:
      test: ps -q `cat /var/run/homegear/homegear.pid` || exit 1
      interval: 5s
      timeout: 5s
      retries: 1

Damit erkennt Docker den Container als “Unhealthy”, wenn der homegear Prozess nicht mehr existiert. Als Swarm-Service wird der dann automatisch neugestartet.

oder wenn das als Standalone Container betrieben wird könnte man “exit 1” auch gegen einen kill-Befehl austauschen. Dann würde bei einem abgestürztem Homegear-Prozess auch der start.sh Prozess gekillt werden, was zu einem Neustart entsprechend der Neustart-Policy führen würde.

healthcheck:
  test: ps -q `cat /var/run/homegear/homegear.pid` || bash -c 'kill -s 15 -1'
  interval: 5s
  timeout: 5s
  retries: 1

So einen Healthcheck kann man auch direkt im Dockerfile konfigurieren.

Hey @Neuer_User,

lief/laeuft da homegear-management auch mit im Container? Weil normalerweise macht homegear-management quasi genau das … allerdings kann ich da nur fuer non-docker-Installationen sprechen, weiss nicht wie das im Container aussieht :thinking:

– Micha

Hi Micha

Ja, da läuft der homegear-management prozess. Hmm, scheint aber keinen Neustart zu generieren. Beide Prozesse (“Homegear” und “Homegear-management”) werden vom start.sh Skript gestartet und laufen eigentlich auch soweit unabhängig voneinander.

Soll eigentlich “Homegear-management” den “Homegear” Prozess starten? Wenn ja, dann ist das aber nicht so im start.sh Skript implementiert:

... [Ausschnitt aus start.sh] ...
/etc/homegear/homegear-start.sh
/usr/bin/homegear -u ${USER} -g ${USER} -p /var/run/homegear/homegear.pid &
sleep 5
/usr/bin/homegear-management -p /var/run/homegear/homegear-management.pid &
/usr/bin/homegear-webssh -p /var/run/homegear/homegear-webssh.pid &
/usr/bin/homegear-influxdb -u ${USER} -g ${USER} -p /var/run/homegear/homegear-influxdb.pid &

Huhu @Neuer_User,

nene, der homegear-management hat auch eine Art watchdog der den homegear-Prozess ueberwacht und ihn neu startet sollte er “abschmieren”. Ich weiss aber wie gesagt nicht ob das im Container funktioniert …

– Micha

Hallo Micha

Im container scheint das nicht zu funktionieren. Ich habe ein paar Tests gemacht. Wenn ich den homegear-Prozess stoppe (ohne den healthcheck), dann passiert gar nichts: Kein Neustart des Homegear-Prozesses. Obwohl der homegear-management Prozess läuft.

Woher weiss der Management-Prozess denn, welchen Prozess er überwachen soll? Und woher weiss er, wie er den neustarten soll (also z.B. Pfad und Start-Argumente)? Zumindest im Container start.sh ist es nicht offensichtlich, wie der Management-Prozess diese Infos erhalten soll.

Wer weiss denn genauer, wie der Watchdog-Prozess in homegear-management exakt funktionieren soll? @sathya ?

Hmm, ich habe mir einmal die management.conf genauer angeschaut. Da gibt es ein paar interessante Zeilen:

# The management service looks for the Homegear socket files in this directory.
socketPath = /var/run/homegear

# Space seperated list of service commands Homegear Management is allowed to execute
allowedServiceCommands = start stop restart reload status enable disable

# Space seperated list of services Homegear Management is allowed to control
controllableServices = homegear homegear-influxdb influxdb mosquitto openvpn@cloudmatic ssh

Das liest sich für mich wie folgt:

  • Homegear Management nutzt den socket, um festzustellen, ob Homegear noch läuft
  • die Steuerung von Homegear erfolgt mittels der Befehle “start stop reload …”, vermutlich via systemd

Während der socket in Docker noch funktionieren kann (da gemeinsames Volume), klappt ein restart via systemd natürlich nicht.

Es stellt sich damit eigentlich die Frage: Brauchen wir homegear-management überhaupt im Docker-Container?

Hi @Neuer_User,

das stimmt leider nicht ganz. Die allowedServiceCommands bzw. controllableServices legen fest, welche Kommandos an welche Services durch die RPC-Funktionen von homegear-management (z.B. durch die AdminUi oder sonstigen Scripten) ausgefuehrt werden duerfen. Das hat nichts mit watchdog-Funktionalitaeten zu tun.

– Micha

Hallo Micha

Was mich bei den allowedServiceCommands wundert ist z.B. “start” oder “enable” und “disable”. Wie soll so ein Befehl denn über die RPC an homegear gesendet werden? “Reload” und “Restart” oder “Stop” könnten gehen. Aber die anderen beziehen sich ja klar auf einen Prozess der aktuell entweder nicht läuft (“Start”) oder dessen automatisches Starten mit “Enable” oder “Disable” festgelegt wird.

Es ist doch vermutlich kein Zufall, dass die Commands genau gleich heissen, wie die systemctl Befehle? ("
start stop restart reload status enable disable")

Ich weiss nicht, aber für mich sieht das noch stark so aus, als ob Homegear-Management per systemctl die in controllableServices genannten Services kontrolliert. Dafür spricht auch, dass da auch neben homegear völlig andere Services gelistet sind (“influxdb mosquitto openvpn ssh”), die gar kein RPC-Interface anbieten. Die kann man eigentlich nur per systemctl steuern.

Also, ohne die Details zu kennen, würde ich wirklich vermuten, dass das Monitoring durch den Management-Prozess von Homegear vielleicht über das RPC-Interface geht. Ein Neustarten würde aber vom Management-Prozess über systemd-Befehle (systemctl) gesteuert werden. Und das funktioniert im Docker-Container natürlich nicht, da Homegear dort von einem start.sh Skript gestartet wird und nicht durch systemd.

Hi @Neuer_User,

das stimmt, homegear-management kann per systemctl diese Dienste kontrollieren. Per RPC geht das dann ganz einfach mit $hg->managementServiceCommand(<service>,<command>); (siehe hier und hier). Diese Settings, bzw. Moeglichkeit, ist auch nicht dafuer gedacht den Homegear-Prozess zu ueberwachen/managen.

Das “Monitoring” funktioniert auch per IPC, da sich homegear-management & homegear sowieso darueber “unterhalten” (siehe hier).

Aber nochmal: ich weiss nicht ob/wie das in einem Container funktioniert, da ich diese nicht nutze.

– Micha

Hi Micha

Dann haben wir ja eigentlich einigermassen das gleiche Verständnis. Was das für Docker und Container bedeutet, ist ganz einfach, dass es da nicht funktioniert :slight_smile:

Im Container läuft kein systemd, also tut ein “systemctl” ganz einfach gar nichts. Daher kann der Management-Prozess zwar auf der RPC-Schnittstelle feststellen, dass der Homegear-Prozess nicht mehr existiert, aber er kann ihn auch nicht neustarten.

Ich weiss noch nicht einmals, ob in einer “normalen” nicht-Docker-Umgebung das wirklich der Management-Prozess übernimmt. Normalerweise macht systemd das völlig selbstständig. Wenn sich ein Prozess unerwartet beendet, dann startet systemd den automatisch neu.

Bei Docker müsste man das eben anders abbilden. Docker kann sowas steuern. Dazu müsste Docker aber wissen, dass der Homegear-Prozess abgestürzt ist. Docker überwacht aber nur den PID1-Prozess im Container. Und das ist der start.sh Prozess. Da liegt das Problem.

Sinnvoll wäre vielleicht ein ganz anderer Ansatz. Anstatt mehrere Prozesse im Docker-Container mit start.sh zu starten, sollte vielleicht der Container mehrmals gestartet werden mit jeweils einen Prozess. Dann übernimmt Docker die Steuerung der einzelnen Prozesse.

Ich kenne mich leider viel zu wenig mit Homegear aus, um das korrekte Zusammenspiel der Prozesse zu kennen. Sonst könnte ich da mal einen Vorschlag machen.

1 Like

Hi

ohne zu tief in Docker einzusteigen, das ursprüngliche Problem von dir, würde es auch dazu führen, dass homegear als non-docker app ein vergleichbares Symptom zeigt? (also unabhängig davon ist ob mit oder ohne docker)

cheers

Hi Jipp

Im “Normalbetrieb” ohne Docker übernimmt systemd die Kontrolle über den Prozess und würde im Falle eines Absturzes Homegear automatisch neustarten. Also, nein, dieses Problem ist Docker-spezifisch, da es dort keine systemd gibt.

der Vorschlag wäre also alles in Microservices aufzuteilen und für jeden einen eigenen Container zu nutzen, damit Docker das Monitoring für jeden einzelnen Container/Service übernehmen kann.

Hört sich sehr aufwendig an. Gibt es keine Alternative? Einen supervisor Process, anstelle des start.sh, der auch Processe neu starten kann oder zumindest alle wichtigen Prozesse überwacht und dann den Container neu startet falls etwas schief geht?

Ich denke, das mit den Microservices ist vielleicht gar nicht so komplex. Man braucht vielleicht nur ganz wenig Anpassungen. Auch vom Buildprozess aus kann eigentlich (fast) alles gleich bleiben.

Es würde eben bei einem Image bleiben, in dem (wie auch jetzt) alle drei oder mehr Binaries für die Services drin sind. Man würde aber drei Start-Skripte anstelle von einem start.sh brauchen.
In einem einfachen docker-compose file würde man dann eben von Docker aus nicht nur einen Container starten, sondern drei (oder wieviele Services es braucht) Starts durchführen => gleiches Image, aber unterschiedliches Start.sh aufrufen.

Das könnte etwa so aussehen (bitte nur schematisch betrachten):

version: "3"

services:
  homegear:
    image: homegear/homegear:stable
    restart: unless-stopped
    ports:
      - 2001-2004:2001-2004
    environment:
      - HOST_USER_ID=65534
      - HOST_USER_GID=65534
      - TZ=Europe/Berlin
    volumes:
      - /data/homegear/etc:/etc/homegear:Z
      - /data/homegear/lib:/var/lib/homegear:Z
      - /data/homegear/firmware:/usr/share/homegear/firmware:Z
      - /var/log/homegear:/var/log/homegear:Z
    tmpfs:
      - /run
    entrypoint: /start-homegear.sh
    stop_grace_period: 60s

 homegear-management:
    image: homegear/homegear:stable
    restart: unless-stopped
    ports:
      - 2001-2004:2001-2004
    environment:
      - TZ=Europe/Berlin
    volumes:
      - /data/homegear/etc:/etc/homegear:Z
      - /data/homegear/lib:/var/lib/homegear:Z
      - /data/homegear/firmware:/usr/share/homegear/firmware:Z
      - /var/log/homegear:/var/log/homegear:Z
    tmpfs:
      - /run
    entrypoint: /start-homegear-management.sh

 homegear-webssh:
    image: homegear/homegear:stable
    restart: unless-stopped
    environment:
      - TZ=Europe/Berlin
    volumes:
      - /data/homegear/etc:/etc/homegear:Z
      - /data/homegear/lib:/var/lib/homegear:Z
      - /data/homegear/firmware:/usr/share/homegear/firmware:Z
      - /var/log/homegear:/var/log/homegear:Z
    tmpfs:
      - /run
    entrypoint: /start-homegear-webssh.sh

Wie erwähnt, das ist nur schematisch zu sehen (ob die Ports und Volumes so stimmen für die aufgeführten Services “Homegear”, “Homegear-Management” und “Homegear-Webssh” weiss ich nicht.

Vorteil wäre, dass der User sogar selber entscheiden kann, welche Prozesse er haben möchte. Wenn er Webssh nicht braucht, könnte er es auch rauslassen, etc.

Mit diesem Kontrukt sollte es möglich sein, dass die Start-Skripte auch terminieren, wenn der gestartete Service abstürzt. Dann kann Docker den Prozess entsprechend der “restart: unless-stopped” Direktive automatisch neustarten.

Hab mal deine Kommentare aufgenommen und ein Update Homegear auf docker - erste Schritte - #11 by jipp gemacht.
Kommentare sind willkommen

3 Likes