Die Speicherung von Anwendungsdaten, die in einem Kubernetes-Cluster ausgeführt werden, kann auf verschiedene Weise eingerichtet werden. Einige davon sind bereits veraltet, andere sind erst vor kurzem hinzugekommen. In diesem Artikel werden wir das Konzept der drei Optionen zur Anbindung von Speicherlösungen betrachten, einschließlich der neuesten — der Anbindung über die Container Storage Interface.

Methode 1. Angabe von PV im Pod-Manifest
Ein typisches Manifest, das einen Pod in einem Kubernetes-Cluster beschreibt:

Die Teile des Manifests, in denen angegeben wird, welcher Speicher gemountet wird und wohin, sind farblich hervorgehoben.
Im Abschnitt volumeMounts geben die Mount-Punkte (mountPath) an — in welchen Ordner innerhalb des Containers das persistente Volume gemountet wird, sowie den Namen des Volumes.
Im Abschnitt x listen alle Volumes auf, die im Pod verwendet werden. Sie geben den Namen jedes Volumes sowie den Typ an (in unserem Fall: awsElasticBlockStore) und die Anschlussparameter. Welche Parameter im Manifest aufgeführt werden, hängt vom Typ des Volumes ab.
Das gleiche Volume kann gleichzeitig in mehreren Containern des Pods gemountet werden. Auf diese Weise können verschiedene Prozesse der Anwendung auf dieselben Daten zugreifen.
Diese Art der Anbindung wurde zu Beginn von Kubernetes entwickelt und ist heute veraltet.
Bei der Verwendung treten mehrere Probleme auf:
- Alle Volumes müssen manuell erstellt werden, Kubernetes kann nichts für uns erstellen;
- Die Zugriffsparameter für jedes Volume sind einzigartig und müssen in den Manifesten aller Pods angegeben werden, die das Volume nutzen;
- Um das Speichersystem zu ändern (z.B. von AWS zu Google Cloud umzuziehen), müssen die Einstellungen und der Typ der angeschlossenen Volumes in allen Manifesten geändert werden.
Das alles ist sehr unpraktisch, weshalb in der Praxis solche Methoden nur für den Anschluss bestimmter spezieller Volumetypen verwendet werden: configMap, secret, emptyDir, hostPath:
configMap und secret sind Systemvolumes, die es ermöglichen, in einem Container ein Volume mit Dateien aus den Kubernetes-Manifesten zu erstellen.
emptyDir ist ein temporäres Volume, das nur für die Lebensdauer des Pods erstellt wird. Es eignet sich gut für Tests oder zur Speicherung temporärer Daten. Wenn der Pod gelöscht wird, wird das emptyDir-Volume ebenfalls gelöscht und alle Daten gehen verloren.
hostPath — ermöglicht das Einbinden eines beliebigen Verzeichnisses des lokalen Servers, auf dem die Anwendung läuft, in den Container der Anwendung, einschließlich /etc/kubernetes. Diese Funktion birgt Sicherheitsrisiken, weshalb Sicherheitsrichtlinien in der Regel die Verwendung solcher Volumes untersagen. Andernfalls könnte ein Angreifer sein Container mit dem Verzeichnis des HTC Kubernetes einbinden und alle Clusterzertifikate stehlen. Im Allgemeinen dürfen hostPath-Volumes nur von Systemanwendungen verwendet werden, die im Namespace kube-system ausgeführt werden.
sind in der Dokumentation aufgeführt.
Methode 2. Verbindung zu Pods SC/PVC/PV
Eine alternative Verbindungsmethode ist das Konzept von Storage-Klasse, PersistentVolumeClaim, PersistentVolume.
Storage-Klasse speichert Verbindungsparameter zum Speichersystem.
PersistentVolumeClaim beschreibt die Anforderungen an das Volume, das die Anwendung benötigt.
PersistentVolume speichert Zugriffsparameter und den Status des Volumes.
Das Kernkonzept: Im Manifest des Pods wird ein Volume vom Typ PersistentVolumeClaim angegeben, und der Name dieser Entität wird im Parameter claimName angegeben.

Im Manifest PersistentVolumeClaim werden die Anforderungen an die Daten beschrieben, die die Anwendung benötigt. Dazu gehören:
- die Größe der Festplatte;
- Zugriffsart: ReadWriteOnce oder ReadWriteMany;
- Ein Verweis auf die Storage Class — in welchem Speichersystem wir das Volume erstellen möchten.
Im Manifest der Storage Class werden der Typ und die Parameter für die Verbindung zum Speichersystem gespeichert. Diese sind für den Kubelet erforderlich, um das Volume auf dem Knoten zu montieren.
In den Manifesten von PersistentVolume wird die Storage Class und der Zugang zu einem bestimmten Volume (Volume-ID, Pfad usw.) angegeben.
Beim Erstellen eines PVC überprüft Kubernetes, welches Volume in welcher Größe und aus welcher Storage Class benötigt wird, und wählt das verfügbare PersistentVolume aus.
Wenn keine solchen PVs verfügbar sind, kann Kubernetes ein spezielles Programm — Provisioner (ihr Name wird in der Storage Class angegeben) — starten. Dieses Programm verbindet sich mit dem Speichersystem, erstellt ein benötigtes Volume, erhält eine ID und erstellt im Kubernetes-Cluster das Manifest PersistentVolume, das mit dem PersistentVolumeClaim verknüpft ist.
Diese Vielzahl von Abstraktionen ermöglicht es, die Informationen darüber, mit welchem Speichersystem die Anwendung arbeitet, von der Ebene der Anwendungsmanifeste auf die Verwaltungsebene zu verlagern.
Alle Verbindungsparameter zum Speichersystem befinden sich in der Storage-Klasse, für die die Cluster-Administratoren verantwortlich sind. Bei einem Umstieg von AWS auf Google Cloud muss nur der Name der Storage-Klasse im PVC in den Anwendungsmanifesten geändert werden. Die Persistent Volume zum Speichern von Daten werden automatisch im Cluster erstellt, mithilfe des Provisioner-Programms.
Methode 3. Container Storage Interface
Der gesamte Code, der mit verschiedenen Speichersystemen interagiert, ist Teil des Kubernetes-Kernels. Die Veröffentlichung von Fehlerbehebungen oder neuen Funktionen ist an neue Releases gebunden, und der Code muss für alle unterstützten Versionen von Kubernetes angepasst werden. All dies ist schwer zu warten und neue Funktionen hinzuzufügen.
Um das Problem zu lösen, haben Entwickler von Cloud Foundry, Kubernetes, Mesos und Docker das Container Storage Interface (CSI) geschaffen — eine einfache, einheitliche Schnittstelle, die die Interaktion des Container-Orchestrierungssystems mit einem speziellen Treiber (CSI Driver) beschreibt, der mit einem bestimmten Speichersystem arbeitet. Der gesamte Code für die Interaktion mit dem Speichersystem wurde aus dem Kubernetes-Kernel in ein separates System ausgelagert.
.
In der Regel besteht der CSI Driver aus zwei Komponenten: Node Plugin und Controller Plugin.
Das Node-Plugin wird auf jedem Knoten gestartet und ist für das Mounten von Volumes sowie die Durchführung von Operationen darauf verantwortlich. Das Controller-Plugin kommuniziert mit dem SAN: Es erstellt oder löscht Volumes, weist Zugriffsrechte zu usw.
Im Kubernetes-Kernel bleiben weiterhin alte Treiber vorhanden, deren Nutzung jedoch nicht mehr empfohlen wird. Stattdessen wird jedem geraten, den CSI-Treiber speziell für das jeweilige System zu installieren, mit dem gearbeitet werden soll.
Diese Neuerung könnte diejenigen verunsichern, die bereits daran gewöhnt sind, die Datenspeicherung über die Storage-Klasse zu konfigurieren. In Wirklichkeit hat sich jedoch nichts Dramatisches geändert. Für Programmierer bleibt alles beim Alten – sie werden weiterhin nur mit dem Namen der Storage-Klasse arbeiten. Für Administratoren hingegen gibt es eine zusätzliche Helm-Chart-Installation und die Struktur der Einstellungen hat sich geändert. Früher wurden die Einstellungen direkt in der Storage-Klasse eingegeben, jetzt müssen sie zunächst in der Helm-Chart definiert und dann in der Storage-Klasse festgelegt werden. Bei genauerer Betrachtung ist jedoch nichts Schlimmes passiert.
Lassen Sie uns anhand eines Beispiels die Vorteile betrachten, die sich aus der Verbindung mit dem Ceph-SAN über den CSI-Treiber ergeben können.
Bei der Arbeit mit Ceph bietet das CSI-Plugin mehr Möglichkeiten für die Interaktion mit dem SAN als die integrierten Treiber.
- Dynamische Erstellung von Festplatten. In der Regel werden RBD-Platten nur im RWO-Modus verwendet, aber der CSI für Ceph ermöglicht deren Nutzung im RWX-Modus. Mehrere Pods auf verschiedenen Knoten können dasselbe RBD-Laufwerk an ihren Knoten bereitstellen und parallel damit arbeiten. Um fair zu sein, ist nicht alles so rosig — diese Festplatte kann nur als Blockgerät angeschlossen werden, was bedeutet, dass die Anwendung für den gleichzeitigen Zugriff darauf angepasst werden muss.
- Snapshots erstellen. In einem Kubernetes-Cluster kann ein Manifest erstellt werden, das die Anforderung zur Erstellung eines Snapshots enthält. Das CSI-Plugin erkennt dies und erstellt einen Snapshot von der Festplatte. Auf dieser Grundlage kann entweder ein Backup oder eine Kopie des PersistentVolume erstellt werden.
- Größe der Festplatte erhöhen. für SAN und PersistentVolume im Kubernetes-Cluster.
- Quotas. Die in Kubernetes integrierten CephFS-Treiber unterstützen keine Quotas, während neue CSI-Plugins mit dem aktuellen Ceph Nautilus Quotas für CephFS-Partitionen aktivieren können.
- Metriken. Das CSI-Plugin kann viele Metriken an Prometheus übermitteln, die zeigen, welche Volumes angeschlossen sind, welche Interaktionen stattfinden usw.
- Topology-aware. Ermöglicht die Angabe in den Manifesten, wie geografisch verteilt der Cluster ist, und vermeidet die Verbindung zu Pods, die in London mit einem in Amsterdam befindlichen Speichersystem gestartet wurden.
So verbinden Sie Ceph über CSI mit einem Kubernetes-Cluster, siehe . Sie können sich auch für den , der am 15. Oktober startet, anmelden.
Autor des Artikels: Sergey Bondarev, praktizierender Architekt bei Southbridge, Certified Kubernetes Administrator, einer der Entwickler von kubespray.
Ein kleines Post Scriptum, nicht zur Werbung, sondern zum Nutzen ...
P.S. Sergey Bondarev bietet zwei Intensivkurse an: aktualisiert 28.-30. September und fortgeschrittene vom 14. bis 16. Oktober.

Quelle: habr.com
