### 4.2 Lösungsarchitektur Im Verlauf der Entwicklung stellte sich heraus, dass eine zentrale Stelle zur Datenspeicherung benötigt wird, damit Entwickler Zugang zu den Daten sowohl im Staging-Bereich als auch in der Produktiv-Form haben. Die bereits in der ersten Phase des Projektes angelegte MongoDB im Atlas Hosting (internet-facing) wurde daher durch eine auf der FH-Infrastruktur gehostete Konstruktion ersetzt, die aus einer MongoDB und einer PostgreSQL-Datenbank besteht: Überblick über die Netzwerkarchitektur des FH K8s Clusters Da es sich bei dem zur Verfügung gestellten System um einen Kubernetes (K8s) Host handelt, wurden entsprechende Manifeste angelegt und auf dem Server bereitgestellt. Aufgrund der in der FH eingesetzten Netzwerkarchitektur war es jedoch nur möglich, den Server von außen über eine VPN-Verbindung (ForcePoint) zu erreichen. Dies stellte zwar keine große Herausforderung für die Projektteilnehmer dar, blockierte jedoch die Anbindung des selbst gehosteten Apache Airflow Servers. Daher wurden die regelmäßig bezogenen News-Artikel weiterhin in die im Internet stehende MongoDB gespeist und etwa einmal im Monat manuell in die FH-Infrastruktur überführt. Nach dem Aufsetzen des Development Environments und den ersten Entwicklungsfortschritten galt es, eine Zielarchitektur zu bestimmen. Aufgrund der Vorteile in Portabilität und Unabhängigkeit von den Gegebenheiten verschiedener Clients wurde sich für eine Docker-basierte Lösung entschieden. Die einzelnen Docker Container, respektive Images, wurden anhand ihrer Anwendungsdomäne sowie des geplanten Datenflusses geschnitten: Die Aufgaben der Container wurden wie folgt verteilt: 1. **Data Ingestion:** - Beziehen von Unternehmensdaten sowie News-Artikeln - Aufbereitung dieser Daten - Überführung in die Staging DB zur weiteren Verarbeitung 2. **Staging DB:** - Persistierung der "Roh-Daten" - Fachliche Trennung von Darstellung und Analyse 3. **Data Loader:** - Transformation der "Roh-Daten" in das für die Visualisierung benötigte Ziel-Format - Durchführung weiterer Analyse-Bausteine (unter anderem Sentiment) - Überführung in die ProdDB 4. **ProdDB:** - Persistierung der Daten im Schema für die Visualisierung 5. **Dashboard Server:** - Webserver zur Bereitstellung der UI - Dazugehörige Geschäftslogik (z.B. Aufbereitung der Graphen) Diese Aufteilung entstand unter anderem nach der Identifikation der verschiedenen Aufgaben-Domänen sowie ihrer Features: Im Detail: Auch für dieses Konstrukt galt es, eine Ausführungsumgebung zu bestimmen. Da sich der Umgang mit K8s für die Gruppe aufgrund mangelnder Erfahrung als nicht durchführbar erwies, wurde stattdessen auf den hinter [jupiter.fh-swf](https://jupiter.fh-swf.de) liegenden Server zurückgegriffen. Bei diesem handelt es sich um einen Docker Swarm Host, auf dem bereits unterstützende Tools wie NGINX oder Portainer installiert sind. Für das Deployment selbst wurde zunächst eine [`docker-compose.yml`](https://github.com/fhswf/aki_prj23_transparenzregister/blob/main/docker-compose.yml) entwickelt. Diese Datei erfasst alle benötigten Komponenten, verknüpft sie über entsprechende Konfigurationen des Docker-Netzwerks und Umgebungsvariablen miteinander und steuert schließlich die Verteilung auf dem Swarm Cluster. Um eine automatisierte Bereitstellung der Services sowie Aktualisierung dieser zu ermöglichen, wurde mit Portainer ein neues Deployment namens `transparenzregister` erstellt und mit dem Code-Repository verknüpft. Auf diese Weise überprüft Portainer in regelmäßigen Intervallen, ob relevante Änderungen im Repository vorliegen – sei es eine direkte Modifikation an der `docker-compose.yml` oder die Bereitstellung eines neueren Docker Images. Bei einer solchen Erkennung startet Portainer automatisch das Deployment erneut. Zudem wurde die NGINX-Konfiguration des Jupiter Servers erweitert, und der Webserver des Transparenzregisters so unter [https://jupiter.fh-swf.de/transparenzregister](https://jupiter.fh-swf.de/transparenzregister) dem Internet zur Verfügung gestellt. Die damit verbundenen Anpassungen an der Konfiguration des Deployments, wie etwa die Einführung des `BASE_PATH`s `/transparenzregister/` und die Integration von Basic Auth, um den Service vor Zugriff Externer zu schützen, wurden ebenfalls über die `docker-compose.yml` ermöglicht. Gebaut werden die dafür benötigten Docker-Images automatisiert in einer mittels GitHub Actions umgesetzten CI/CD-Pipeline. Um das Erstellen weiterer Images auf Basis des Repos zu vereinfachen und Wiederholungen im Aufbau sowie in der Konfiguration zu vermeiden, werden die einzelnen Images in einem Prozess erstellt. Dieser greift das im Projektbau entstehende `*.whl` auf und transferiert dieses neben weiteren grundsätzlichen Einstellungen - unter anderem Labels - zunächst in ein Base Image. Dieses wird daraufhin von den einzelnen Applikationen aufgegriffen, um die zusätzlich benötigten Abhängigkeiten zu erweitern und letztlich mit dem entsprechenden `CMD` auf die Zielapplikation ausgerichtet. Als `ENTRYPOINT` wird dabei [`["/usr/bin/tini", "--"]`](https://github.com/krallin/tini) verwendet, um die Threads zu verwalten und Zombie-Prozesse zu vermeiden. So ist gewährleistet, dass zentrale Einstellungen global für alle Applikationen identisch sind und bei Änderungen nur an einer Stelle eingeführt werden müssen. Was dabei entsprechend entfällt, ist die Möglichkeit, die Images getrennt voneinander zu bauen. Da das Projekt jedoch nur in einer kompatiblen Version aller Applikationen lauffähig ist, stellt dies kein signifikantes Hindernis dar. Da die eingesetzten Datenbanken (MongoDB, PostgreSQL) bereits als Images frei zur Verfügung stehen und keine weiteren Sonderkonfigurationen benötigt werden, wird auf den Bau eigener Images verzichtet und stattdessen auf die via Docker Hub verfügbaren Images gesetzt. Auch wenn das Deployment anfangs wie gewünscht ablief, traten im Laufe der Zeit einige Probleme auf. Die hohe Frequenz an Änderungen am `main`-Branch, der vom automatisierten Deployment überwacht wird, durch die Integration von Dependabot sorgte dafür, dass schnell aufeinander folgende Deployments auf dem Server gestartet wurden und somit eine hohe Downtime der Services entstand. Ebenfalls hatte dies den Seiteneffekt, dass Unmengen an Docker Images erstellt und auf den Server transportiert wurden. Dies hatte in Kombination mit der ohnehin hohen Anzahl an – teilweise veralteten – Images zur Folge, dass der Speicherplatz auf dem Server an seine Grenzen geriet. Dieser Herausforderung hätte durch eine feinere Steuerung des Deployments begegnet werden können. Unter anderem hätten Änderungen erst auf einem `develop`- oder `release`-Branch gesammelt und erst bei Vollendung mehrerer Features oder relevanter Änderungen (z.B. Aktualisierung eingesetzter Bibliotheken) auf den `main`-Branch überführt und somit in das Deployment übergeben werden können. Eine erweiterte Versionierungsstrategie der Images (z.B. nach Semantic Versioning) hätte ebenfalls unterstützen können. Alternativ hätten Vorkehrungen getroffen werden müssen, um die auf dem Jupiter Server abgelegten Docker Images regelmäßig aufzuräumen. Für die lokale Entwicklung sowie das Testen wurde zusätzlich eine [`local-docker-compose.yml`](https://github.com/fhswf/aki_prj23_transparenzregister/blob/main/local-docker-compose.yml) angelegt. Diese Datei beinhaltet den grundlegenden Aufbau des Produktiv-Deployments, wurde jedoch so angepasst, dass auf ein lokales Build der Docker Images aufgebaut wird. Zudem wurde ein zusätzlicher Container eingeführt, der die Staging DB zu Beginn mit einem Snapshot der eingesetzten Daten füllt, um somit den gesamten Datenfluss abspielen zu können. Näheres zum Aufsetzen wird in der [README](https://github.com/fhswf/aki_prj23_transparenzregister/blob/main/README.md) beschrieben. Um den kompletten Build Process neu zu starten, wurde zusätzlich die [rebuild-and-start.bat](https://github.com/fhswf/aki_prj23_transparenzregister/blob/main/rebuild-and-start.bat) angelegt, welche die dort beschriebenen Schritte in einem Skript kapselt.