Kubernetes Persistent Volume Claims

In diesem Beitrag werden die Themen, stateful/sateless Anwendungen, Kubernetes Persistent Volume Claims und Bereitstellung-Strategien angesprochen.

Kubernetes Persistent Volume Claims

Dieser Beitrag wurde aus "akube Part 2: Die Server" extrahiert. In diesem Beitrag versuche ich, einen Überblick über die Form der Anwendungen und Speichermöglichkeiten innerhalb von Kubernetes zu vermitteln. Kubernetes Persistent Volume Claims - oder auch PVC - ist der Fachbegriff dafür.

Zustände

Bei unseren Anwendungen - die in der Regel in Containern laufen - kann man zwischen den Zuständen stateless und stateful unterscheiden.

Stateless

Zustandslos - also stateless - bedeutet, dass kein Zustand aufgezeichnet oder gespeichert wird. Man nehme einen reinen "Taschenrechner" WebService, der als Beispiel eine SUM Methode bereitstellt. Dieser Methode werden 2 Zahlen übermittelt, die wiederum addiert und dem Aufrufer zurückgeschickt werden. In dieser Konstellation sind weder die Summanden noch das Ergebnis wichtig. Deshalb braucht diese Anwendung keinen Speicher. Mit anderen Worten, diese Anwendung wird stateless betrieben.

Stateful

Eine Anwendung wird als stateful bezeichnet wenn der Zustand gespeichert wird und bei einem Neustart weiterhin zur Verfügung steht. So funktionieren die meisten Anwendungen. Ob es nun eine monolithische oder auf z.B. die Microservices-Architektur basierte Anwendung ist, spielt dabei keine Rolle. Bei Microservices ist es dann nicht die komplette Anwendung, sondern eine der einzelnen Komponenten, z.B. eine Datenbank.

Ok, give me more...

In der Regel betriebt man Container stateless. Container können auch im statefulf Zustand betrieben werden. Nehmen wir einen Autor, der seinen eigenen Blog betreibt. Ein Blog braucht persistenten Speicher. Ohne persistenten Speicher existieren die Beiträge nur während der Laufzeit.

Ein Blog ist eine Webanwendung, die im Hintergrund eine Datenbank und Speicher auf irgendeinem Dateisystem verwendet. Die Datenbank braucht natürlich auch einen physikalischen Speicherort um die Datenbank Dateien abzulegen.

Der große Vorteil von Kubernetes ist die Replikation und die Skalierbarkeit der einzelnen Pods. Um unser "Deployment" weiterhin replizierbar und skalierbar zu halten, darf es bei einer stateful Anwendung zu keinem Datenverlust kommen.

So jetzt fangen die Möglichkeiten an, die mit jedem "Deployment" und mit jeder Umgebung in der Regel variiert, und hier und da Vorteile in der Technik gegenüber Variante A, B oder C bietet.

Die  Replikation und die Skalierbarkeit unserer Deployments sollte immer im Fokus stehen. Daher gehe ich auf ein Paar Paradigmen und persönliche Erfahrungen von mir ein.

Fallbeispiel PaaS (Azure, AWS, Google Cloud)

Ich kenne mich eigentlich nur mit Azure unter den großen Cloud Anbietern aus. Ich würde für meinen Blog in Azure immer die nativen Azure Dienste verwenden. Als Container-Umgebung ACI. Als Datenbank Azure SQL. Für den Speicher Azure Filestorage.

  • Azure Filestorage für Dateien/Bilder
  • Azure SQL Service für Datenbank (CosmosDB für NoSQL oder Graphen)
  • ACI für den Cotnainer (AKS kann natürlich auch hergenommen werden)

Fallbeispiel Baremetal Kubernetes Cluster mit Cloud Storage/Services

Die Lösung in diesem Fall wäre einfach, man nehme die "Speicher" Dienste aus der Cloud, und konsumiere diese dann im eigenen Baremetal Kubernetes Cluster. Dafür reicht in der Regel eine Storage aus.

  • Baremetal Kubernetes Cluster (RKE)
  • Azure Filestorage
  • Azure SQL

Damit wäre unser "Deployment" evtl. nicht replizierbar, dieses Szenario habe ich tatsächlich noch nicht getestet. Mit anderen Worten, die Lösung für dieses Beispiel ist eine Annahme. Auf die potentiellen Probleme und was man bedenken muss, gehe ich im nächsten Beispiel ein.

Fallbeispiel Baremetal Kubernetes Cluster mit ohne Cloud Storage/Services

Die Lösung für diesen Fall unterscheidet sich gegenüber den beiden bereits genannten Fällen. Bei den ersten beiden Fällen legen wir die komplette Verantwortung für den Speicher in die Hände des Cloud-Dienstleisters.

Unser Speicher muss immer laufen, muss immer erreichbar sein, disaster recovery - also Backup & Restore Strategie - muss gegeben sein, usw.
In diesem Fall übernehmen wir die Verantwortung für unseren "Persistend Volume Claim".

Und hier fängt das Problem an, was nehmen wir? Wie machen wir das? Auf was ist zu achten? Tja, dafür gibt es nicht "die eine Lösung". Es gibt verschiedene Lösungen.

Kubernetes Persistent Volume Claims

Bei der Wahl unserer Lösung, müssen wir immer einen Punkt im Fokus haben. Richtig, die Replizierbarkeit. Daher betrachte ich für meine Deployments nur PVC die mit dem ReadWriteMany oder ReadOnlyMany Zugriffs-Modi betrieben werden. Das grenzt die Suche nach dem passenden PVC ein.

Viel einfacher ist es weg von "Deployments" - welches eigentlich für stateless gedacht ist - zu StatefulSets . Denn StatefulSets wurden genau dafür entwickelt. StatefulSets sind das Gerüst für stateful Anwendungen, die eine dauerhafte Identität und eine stabile Zuweisung benötigen. Im Hintergrund wird einem Pod - und dessen Replikationen - mit dem volumeClaim Template eine eigene PVC zugewiesen. Dadurch können auch ReadWriteOnce Provisionierer verwendet werden. Damit stehen uns wieder alle Kubernetes Persistent Volume Claims zur Verfügung.

Für diese Serie werde ich Heketi-GlusterFS - unterstützt ReadWriteMany Modus - als PVC verwenden. Eine weitere Variante die ich bald testen möchte ist die mit rook und ceph. Für unsere akube Reihe - und zukünftigen stateful Deployments - ist nur das dynamische Bereitstellen interessant, und beide Varianten bieten diese Möglichkeit.

Grundsätzlich kann man alles als Kubernetes Persistent Volume Claims verwenden, wofür es einen Storage Class provisioner gibt. Eine kleine Erläuterung zu den Storage Classes kann hier nachgelesen werden.