Volumes-Plugins für Speicher in Kubernetes: von Flexvolume zu CSI

Volumes-Plugins für Speicher in Kubernetes: von Flexvolume zu CSI

Als Kubernetes noch in der Version v1.0.0 war, gab es Volume-Plugins. Diese waren notwendig, um Kubernetes mit Systemen zur Speicherung von persistenten (dauerhaften) Daten der Container zu verbinden. Ihre Anzahl war nicht groß, und zu den ersten gehörten Anbieter wie GCE PD, Ceph, AWS EBS und andere.

Die Plugins wurden zusammen mit Kubernetes bereitgestellt, weshalb sie den Namen „in-tree“ erhielten. Allerdings war vielen der bestehende Satz solcher Plugins nicht ausreichend. Tüftler fügten einfache Plugins in den Kubernetes-Kernel mithilfe von Patches ein, sammelten dann ihren eigenen Kubernetes und installierten ihn auf ihren Servern. Mit der Zeit erkannten die Entwickler von Kubernetes jedoch, dass man das Problem nicht mit einem Quick-Fix lösen kann. Die Menschen brauchen eine Angel . Und mit der Veröffentlichung von Kubernetes v1.2.0 wurde sie eingeführt...Flexvolume-Plugin: Die einfache Angel

Die Entwickler von Kubernetes haben das Plugin FlexVolume erstellt, das eine logische Hülle aus Variablen und Methoden für die Arbeit mit von Dritten entwickelten Flexvolume-Treibern darstellt.

Lassen Sie uns anhalten und genauer betrachten, was einen FlexVolume-Treiber ausmacht. Dies ist eine Art

ausführbare Datei (Binärdatei, Python-Skript, Bash-Skript usw.), die beim Ausführen Argumente von der Befehlszeile entgegennimmt und eine Nachricht mit vorab bekannten Feldern im JSON-Format zurückgibt. Das erste Argument der Befehlszeile ist gemäß Konvention immer die Methode, während die restlichen Argumente deren Parameter sind. Schema zum Anschluss von CIFS Shares in OpenShift. Flexvolume-Treiber — genau in der Mitte

Volumes-Plugins für Speicher in Kubernetes: von Flexvolume zu CSI
Minimal erforderliche Methoden

flexvolume_driver mount # Verantwortlich für das Anbinden des Volumes an den Pod # Format der zurückgegebenen Nachricht: { "status": "Success"/"Failure"/"Not supported", "message": "Aus welchem Grund wurde genau dieser Status zurückgegeben", }flexvolume_driver unmount # Verantwortlich für das Abmounten des Volumes vom Pod # Format der zurückgegebenen Nachricht: { "status": "Success"/"Failure"/"Not supported", "message": "Aus welchem Grund wurde genau dieser Status zurückgegeben", }flexvolume_driver init # Verantwortlich für die Initialisierung des Plugins # Format der zurückgegebenen Nachricht: { "status": "Success"/"Failure"/"Not supported", "message": "Aus welchem Grund wurde genau dieser Status zurückgegeben", // Bestimmt, ob der Treiber die Methoden attach/deatach verwendet "capabilities":{"attach": True/False} } sieht so aus:

Verwendung der Methoden

attach detach und detach bestimmt das Szenario, nach dem kubelet zukünftig beim Aufruf des Treibers handeln wird. Es gibt auch spezielle Methoden expandvolume und expandfs, die für die dynamische Größenänderung von Volumes verantwortlich sind.

Ein Beispiel für die Änderungen, die die Methode expandvolume, sowie die Möglichkeit, Volumes in Echtzeit zu vergrößern, einführt, finden Sie in unserem Pull-Request im Rook Ceph Operator.

Hier ist ein Beispiel für die Implementierung eines Flexvolume-Treibers zur Arbeit mit NFS:

usage() {
    err "Ungültige Verwendung. Verwendung: "
    err "t$0 init"
    err "t$0 mount  "
    err "t$0 unmount "
    exit 1
}

err() {
    echo -ne $* 1>&2
}

log() {
    echo -ne $* >&1
}

ismounted() {
    MOUNT=`findmnt -n ${MNTPATH} 2>/dev/null | cut -d' ' -f1`
    if [ "${MOUNT}" == "${MNTPATH}" ]; then
        echo "1"
    else
        echo "0"
    fi
}

domount() {
    MNTPATH=$1

    NFS_SERVER=$(echo $2 | jq -r '.server')
    SHARE=$(echo $2 | jq -r '.share')

    if [ $(ismounted) -eq 1 ] ; then
        log '{"status": "Erfolg"}'
        exit 0
    fi

    mkdir -p ${MNTPATH} >& /dev/null

    mount -t nfs ${NFS_SERVER}:/${SHARE} ${MNTPATH} >& /dev/null
    if [ $? -ne 0 ]; then
        err "{ "status": "Fehler", "message": "Fehler beim Einhängen von ${NFS_SERVER}:${SHARE} bei ${MNTPATH}"}"
        exit 1
    fi
    log '{"status": "Erfolg"}'
    exit 0
}

unmount() {
    MNTPATH=$1
    if [ $(ismounted) -eq 0 ] ; then
        log '{"status": "Erfolg"}'
        exit 0
    fi

    umount ${MNTPATH} >& /dev/null
    if [ $? -ne 0 ]; then
        err "{ "status": "Fehlgeschlagen", "message": "Fehler beim Unmounten des Volumes bei ${MNTPATH}"}"
        exit 1
    fi

    log '{"status": "Erfolg"}'
    exit 0
}

op=$1

if [ "$op" = "init" ]; then
    log '{"status": "Erfolg", "capabilities": {"attach": false}}'
    exit 0
fi

if [ $# -lt 2 ]; then
    usage
fi

shift

case "$op" in
    mount)
        domount $*
        ;;
    unmount)
        unmount $*
        ;;
    *)
        log '{"status": "Nicht unterstützt"}'
        exit 0
esac

exit 1

Nachdem die ausführbare Datei vorbereitet wurde, müssen Sie den Treiber im Kubernetes-Cluster bereitstellen . Der Treiber muss sich auf jedem Knoten des Clusters an einem zuvor festgelegten Pfad befinden. Standardmäßig wurde gewählt:… aber bei Verwendung verschiedener Kubernetes-Distributionen (OpenShift, Rancher…) kann der Pfad anders sein.

/usr/libexec/kubernetes/kubelet-plugins/volume/exec/имя_поставщика_хранилища~имя_драйвера/

Flexvolume-Probleme: Wie wirft man die Angel richtig aus?

Es stellte sich als eine nicht triviale Aufgabe heraus, den Flexvolume-Treiber auf den Knoten des Clusters bereitzustellen. Nachdem Sie den Vorgang einmal manuell durchgeführt haben, können Sie leicht mit der Situation konfrontiert werden, dass im Cluster neue Knoten erscheinen: aufgrund der Hinzufügung eines neuen Knotens, der automatischen horizontalen Skalierung oder — noch schlimmer — der Ersetzung eines Knotens aufgrund eines Fehlers. In diesem Fall kann die Arbeit mit dem Speicher auf diesen Knoten erfolgen

, solange Sie nicht weiterhin manuell den Flexvolume-Treiber auf ihnen hinzufügen. nicht möglich ist, solange Sie nicht weiterhin manuell den Flexvolume-Treiber darauf hinzufügen.

Die Lösung dieses Problems war einer der Primitive von Kubernetes — DaemonSet. Wenn ein neuer Knoten im Cluster erscheint, wird automatisch ein Pod aus unserem DaemonSet darauf platziert, zu dem ein lokales Volume im Pfad zur Auffindung der Flexvolume-Treiber hinzukommt. Bei erfolgreicher Erstellung kopiert der Pod die erforderlichen Dateien für die Arbeit des Treibers auf die Festplatte.

Hier ist ein Beispiel für ein solches DaemonSet zur Bereitstellung des Flexvolume-Plugins:

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: flex-set
spec:
  template:
    metadata:
      name: flex-deploy
      labels:
        app: flex-deploy
    spec:
      containers:
        - image: 
          name: flex-deploy
          securityContext:
              privileged: true
          volumeMounts:
            - mountPath: /flexmnt
              name: flexvolume-mount
      volumes:
        - name: flexvolume-mount
          hostPath:
            path:

… und ein Beispiel für ein Bash-Skript zur Bereitstellung des Flexvolume-Treibers:

#!/bin/sh

set -o errexit
set -o pipefail

VENDOR=k8s.io
DRIVER=nfs

driver_dir=$VENDOR${VENDOR:+"~"}${DRIVER}
if [ ! -d "/flexmnt/$driver_dir" ]; then
  mkdir "/flexmnt/$driver_dir"
fi

cp "/$DRIVER" "/flexmnt/$driver_dir/.$DRIVER"
mv -f "/flexmnt/$driver_dir/.$DRIVER" "/flexmnt/$driver_dir/$DRIVER"

while : ; do
  sleep 3600
done

Es ist wichtig, nicht zu vergessen, dass der Kopiervorgang nicht atomar ist. Es besteht eine hohe Wahrscheinlichkeit, dass kubelet den Treiber verwendet, bevor der Vorbereitungsprozess abgeschlossen ist, was zu einem Fehler im System führen kann. Der richtige Ansatz wäre, zunächst die Treiberdateien unter einem anderen Namen zu kopieren und anschließend eine atomare Umbenennungsoperation durchzuführen.

Volumes-Plugins für Speicher in Kubernetes: von Flexvolume zu CSI
Der Ablauf zur Zusammenarbeit mit Ceph im Rook-Operator: Der Flexvolume-Treiber befindet sich im Ablauf innerhalb des Rook-Agenten

Ein weiteres Problem bei der Verwendung von Flexvolume-Treibern besteht darin, dass die erforderliche Software für die meisten Speicherlösungen auf dem Clusterknoten installiert sein muss (zum Beispiel das Paket ceph-common für Ceph). Ursprünglich war das Flexvolume-Plugin nicht für die Implementierung so komplexer Systeme gedacht.

Die ursprüngliche Lösung für dieses Problem ist in der Implementierung des Flexvolume-Treibers des Rook-Operators zu sehen:

Der Treiber selbst wird als RPC-Client umgesetzt. Der IPC-Socket für die Kommunikation liegt im selben Verzeichnis wie der Treiber selbst. Wir erinnern uns, dass es sinnvoll wäre, DaemonSet zum Kopieren der Treiberdateien zu verwenden, das ein Volume verbindet, das auf das Verzeichnis mit dem Treiber zeigt. Nach der Kopie der erforderlichen Treiberdateien stirbt dieser Pod nicht, sondern verbindet sich als vollständiger RPC-Server über das verbundene Volume mit dem IPC-Socket. Das Paket ceph-common ist bereits innerhalb des Pod-Containers installiert. Der IPC-Socket gibt die Gewissheit, dass kubelet mit genau dem Pod kommuniziert, der sich auf demselben Knoten befindet. Genial einfach!..

Auf Wiedersehen, unsere lieben… in-tree Plugins!

Die Entwickler von Kubernetes haben festgestellt, dass die Anzahl der Speicher-Plugins im Kernel zwanzig beträgt. Und jede Änderung in jedem dieser Plugins durchläuft in irgendeiner Weise den vollständigen Release-Zyklus von Kubernetes.

Es stellt sich heraus, dass, um die neue Version des Speicher-Plugins zu verwenden, der gesamte Cluster aktualisiert werden muss. Darüber hinaus könnten Sie überrascht sein, dass die neue Version von Kubernetes plötzlich mit dem verwendeten Linux-Kernel inkompatibel wird… Daher wischen Sie sich die Tränen ab und kämpfen mit den Zähnen, um die Zeit für das Upgrade des Linux-Kernels und des Kubernetes-Clusters mit Ihrem Management und den Benutzern abzustimmen. Mit möglichen Ausfallzeiten bei der Bereitstellung von Diensten.

Die Situation ist mehr als komisch, finden Sie nicht? Der gesamten Community wurde klar, dass dieser Ansatz nicht funktioniert. Mit einem kraftvollen Beschluss geben die Kubernetes-Entwickler bekannt, dass neue Plugins zur Arbeit mit Speichern nicht mehr in den Kernel aufgenommen werden. Zudem wurden, wie wir bereits wissen, bei der Implementierung des Flexvolume-Plugins eine Reihe von Mängeln festgestellt…

Um die Frage nach persistente Datenspeichern einmal für alle zu klären, wurde das zuletzt hinzugefügte Plugin für Volumes in Kubernetes — CSI — ins Leben gerufen. Seine Alpha-Version, die vollständiger als Out-of-Tree CSI Volume Plugins bezeichnet wird, wurde mit der Veröffentlichung angekündigt Kubernetes 1.9.

Container Storage Interface, oder Spinning CSI 3000!

Zunächst möchte ich betonen, dass CSI kein einfaches Volume-Plugin ist, sondern ein echtes Standard zum Erstellen benutzerdefinierter Komponenten für die Arbeit mit Datenspeichern. Es war vorgesehen, dass Orchestrierungssysteme wie Kubernetes und Mesos lernen sollten, mit Komponenten zu arbeiten, die gemäß diesem Standard implementiert sind. Und Kubernetes hat bereits gelernt.

Wie sieht der CSI-Plugin in Kubernetes aus? Der CSI-Plugin arbeitet mit speziellen Treibern (CSI-Treibern), die von Drittentwicklern geschrieben wurden. Der CSI-Treiber in Kubernetes muss minimal aus zwei Komponenten (Pods) bestehen:

  • Controller — verwaltet externe persistente Speicher. Wird in Form eines gRPC-Servers veröffentlicht, für den das Primitive verwendet wird StatefulSet.
  • Node — ist verantwortlich für das Einhängen der persistente Speicher an die Cluster-Knoten. Wird ebenfalls in Form eines gRPC-Servers implementiert, aber für den wird das Primitive verwendet DaemonSet.

Volumes-Plugins für Speicher in Kubernetes: von Flexvolume zu CSI
Das Funktionsschema des CSI-Plugins in Kubernetes

Über einige andere Details der Arbeit von CSI können Sie beispielsweise aus dem Artikel «Understanding the CSI», dessen Übersetzung wir vor einem Jahr veröffentlicht haben.

Die Vorteile dieser Implementierung

  • Für grundlegende Dinge – zum Beispiel zur Registrierung eines Treibers für einen Knoten – haben die Entwickler von Kubernetes eine Reihe von Containern implementiert. Es ist nicht mehr nötig, die JSON-Antwort mit den capabilities selbst zu erstellen, wie es für das Flexvolume-Plugin der Fall war.
  • Anstelle von „Reinlegen“ ausführbarer Dateien auf Knoten stellen wir jetzt Pods im Cluster bereit. Das ist genau das, was wir von Kubernetes erwarten: Alle Prozesse finden innerhalb von Containern statt, die mit den Primitive von Kubernetes bereitgestellt werden.
  • Für die Implementierung komplexer Treiber ist es nicht mehr notwendig, einen RPC-Server und einen RPC-Client zu entwickeln. Der Client wurde von den Entwicklern von Kubernetes für uns realisiert.
  • Die Übergabe von Argumenten zur Arbeit mit dem gRPC-Protokoll ist viel bequemer, flexibler und zuverlässiger als die Übergabe über Befehlszeilenargumente. Um zu verstehen, wie man CSI Unterstützung für Metriken zur Nutzung des Volumes durch Hinzufügen einer standardisierten gRPC-Methode integrieren kann, kann man sich anschauen unserem Pull-Request für den Treiber vsphere-csi.
  • Die Kommunikation erfolgt über IPC-Sockets, damit man nicht durcheinandergerät, an welchen Pod kubelet die Anfrage gesendet hat.

Kommt Ihnen diese Liste bekannt vor? Die Vorteile von CSI sind die Lösung genau dieser Probleme, die bei der Entwicklung des Flexvolume-Plugins nicht berücksichtigt wurden.

Das DBMS Tarantool ist ein attraktives, zukunftsträchtiges Produkt zur Erstellung von hochbelasteten Anwendungen.

CSI als Standard für die Implementierung von benutzerdefinierten Plugins zur Interaktion mit Datenspeichern wurde von der Gemeinschaft sehr positiv aufgenommen. Darüber hinaus werden aufgrund seiner Vorteile und Vielseitigkeit sogar CSI-Treiber für Datenspeicher wie Ceph oder AWS EBS entwickelt, für die Plugins bereits in der allerersten Version von Kubernetes hinzugefügt wurden.

Anfang 2019 wurden In-Tree-Plugins als veraltet erklärt. Es ist geplant, die Unterstützung für das Flexvolume-Plugin aufrechtzuerhalten, jedoch wird es keine weiteren funktionalen Erweiterungen dafür geben.

Wir haben bereits Erfahrungen mit ceph-csi, vsphere-csi gesammelt und sind bereit, diese Liste zu erweitern! Bisher bewältigt CSI die ihm übertragenen Aufgaben hervorragend, und wir werden sehen, was die Zukunft bringt.

Vergessen Sie nicht, dass alles Neue gut überdachtes Altes ist!

P.S.

Lesen Sie auch in unserem Blog:

Quelle: habr.com

60GB SSD 8Gb DDR4