Das Storage-Management und die Virtualisierung der Speicherumgebung stehen im Mittelpunkt der November-Ausgabe des IT-Administrator. Denn längst sind die ... (mehr)

Etcd speichert Konfiguration

Als Backendspeicher setzt Kubernetes den etcd-Service ein. Hierbei handelt es sich um eine verteilte Key/Value-Datenbank. Diese hält Konfigurations- und Status-Informationen des Kubernetes-Clusters vor. Der kubelet-Service auf den einzelnen Nodes fragt diese Datenbank ständig nach Änderungen ab und führt bei Bedarf notwendige Aktionen aus. Beispielsweise enthält die Datenbank eine Liste sämtlicher Nodes eines OpenShift-Clusters. Diese Information verwendet der Master-Knoten, um zu entscheiden, auf welchen Hosts ein neuer Pod erzeugt werden kann. Damit der Master-Knoten keinen Single Point of failure darstellt, bietet es sich an, ihn als hochverfügbaren Service zu implementieren. Dies funktioniert beispielsweise mit der Cluster-Software Pacemaker oder HAProxy.

Bevor es an das Setup des Storage-Systems geht, ist ein Login auf dem Master-Knoten notwendig (»oc login« ) und, falls nicht bereits vorhanden, die Anlage eines neuen Projekts, für das der Storage zur Verfügung gestellt wird (»oc new-project Projektname« ). An dieser Stelle gehen wir davon aus, dass der Heketi-Service zuvor eingerichtet wurde und alle Gluster-Storage-Container bereitstehen [4].

Um nun das Storage-System vorzubereiten, ist es wichtig zu verstehen, dass Gluster alle exportierten Festplatten der Gluster Storage Nodes in Pools organisiert, die dann innerhalb eines Clusters zur Verfügung stehen. Aus diesen Pools lassen sich einzelne Storage-Blöcke, sogenannte Persistent Volumes (PVs), in einem Open­Shift-Projekt benutzen. Innerhalb von Pods werden dann Persistent Volume Claims (PVC) als persistenter Speicher verwendet. Persistent Volumes werden praktisch als Speicher im Netzwerk freigegeben und stellen, wie auch OpenShift-Nodes, eine Ressource dar, auf die Container zurückgreifen können. Kubernetes regelt diesen Zugriff über ein entsprechendes Vol-ume-Plugin. Benötigt ein Entwickler oder Administrator ein Volume aus diesem Speicher, findet die Anfrage nach diesem Volume mit Hilfe eines Persistent Volume Claim statt. Dies ist ähnlich wie bei einem Pod, der auf die einzelnen OpenShift-Nodes als Ressource zurückgreifen muss. Beim Speicher greifen die einzelnen Volume Claims auf die zuvor eingerichteten Persistent Volumes als Ressource zurück. Idealerweise werden mehrere solcher Persistent Volumes mit unterschiedlichen Performance-Eigenschaften angelegt. So lassen sich dann bei Anfragen nach einem Storage-Volume, den Volume Claims, die passenden Persistent Volumes aussuchen.

Wie zuvor erwähnt, werden die meisten Kubernetes-Objekte über JSON-Dateien beschrieben und dann mit dem Tool oc innerhalb der OpenShift-Umgebung definiert. Kubernetes benötigt als erstes Objekt einen Service für die Gluster Storage Nodes. Es abstrahiert vom Zugriff auf die einzelnen Nodes und ermöglicht einen transparenten Zugriff auf diese. Ein Kubernetes Service greift hierfür auf einen sogenannten Endpoint zurück. Um einen solchen zu definieren, verwenden Sie eine JSON-Datei wie in Listing 1. Die Datei steht auf einem Open-Shift-System auch unterhalb von "/usr/share/heketi/openshift/" zur Verfügung. Das OpenShift-Tool oc erzeugt aus der JSON-Datei ein entsprechendes Kubernetes-Objekt:

# oc create -f gluster-endpoint.json
endpoints "glusterfs-cluster" created

Ob dies geklappt hat, lässt sich ebenfalls mittels oc verifizieren (Listing 2).

Listing 2: Endpoints anzeigen



# oc get endpoints
NAME                                   ENDPOINTS                                                                                           AGE
storage-project-router          192.168.121.233:80,192.168.121.233:443,192.168.121.233:1936        2d
glusterfs-cluster                    192.168.121.101:1,192.168.121.102:1,192.168.121.103:1                    3s
heketi                                    10.1.1.3:8080                                                                                           2m
heketi-storage-endpoints      192.168.121.101:1,192.168.121.102:1,192.168.121.103:1                    3m

Auf Basis dieses Endpoints erzeugen Sie im nächsten Schritt den eigentlichen Service für diese Gluster Nodes. Auch hierfür ist eine JSON-Datei "gluster-service.json" notwendig:

{
    "kind": "Service","apiVersion": "v1", "metadata": {
       "name": "glusterfs-cluster"
    },
    "spec": {
    "ports": [
          {"port": 1}
       ]
    }
}

Im Anschluss erzeugen Sie den Service und verifizieren, dass keine Fehler aufgetreten sind (Listing 3). Um nun den GlusterFS-Speicher entsprechend dynamisch zu provisionieren, greifen Sie auf den Heketi-Service zurück. Er verfügt über ein eigenes Tool, mit dem Sie ein entsprechendes Volume innerhalb eines trusted Storage Pools erzeugen:

 

# heketi-cli volume create --size=100 --persistent-volume-file=pv01.json

Listing 3: Service verifizieren



# oc create -f gluster-service.json
service "glusterfs-cluster" created
# oc get service
NAME                                CLUSTER-IP     EXTERNAL-IP   PORT(S)                                    AGE
storage-project-router       172.30.94.109    <none>               80/TCP,443/TCP,1936/TCP    2d
glusterfs-cluster                 172.30.212.6      <none>                1/TCP                                      5s
heketi                                 172.30.175.7      <none>                8080/TCP                                2m
heketi-storage-endpoints   172.30.18.24      <none>                1/TCP                                      3m

Die Datei "pv01.json" muss dabei den Namen des zuvor eingerichteten Endpoints, die gewünschte Größe des Volumes und einen Namen für das Volume enthalten (Listing 4). Schließlich müssen Sie noch das Volume in Kubernetes einbinden und sicherstellen, dass dies fehlerfrei funktioniert hat (Listing 5).

Listing 4: pv01.json



{
"kind": "PersistentVolume",
"apiVersion": "v1",
"metadata": {
    "name": "glusterfs-1ba23e11", "creationTimestamp": null
},
"spec": {
    "capacity": {
    "storage": "100Gi"
    },
    "glusterfs": {
    "endpoints": "glusterfs-cluster", "path": "vol_1ba23e1134e531dec3830cfbcad1eeae"
    },
    "accessModes": [
    "ReadWriteMany"
    ],
    "persistentVolumeReclaimPolicy": "Retain"
},
"status": {}
}

Listing 5: Volumes einbinden



# oc create -f pv01.json
persistentvolume "glusterfs-1ba23e11" created
# oc get pv
NAME                        CAPACITY    ACCESSMODES    STATUS    CLAIM    REASON    AGE
glusterfs-1ba23e11    100Gi             RWX                       Available                                      4s

Aus diesem Storage-Block lässt sich nun ein Persistent Volume Claim (PVC) definieren. Diesen PVC geben Sie im nächsten Schritt beim Anlegen eines Pods als Speicher an:

{
    "apiVersion": "v1",
    "kind": "PersistentVolumeClaim",
    "metadata": {
       "name": "glusterfs-claim"
    },
    "spec": {
       "accessModes": [
          "ReadWriteMany"
       ],
       "resources": {
          "requests": {
            "storage": "10Gi"
          }
       }
    }
}

Mittels oc legen Sie den PVC an, der im Anschluss zur Verfügung stehen sollte (Listing 6). Schließlich folgt die Definition des eigentlichen Pods:

apiVersion: v1
kind: Pod
metadata:
    name: fedora
spec:
    containers:
       - image: fedora:latest
       volumeMounts:
         - mountPath: /data
             name: pvc01
    volumes:
       - name: pvc01
         persistentVolumeClaim:
             claimName: glusterfs-claim
 
# oc create -f fedora.yml
pod "fedora" created

Listing 6: PVC anlegen



# oc create -f pvc.json
persistentvolumeclaim "glusterfs-claim" created
# oc get pvc
NAME                  STATUS     VOLUME                  CAPACITY    ACCESSMODES     AGE
glusterfs-claim     Bound         glusterfs-1ba23e11    100Gi            RWX                         11s

Dieser Pool umfasst ediglich einen einzelnen Container, der auf Basis des Fedora-Container-Images erzeugt wurde. Der Abschnitt "volumes" referenziert den zuvor eingerichteten Speicher über dessen Namen und versieht ihn mit einem Volumen-Namen. Der wird im Abschnitt "volumeMounts" wiederum dazu verwendet, das Volume an einen bestimmten Mountpoint zu binden.

Innerhalb des Pods steht nun der Speicher, der innerhalb des Persistent Storage Claims angefordert wurde, unterhalb des Mountpoints "/data" zur Verfügung. Da der Speicher aus dem Gluster-Storage-Pool geliefert wird, ist er somit unabhängig von dem Node, auf dem der Pod läuft, vorhanden und natürlich auch nicht an den Lifecycle des Pods gebunden. Er ist auch nach dem Beenden des Pods zum Einsatz bereit.

Fazit

Mit der Möglichkeit, Persistent Storage für Container zur Verfügung zu stellen und somit Daten unabhängig von der Lebenszeit eines Containers zu erhalten, wird ein weiterer Schritt in die richtige Richtung gemacht. Dieser wird sicherlich dazu beitragen, dass Container weiteren Einzug in Enterprise-Umgebungen erhalten.

Wer sich nicht an die Red-Hat-eigene PaaS-Lösung OpenShift binden möchte, dem steht natürlich frei, die Kombination aus Gluster-Storage, Docker und Kubernetes selbständig zu implementieren, was aber natürlich einiges an zusätzlichem Aufwand bedeutet. Dies betrifft gerade die Integration in Entwicklungsumgebungen, da diese nicht alleine durch die genannten Tools zur Verfügung gestellt wird.

(of)

Link-Codes

[1] Torus Distributed Storage für Container: https://coreos.com/blog/torus-distributed-storage-by-coreos.html/

[2] Red Hat OpenShift Container Platform: https://www.openshift.com/container-platform/

[3] OpenShift-Installation: https://access.redhat.com/documentation/en/openshift-enterprise/3.2/installation-and-configuration/installation-and-configuration/

[4] OpenShift hyper-converged Storage Setup: https://access.redhat.com/documentation/en/red-hat-gluster-storage/3.1/paged/deployment-guide-for-containerized-red-hat-gluster-storage-in-openshift-enterprise/chapter-4-setting-up-the-environment/

comments powered by Disqus
Mehr zum Thema

Kubernetes-Distribution OpenShift (2)

Zustandslose Anwendungen auf Container-Plattformen wie Kubernetes und OpenShift zu betreiben, ist vergleichsweise einfach. Deutlich komplizierter wird es mit stateful Apps, die persistenten Speicher benötigen. Im zweiten Teil des OpenShift-Workshops stellen wir Lösungsansätze vor und zeigen, wie Sie eine Datenbank im OpenShift-Cluster installieren.

Artikel der Woche

Eigene Registry für Docker-Images

Wer selber Docker-Images herstellt, braucht auch eine eigene Registry. Diese gibt es ebenfalls als Docker-Image, aber nur mit eingeschränkter Funktionalität. Mit einem Auth-Server wird daraus ein brauchbares Repository für Images. (mehr)
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Ausgabe /2021