Datenspeicherung im Kubernetes-Cluster

Die Speicherung von Anwendungsdaten für in einem Kubernetes-Cluster ausgeführte Anwendungen kann auf verschiedene Arten konfiguriert werden. Einige davon sind bereits veraltet, andere sind neu hinzugekommen. In diesem Artikel betrachten wir das Konzept der drei Verbindungsmöglichkeiten zu Speicher-Arrays, einschließlich der neuesten – der Verbindung über die Container Storage Interface.

Datenspeicherung im Kubernetes-Cluster

Methode 1. Angabe von PV im Pod-Manifest

Ein typisches Manifest, das einen Pod im Kubernetes-Cluster beschreibt:

Datenspeicherung im Kubernetes-Cluster

Die Teile des Manifests, die beschreiben, welcher Volume verbunden wird und wo, sind farblich hervorgehoben.

Im Abschnitt volumeMounts geben die Mount-Punkte (mountPath) an – in welches Verzeichnis innerhalb des Containers das persistente Volume eingebunden wird, sowie den Namen des Volumes an.

Im Abschnitt x listen alle Volumes auf, die im Pod verwendet werden. Sie geben den Namen jedes Volumes an, sowie den Typ (in unserem Fall: awsElasticBlockStore) und die Verbindungsparameter. Welche Parameter im Manifest angegeben werden, hängt vom Typ des Volumes ab.

Das gleiche Volume kann gleichzeitig in mehreren Containern des Pods eingebunden werden. Auf diese Weise können verschiedene Anwendungsprozesse auf dieselben Daten zugreifen.

Diese Verbindungsmethode wurde ursprünglich zu Beginn von Kubernetes entwickelt und ist mittlerweile veraltet.

Bei der Verwendung entstehen mehrere Probleme:

  1. alle Volumes müssen manuell erstellt werden, Kubernetes kann nichts für uns erstellen;
  2. die Zugangsparameter zu jedem Volume sind einzigartig und müssen in den Manifesten aller Pods angegeben werden, die das Volume verwenden;
  3. um das Speichersystem zu ändern (zum Beispiel von AWS zu Google Cloud zu wechseln), müssen die Einstellungen und der Typ der angeschlossenen Volumes in allen Manifesten angepasst werden.

All dies ist sehr unpraktisch, weshalb diese Methode in der Realität nur für einige spezielle Volumen-Typen verwendet wird: configMap, secret, emptyDir, hostPath:

  • configMap und secret – Dienstvolumen, die es ermöglichen, in einem Container ein Volume mit Dateien aus den Kubernetes-Manifests zu erstellen.

  • emptyDir – ein temporäres Volume, das nur für die Lebensdauer des Pods erstellt wird. Es ist nützlich für Tests oder zur Speicherung temporärer Daten. Wenn der Pod gelöscht wird, wird auch das Volume vom Typ emptyDir gelöscht und alle Daten gehen verloren.

  • hostPath — ermöglicht es, ein beliebiges Verzeichnis des lokalen Servers, auf dem die Anwendung läuft, in den Container einzubinden, einschließlich /etc/kubernetes. Diese Möglichkeit ist unsicher, weshalb Sicherheitsrichtlinien in der Regel die Verwendung solcher Volumes verbieten. Andernfalls könnte ein Angreifer in der Lage sein, das Verzeichnis HTC Kubernetes in seinen Container einzubinden und alle Zertifikate des Clusters zu stehlen. In der Regel dürfen nur systemeigene Anwendungen, die im Namespace kube-system ausgeführt werden, hostPath-Volumes verwenden.

Speichersysteme, mit denen Kubernetes von Haus aus arbeitet sind in der Dokumentation aufgeführt.

Methode 2: Verbindung zu Pods SC/PVC/PV

Eine alternative Verbindungsmethode ist das Konzept Storage Class, PersistentVolumeClaim, PersistentVolume.

Storage Class speichert die Verbindungsparameter zum Speichersystem.

PersistentVolumeClaim beschreibt die Anforderungen an das Volume, das für die Anwendung benötigt wird.
PersistentVolume speichert die Zugriffsparameter und den Status des Volumes.

Der Kern der Idee: Im Pod-Manifest wird ein Volume des Typs PersistentVolumeClaim angegeben und der Name dieser Entität im Parameter claimName angegeben.

Datenspeicherung im Kubernetes-Cluster

Im Manifest des PersistentVolumeClaim werden die Anforderungen an das Daten-Volume beschrieben, das für die Anwendung erforderlich ist. Dazu gehören:

  • Größe des Festplattenspeichers;
  • Zugriffsart: ReadWriteOnce oder ReadWriteMany;
  • Verweis auf die Storage Class — in welchem Speichersystem wir das Volume erstellen möchten.

Im Manifest der Storage Class werden der Typ und die Verbindungsparameter zum Speichersystem gespeichert. Diese werden vom Kubelet benötigt, um das Volume an seinen Knoten zu mounten.

In den Manifests der PersistentVolumes wird die Storage Class und die Zugriffsparameter für ein bestimmtes Volume (ID des Volumes, Pfad usw.) angegeben.

Bei der Erstellung eines PVC schaut Kubernetes, welches Volumen in welcher Größe und aus welcher Storage Class benötigt wird, und wählt ein freies PersistentVolume aus.

Wenn solche PVs nicht verfügbar sind, kann Kubernetes ein spezielles Programm starten — Provisioner (dessen Name in der Storage Class angegeben wird). Dieses Programm verbindet sich mit dem Speichersystem, erstellt ein Volume der gewünschten Größe, erhält die ID und erstellt im Kubernetes-Cluster ein Manifest des PersistentVolumes, das mit dem PersistentVolumeClaim verknüpft ist.

All diese vielen Abstraktionen ermöglichen 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. Alles, was bei einem Umzug von AWS zu Google Cloud getan werden muss, besteht darin, in den Anwendungsmanifests den Namen der Storage-Klasse im PVC zu ändern. Die Persistenzvolumen zur Datenspeicherung werden automatisch im Cluster mit Hilfe des Provisioners erstellt.

Methode 3. Container Storage Interface

Der gesamte Code, der mit verschiedenen Speichersystemen interagiert, ist Teil des Kubernetes-Kerns. Die Veröffentlichung von Bugfixes oder neuen Funktionen ist an neue Releases gebunden, und der Code muss für alle unterstützten Versionen von Kubernetes geändert werden. All dies ist schwer wartbar und es ist schwierig, 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 zwischen dem Container-Orchestrator und dem speziellen Treiber (CSI Driver), der mit einem bestimmten Speichersystem arbeitet, beschreibt. Der gesamte Code zur Interaktion mit dem Speichersystem wurde aus dem Kubernetes-Kern in ein separates System ausgelagert.

Dokumentation zum Container Storage Interface.

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 Einhängen der Volumes und deren Operationen verantwortlich. Der Controller Plugin interagiert mit dem Speichersystem: Er erstellt oder löscht Volumes, weist Zugriffsrechte zu usw.

Während im Kubernetes-Kern alte Treiber verbleiben, wird deren Nutzung nicht mehr empfohlen, und allen wird geraten, den CSI Driver konkret für das System zu installieren, mit dem gearbeitet werden soll.

Diese Neuerung kann diejenigen erschrecken, die bereits daran gewöhnt sind, die Datenspeicherung über die Storage-Klasse zu konfigurieren, aber eigentlich ist nichts Schlimmes geschehen. Für Programmierer ändert sich genau genommen nichts – sie arbeiten weiterhin nur mit dem Namen der Storage-Klasse. Für Administratoren ist die Installation des Helm-Charts hinzugekommen und die Struktur der Einstellungen hat sich verändert. Früher wurden die Einstellungen direkt in die Storage-Klasse eingegeben, jetzt müssen sie zunächst im Helm-Chart festgelegt und dann in der Storage-Klasse eingetragen werden. Wenn man es genau betrachtet, ist nichts Schlimmes passiert.

Lassen Sie uns anhand eines Beispiels betrachten, welche Vorteile man durch den Wechsel zur Anbindung an das Ceph-Speichersystem mit Hilfe des CSI-Treibers erzielen kann.

Bei der Arbeit mit Ceph bietet das CSI-Plugin mehr Möglichkeiten zur Interaktion mit dem Speichersystem als die eingebauten Treiber.

  1. Dynamische Erstellung von Festplatten. In der Regel werden RBD-Disks nur im RWO-Modus verwendet, während CSI für Ceph es ermöglicht, sie im RWX-Modus zu verwenden. Mehrere Pods auf verschiedenen Knoten können dasselbe RDB-Laufwerk einbinden und parallel damit arbeiten. Um fair zu sein, ist nicht alles so strahlend — diese Festplatte kann nur als Blockgerät angeschlossen werden, was bedeutet, dass die Anwendung angepasst werden muss, um im Modus des gemeinsamen Zugriffs damit zu arbeiten.
  2. Snapshots erstellen. In einem Kubernetes-Cluster kann ein Manifest erstellt werden, das die Anforderung zum Erstellen eines Snapshots enthält. Das CSI-Plugin erkennt dies und erstellt einen Snapshot von der Festplatte. Darauf basierend kann entweder ein Backup oder eine Kopie des PersistentVolume erstellt werden.
  3. Erhöhung der Festplattengröße auf Storage-Arrays und PersistentVolumes im Kubernetes-Cluster.
  4. Quoten. Die in Kubernetes eingebauten CephFS-Treiber unterstützen keine Quoten, während die neuen CSI-Plugins mit der neuen Ceph Nautilus-Version Quoten für CephFS-Partitionen aktivieren können.
  5. Metriken. Das CSI-Plugin kann Prometheus zahlreiche Metriken über die angeschlossenen Volumes, Interaktionen usw. bereitstellen.
  6. Topology aware. Ermöglicht es, in den Manifests anzugeben, wie geografisch verteilt der Cluster ist, und zu vermeiden, dass Pods, die mit einem in London ansässigen Speichersystem verbunden sind, auf ein Speichersystem zugreifen, das sich in Amsterdam befindet.

Wie man Ceph über CSI an ein Kubernetes-Cluster anschließt, sehen Sie im praktischen Teil der Abendvorlesung von Sljörm. Ebenso kann man sich für den Ceph-Videokursanmelden, der am 15. Oktober beginnt.

Autor des Artikels: Sergej Bondarev, praktizierender Architekt bei Southbridge, Certified Kubernetes Administrator, einer der Entwickler von kubespray.

Ein kleines Post Scriptum, nicht aus Werbung, sondern zum Nutzen...

P.S. Sergej Bondarev leitet zwei Intensivkurse: den aktualisierten Kubernetes Basis 28.-30. September und den fortgeschrittenen Kubernetes Mega vom 14. bis 16. Oktober.

Datenspeicherung im Kubernetes-Cluster

Quelle: habr.com

60GB SSD 8Gb DDR4