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-effort‘ voor 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?
.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