In einem Cluster, der durch Kubernetes verwaltet wird, darf eine Persistenz aber keine Abhängigkeit zu einem bestimmten Knoten (sei es eine VM oder Hardware) hinzufügen. Macht sie das dennoch, hat Kubernetes (und damit sein Scheduler) nicht mehr die Freiheiten, die benötigt werden, um wichtige “Nicht Funktionale Anforderungen” (NFR) wie hohe Verfügbarkeit, dynamische Skalierung, Health Checks, Re-Placement etc. sicher zu stellen. Zum Beispiel kann der Scheduler bei Ausfall von Knoten (z.B. während automatischer Kernel Updates) die Container nicht mehr einfach auf einem anderen Knoten neu starten.

In diesem ersten Teil des Artikels gibt es zunächst einen Vergleich der prinzipiellen Varianten, mit denen eine Persistenz bei gängigen Cloud Providern oder auch Bare Metal realisiert werden kann.

Massenspeicher

Storage Area Networks (SANs), Network Attached Storage (NAS) und Dateisysteme wie NFS gibt es schon eine ganze Weile.

Fast ebenso lange gibt es verschiedenste Dienste der Cloud-Anbieter. Sie bieten unter anderem:

Das sieht eigentlich nach brauchbaren Lösungen aus. Dennoch bleiben einige Fragen offen:

Strategien für zustandsbehaftete Applikationen

Generell erhöhen wir die Verfügbarkeit durch Replikation von Daten. Bei drei Knoten, die jeweils 99,95% garantierte Verfügbarkeit haben, kommt man bei dreifach redundanter Auslegung auf 99,9998%. Das heißt: die maximale Ausfallzeit von ca. 4.5 Stunden reduziert sich auf nur noch geringe 12 Minuten.

Natürlich lässt sich Verfügbarkeit nicht so trivial buchhalterisch berechnen. Es müssen alle Komponenten eines Systems beachtet werden. Gewisse Hardware-Komponenten werden gemeinsam verwendet, ebenso muss man auf Fehler der eigenen Software und der verwendeten Produkte achten. Überschlägig kann man aber gut erkennen, welche signifikante Auswirkung Redundanz auf die Verfügbarkeit hat.

Eine solche Replikation von Daten können wir generell über die Verwendung entsprechender Produkte wie MongoDB, Postgresql, Kafka etc. erreichen. Mit allen kann sichergestellt werden, dass pro Instanz auch eine Replika der Daten vorliegt. Die Frage, die sich hier stellt, ist aber: Wo werden die Daten gespeichert?

Stellt ein Cloud-Anbieter Block-Storage-Dienste bereit, die die notwendige Verfügbarkeit garantieren, ist eine mögliche Lösung schon gefunden. Fehlen solche Dienste, so ist eine VM-lokale SSD oder ein Container Native Storage (Cluster Filesystem) ein ebenso möglicher Weg.

Ein wichtiges Kriterium ist aber, dass containerisierte Anwendungen in Produktion einige spezifische Anforderungen haben. Wie bereits beschrieben, kann Kubernetes die Einhaltung einiger wichtiger NFRs sicherstellen. Bezogen auf persistente Daten heißt das: das Volume (Datenträger) einer Containerinstanz sollte dynamisch erzeugt werden können und muss auf jedem Knoten des Clusters stabil zur Verfügung stehen.

Managed Services

Cloud-Anbieter wie Amazon bieten fertige Dienste (managed services) für relationale oder NoSQL-Datenbanken, Messaging Systeme, BigData und vieles mehr an. Mitentscheidend ist hier, ob ein solches, zumeist im Ausland sitzendes Unternehmen für das eigene Projekt in Frage kommt und ob der erhöhte Vendor Lock-In ein Problem darstellt.

Managed Service
Managed Service

Pro:

Con:

Nutzung der Lokalen Persistenz

Die Nutzung einer lokalen SSD über eine VM oder auch über Bare Metal ist die einfachste und klassische Methode, Daten zu persistieren. Allerdings befinden sich alle Daten dann nur auf einem spezifischen Knoten. Verschiedene Anforderungen eines Container Managers können also nicht befriedigt werden. StatefulSets von Kubernetes, beispielsweise, werden so überhaupt nicht funktionieren.

Lokale Persistenz
Lokale Persistenz

Pro:

Con:

Managed Block Storage Services

Alle üblichen Cloud-Anbieter bieten in irgendeiner Form Block- oder Object-Storage-Dienste an. Solche Dienste können auf die Knoten und weiter in die Container gemountet werden. Im Fall von Kubernetes erfolgt das automatisch. Es stellt auch sicher, dass ein Volume mit dem “eigenen” Container zu einem anderen Knoten wandert, sollte das notwendig sein.

Es sollte auch nicht vergessen werden, dass hinter solchen Diensten immer ein komplexes Storage-System steckt. Die maximal verfügbaren IO Operations liegen signifikant unter denen einer lokalen SSD.

Managed Storage
Managed Storage

Pro:

Con:

Verteilte Dateisysteme

Werden Cluster File-Systeme (verteilte File-Systeme) durch Container verwendet, spricht man auch von einem Cloud Native Container Storage. Charakteristisch für solche Systeme im Umfeld Kubernetes ist:

Interessante Kandidaten sind derzeit:

Nutzung Lokaler Persistenz

Im Gegensatz zur direkten Nutzung lokalen SSDs kann ein Cluster FS eine ausreichende Grundlage zur Verwendung eines Container Managers legen. Hat man nur lokal Storage zur Verfügung ist das, neben dem Aufsetzen eines eigenen SAN, der einzig sinnvolle Weg.

Verteiltes FS mit Nutzung von lokaler Persistenz
Verteiltes FS mit Nutzung von lokaler Persistenz

Pro:

Con:

Nutzung Managed Block Storage Services

Natürlich kann man statt lokaler SSDs auch den Managed Storage des Cloud-Anbieters verwenden. Ob sich der Aufwand eines solchen weiteren Layers allerdings lohnt, muss im Detail geklärt werden, kann aber durchaus Vorteile bringen.

Verteiltes FS mit Nutzung von Managed Block Storage
Verteiltes FS mit Nutzung von Managed Block Storage

Pro:

Con:

Fazit

Mit den hier genannten Möglichkeiten, persistente Daten zu verwalten, lassen sich die meisten Anwendungsfälle wie Cloud Provider, Bare Metal, verschiedene Zugriffsszenarien etc. abdecken. Besonders die Systeme zur Container Native Storage erhöhen die Flexibilität und bieten dazu noch einige sehr sinnvolle Dinge wie Quotas oder Striping. Dennoch: obwohl ihre Anwendung recht leicht verständlich ist, darf ihre Komplexität nicht unterschätzt werden. Wer sich davor nicht scheut, sollte aber einen näheren Blick darauf werfen.

Im zweiten Teil dieses Posts werde ich näher auf die Unterstützung durch Kubernetes eingehen.