Von Andreas Jordan auf Freitag, 18. Oktober 2024
Kategorie: Kurz & Gut

Kurz und gut – Episode #23 Mit Anmut und Würde: Graceful Shutdown von PowerShell Containern

​Wenn ein Anwendungscontainer beendet wird, erhält der darin laufende Prozess, vor der Terminierung, das SIGTERM-Signal. Dadurch hat dieser Prozess die Möglichkeit, die laufende Anwendung sauber zu beenden. So können noch schnell wichtige Daten gespeichert werden, bevor der Container vom Betriebssystem terminiert wird. Leider kann ein PowerShell-Skript das Signal nicht abfangen und verarbeiten. Stattdessen endet das Skript sofort. Damit besteht keine Chance, die laufende Verarbeitung sauber abzuschließen.

Mit einem kleinen Umweg über ein bash-Skript lässt sich dieses Problem aber lösen.

Der Umweg: Datei statt Signal

Auch außerhalb von Containern verwende ich das folgende Verfahren, gerade bei sehr lang laufenden Skripten, die im Wesentlichen eine Schleife durchlaufen. So wird bei jedem Schleifendurchlauf geprüft, ob eine bestimmte Datei vorhanden ist. Diese Datei dient somit als Signal. Ist die Datei vorhanden, wird die Schleife sofort verlassen und abschließende Arbeiten können durchgeführt werden, bevor das Skript endet. 

Die Übersetzung: Aus Signal wird Datei

Soll ein Container gestoppt werden, so sendet die Plattform (z. B. Kubernetes, OpenShift oder Docker Compose) das Signal SIGTERM an das im Container als ENTRYPOINT konfigurierte Programm. Dem Programm wird dann etwas Zeit gegeben, sich sauber zu beenden. Erst dann wird das Programm zwingend gestoppt und der Container entfernt.

Wir haben viel recherchiert und vieles ausprobiert. Aber PowerShell scheint nicht in der Lage zu sein, das Signal innerhalb eines Skriptes zu empfangen und zu verarbeiten. Wenn ihr andere Informationen habt, meldet euch gerne bei uns.

Um das Signal abfangen zu können, verwenden wir daher als ENTRYPOINT für den Container nicht mehr die PowerShell, sondern eine klassische Shell, in unserem Fall die bash. Von dort aus wird dann das eigentliche PowerShell-Skript gestartet. Eine kleine Shell-Funktion wird als Signalhandler eingesetzt und erzeugt die als Signal dienende Datei. Anschließend wird auf das Ende des PowerShell Prozesses gewartet, bevor das Shell-Skript und damit der Container beendet wird.

Das Skript

Das folgende Skript wird als start.sh in den Container integriert und mit ENTRYPOINT ["bash", "start.sh"] im Dockerfile referenziert:

Die eigentliche Arbeit des Containers übernimmt weiterhin das PowerShell-Skript start.ps1, das während seiner Arbeit immer wieder die Existenz der Datei /tmp/stop prüft.

Und wie sieht es innerhalb dieses Skriptes aus? Nehmen wir doch einfach das gleiche Beispiel wie in meinem letzten Blogartikel und ergänzen diesmal den Test auf die Datei: 

Warum PowerShell?

Falls ihr euch die ganze Zeit fragt, warum man PowerShell in Containern einsetzen sollte, will ich kurz von einem Einsatz berichten. Mit PowerShell ist sowohl der Zugriff auf REST-Schnittstellen als auch Datenbanken sehr einfach möglich. So lädt sich bei einem meiner Kunden ein PowerShell-Skript per REST-Schnittstelle Dateien aus einem MinIO Server herunter, zerlegt diese und importiert die Daten in eine Oracle-Datenbank. Wie der Zugriff von PowerShell auf Oracle erfolgt, habe ich hier schon einmal beschrieben.  

Fazit

Mit einem kleinen Umweg lassen sich auch PowerShell-Skripte in Containern betreiben.

Habt ihr spezielle Anforderungen? Sprecht uns gerne an. 

Seminarempfehlung

Kommentare hinterlassen