Dienstag, 14. Mai 2024

Cloud Serie: GCP Filestore vs. Cloud Storage - ESC Index-Applikation serverless mit Cloud Run betreiben


Die Google Cloud kennt verschiedene Werkzeuge, um Daten zu speichern. Es gibt verschiedene Datenbanken und mehrere Möglichkeiten, unstrukturierte Daten in Form von Dateien zu speichern. Jede Möglichkeit hat ihre Eigenschaften und die diesbezüglichen Vor- und Nachteile. Heute schauen wir uns an, wie man eine ESC Applikation mit einem persistenten Index serverless auf der GCP betreiben kann.

Um die Applikation serverless zu betreiben, verwenden wir Cloud Run. Bevor wir uns allerdings das konkrete Deployment mit Cloud Run anschauen können, müssen wir uns mit dem Speicher beschäftigen. Die ESC-Applikation verwendet einen Lucene-Index. Dieser ist Datei basiert, stellt gewisse Anforderungen an die API und kann sehr gross werden. Da der Index persistent sein muss und sehr gross werden kann, kommt eine Speicherung innerhalb des Cloud Rund Containers nicht in Frage. Wir brauchen eine Alternative.

Cloud Storage
Der Lucene-Index besteht aus einzelnen Dateien. Könnte man dafür also Cloud Storage verwenden? Spoiler: Nein, das geht nicht. Lucene bietet ein API an, mit welchem man eigene Storage-Implementierungen machen kann. So wäre es bspw. möglich, einen Lucene-Index in einer Datenbank zu speichern. Es gibt jedoch zwei Einschränkungen von Cloud Storage, welche eine robuste Implementierung verhindern:
  1. Cloud Storage kennt keinen Lock-Mechanismus. Es liegt nicht in der Natur dieses Speichers, dass Prozesse einzelne Objekte (Dateien) blockieren. Lucene braucht aber einen Lock-Mechanismus. Ohne diesen ist kaum abschätzbar, was die effektiven Seiteneffekte sind.

  2. Mit Cloud Storage kann man immer nur ganze Objekte (Dateien) speichern. Bei grossen Indizes ist dies bei vielen Schreiboperationen überhaupt nicht effizient. Lucene schreibt und entfernt auch nur Blöcke. Die Implementierung müsste dies simulieren, in dem jeweils das ganze Objekt gelesen, in Memory die Änderungen vorgenommen werden, und dann das ganze Objekt wieder gespeichert würde. Ineffizient und im Zusammenspiel mit dem fehlenden Lock gefährlich.
Cloud Storage kann entsprechend nicht für unseren servless Index-Storage verwendet werden. Diese Einschränkungen gelten auch, wenn FUSE verwendet wird, also ein Adapter mit welchem man Cloud Storage von der Semantik her wie ein "normales" Dateisystem verwenden könnte (Details siehe hier).

Filestore
Filestore ist ein verwaltet Dateispeicher, welcher POSIX kompatibel ist und Dateisperren sowie Nebenläufigkeit zulässt (gleichzeitiges Schreiben desselben Files). Mit der Verwendung von Filestore kann ESC ohne Anpassungen verwendet werden, da die Lucene Standardimplementierung der Storage-Klasse auch mit Filestore funktioniert. Daher werden wir im Folgenden Filestore für das serverless Deployment unserer ESC-Applikation verwenden.

Exkurs: Block-, Datei- und Objektspeicher
Wie Eingangs erwähnt bietet GCP verschiedene Speichermöglichkeiten. Diese lassen sich in die drei Kategorien: Blockspeicher, Dateispeicher und Objektspeicher einteilen. Blockspeicher (Block Storage) sind bspw. die Cloud Persistence Disks (HDD oder SSD). Ein Dateispeicher ist Filestore und ein Objektspeicher ist bspw. Cloud Storage.

ESC Beispiel-Applikation
Bevor wir eine Filestore-Instanz erstellen und unsere Applikation via Cloud Run deployen können, brauchen wir eine ESC-Applikation. Dazu schreiben wir eine ganz einfache ESC-Applikation, welche ein REST-API zur Verfügung stellt. Zu Testzwecken bietet die Applikation zwei Endpoints: Einen um eine Person hinzuzufügen (indexieren) und einen um eine Person zu suchen:

Beispiel ESC-Applikation


Cloud Run vorbereiten
Unsere Beispiel-Applikation müssen wir zu einem Assembly-JAR-File builden. Dies erleichtert anschliessend die Erstellung des Docker-Images.

Als nächstes erstellen wir ein Batch-Script, welches das Filestore-Verzeichnis mounted und die ESC-Applikation startet. Am besten wird das Script direkt im Root-Verzeichnis der Applikation erstellt, run.sh:

run.sh Bash-Script


Nun können wir das Docker-Image erstellen:

Docker-Image für ESC Beispiel-Applikation


Filestore-Instanz erstellen
Bis auf die Filestore-Instanz haben wir nun alles zusammen für unser Deployment. Die Filestore-Instanz ist einfach via CLI erstellt. Dazu brauchen wir noch einen VPC um anschliessend von Cloud Run darauf zugreifen zu können. Wir exportieren die IP-Adresse der Filestore-Instanz anschliessend als Variable und erstellen einen dedizierten Service-Account. Das ganze kann via CLI wie folgt erstellt werden (Platzhalter entsprechend ersetzen):

Filestore-Instanz mit VPC und Service-Account erstellen.

Cloud Run deployen
Nun haben wir alles zusammen und können unsere ESC-Applikation mit Cloud Run deployen (Platzhalter anpassen):

Cloud Run Deployment mit Docker-File


Landingzone, Security & Co.
Die im Beitrag von Cloud Function (hier) erwähnten Aspekte der Landingzone und Sicherheit etc. gelten auch für Cloud Run. Insbesondere das Thema Load Balancer, um eine eigene Domain für den Service zu erhalten.

Fazit
Eine Applikation kann schnell, mit einem einfachen Docker-File, in Cloud Run deployed werden. Eine Filestore-Instanz ist schnell erstellt und kann (auch) in einer Cloud Run Applikation verwendet werden. Damit lässt sich ein Grossteil von Applikationen recht einfach serverless auf der GCP betreiben.

Keine Kommentare: