Longhorn Storage

Longhorn is an official CNCF project that delivers a powerful cloud-native distributed storage platform for Kubernetes

Met Rancher Longhorn is het eenvoudig om storage toe te voegen aan Kubernetes. De installatie geschiedt via de “Apps & Marketplace” in de Rancher manager en in de Charts kan Longhorn gekozen worden.

Instellingen kunnen eventueel aangepast worden via ‘Customize Helm options before install‘ en via ‘Edit YAML‘.

Storage worker-nodes

Het aanmaken van de default-disk kan geconfigureerd worden. Om ervoor te zorgen dat alleen nodes gebruikt worden die voorzien zijn van de juiste labels en annotations, is er de ‘createDefaultDiskLabeledNode‘ optie die op ‘true‘ dient te staan.

Vervolgens is een label ‘node.longhorn.io/create-default-disk‘ nodig. Als de waarde ‘true‘ is zal het path vanuit de settings.default-data-path gebruik worden, een waarde ‘config‘ zal zoeken naar de annotation ‘node.longhorn.io/default-disks-config‘. Hierin kunnen opties aangegeven worden (in JSON formaat), bv:

[
  {
    "path":"/longhorn",
    "allowScheduling":true
  }
]

Dedicated Nodes

Een data_locality-label geeft aan dat er gebruik gemaakt wordt van Longhorn volumes op dezelfde node als de pod die het volume gebruikt. Het wordt aangegeven met een parameter in de storageClass ‘dataLocality: best-effortvoor de volumes en met een label op de node ‘node.longhorn.io/data_locality:true‘.

Exclusive storage nodes

Om een node exclusief te gebruiken voor de storage kan een taint op de (storage)worker node geplaatst worden. Bijvoorbeeld: ‘nodetype=storage:NoSchedule‘ waardoor er geen andere workloads op deze node gebruikt gaan worden.

Zie de de referentie voor Longhorn opties voor meer uitleg over de mogelijkheden.

Na de installatie zal er een StorageClass zijn aangemaakt met de naam ‘longhorn‘.

Hoe werkt het?

bron: longhorn.io

.De Longhorn Manager pod draait op elke worker-node als een DaemonSet en is verantwoordelijk voor het aanmaken en beheren van de volumes binnen het Kubernetes cluster. Zodra een volume aangemaakt wordt, zal Longhorn op elke worker-node die Schedulable is, een replica aanmaken.

De Longhorn Engine draait altijd op dezelfde node waar de pod op is deployed en zal zorgen dat het volume gesynchroniseerd wordt over de replicas op de aanwezige ‘schedulable’ worker-nodes.

In de afbeelding hierboven:

  • Er zijn 3 pods met Longhorn volumes
  • Elk volume heeft een ‘dedicated’ controller, de Longhorn Engine
  • Er zijn 2 nodes met Longhorn storage
  • Elke Longhorn volume heeft 2 replicas
  • De pijlen in de afbeelding geven aan hoe de read/write flows lopen
  • Met een Longhorn Engine voor elk volume blijft de data beschikbaar, ook als een controller faalt.

CSI driver

De Longhorn CSI driver formatteert het block-device en mount het in de node. De kubelet ‘bind-mount‘ vervolgens het device in de Kubernetes pod zodat deze het volume kan gebruiken.

Longhorn UI

De Longhorn User-interface is de toegang naar de Longhorn Manager en communiceert met de API. Met de Longhorn UI is het mogelijk om snapshots en backups te maken en nodes en disks te beheren. Het ‘Dashboard‘:

In ‘Nodes‘ wordt een overzicht getoond van de nodes en welke daarvan gebruikt kunnen worden voor storage (Schedulable).

Via ‘Volumes‘ worden de PVC’s en de status getoond:

Meer details over een PVC kan verkregen worden door één van de getoonde PVC’s te kiezen. Ook kan hier via Operation o.a. de ‘replicas-count‘ aangepast worden als dat afwijkt van de default.

Longhorn is een ‘thin-provisioned‘ storage systeem en zal daardoor alleen de ruimte innemen die daadwerkelijk in gebruik is. Dus een volume van 5Gi dat alleen 262Mi in gebruik heeft zal een grootte hebben van 262Mi. Dit zie je terug in de details van een volume.(Size versus Actual Size)

Indien de gebruikte ruimte in een volume kleiner wordt zal de gebruikte ruimte NIET kleiner worden aangezien een block-storage-device niets weet over de aanwezigheid van bestanden zoals een filesystem storage. Dus een volume van 10Gi waarin de 2Gi teruggaat naar 1Gi zal nog steeds 2Gi in grootte blijven.

Replicas

Een replica bevat de snapshots van een volume en deze snapshots zijn layers zoals ook in een image en de oudste snapshot is de base-layer. Nieuwere snapshots komen daar bovenop en bevatten de wijzigingen t.o.v. de onderliggende snapshot. Meerde replicas bestaan in een cluster en zijn verdeeld over de nodes.


Ter lering ende vermaeck, een mysql deployment met PV op Longhorn.

Longhorn bestaat in dit geval uit een standaard installatie met 2 worker-nodes met storage enabled en een replica-count van 2.

De Persistent Volume (mysql-pv.yml):

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
  labels:
    name: mysql-data
    type: longhorn
spec:
  capacity:
    storage: 5G
  volumeMode: Filesystem
  storageClassName: longhorn
  accessModes:
    - ReadWriteOnce
  csi:
    driver: io.rancher.longhorn
    fsType: ext4
    volumeAttributes:
      numberOfReplicates: '2'
      staleReplicaTimeout: '20'
    volumeHandle: mysql-data

De Persistent Volume Claim: (mysql-pvc.yml)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    type: longhorn
    app: example
spec:
  storageClassName: longhorn
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

De Deployment: (mysql-deploy.yml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-mysql
  labels:
    app: example
spec:
  selector:
    matchLabels:
      app: example
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: example
        tier: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

Feitelijk zou je het MYSQL_ROOT_PASSWORD uit een K8s secret moeten halen maar voor de test voldoet dit ook.

Apply deze manifests en er zal een pod aangemaakt worden waarop we kunnen connecten en testen. Het test scenario:

  • Maak een nieuwe database
  • Verwijder de bestaande pod
  • Connect naar de nieuwe pod
  • Controleer de eerder aangemaakte database

De bijbehorende commando’s voor het scenario:

$ kubectl get pods | grep mysql
my-mysql-689bccf96b-npg5s   1/1     Running   0          25m

$ kubectl exec -it my-mysql-689bccf96b-npg5s -- /bin/bash
root@my-mysql-689bccf96b-npg5s:/# mysql -u root -p mysql
Enter password:

mysql> create database longhorn_test;
Query OK, 1 row affected (0.01 sec)

mysql> exit
root@my-mysql-689bccf96b-npg5s:/# exit

$ kubectl delete pod my-mysql-689bccf96b-npg5s
pod "my-mysql-689bccf96b-npg5s" deleted

$ kubectl get pods | grep mysql
my-mysql-689bccf96b-sm8jl   1/1     Running   0          31s

$ kubectl exec -it my-mysql-689bccf96b-sm8jl -- /bin/bash
root@my-mysql-689bccf96b-sm8jl:/# mysql -u root -p mysql
Enter password:

mysql> show databases;
+----------------------+
| Database             |
+----------------------+
| information_schema   |
| longhorn_test        |
| #mysql50#lost+found  |
| mysql                |
| performance_schema   | |
+----------------------+
5 rows in set (0.00 sec)

mysql> exit

root@my-mysql-689bccf96b-sm8jl:/# exit

Als de deployment van de mysql-test verwijderd wordt uit het cluster, zal de PVC in Longhorn blijven met status ‘Detached

De node speeltuin-w01 kan nu Cordoned worden en als dan de test-deployment weer gestart wordt zal deze op node speeltuin-w02 ge-scheduled worden.

The proof of the pudding is in the eating!

$ kubectl get po | grep mysql
my-mysql-689bccf96b-q4g9c   1/1     Running   0          4m18s

$ kubectl exec -it my-mysql-689bccf96b-q4g9c -- /bin/bash

root@my-mysql-689bccf96b-q4g9c:/# mysql -u root -p mysql
Enter password:

mysql> show databases;
+----------------------+
| Database             |
+----------------------+
| information_schema   |
| longhorn_test        |
| #mysql50#lost+found  |
| mysql                |
| performance_schema   |
+----------------------+
5 rows in set (0.01 sec)

mysql> exit

root@my-mysql-689bccf96b-q4g9c:/# exit