Blog

Longhorn : stockage distribué cloud-native sur OpenShift

OpenShift
Longhorn
Stockage
Kubernetes
Helm

Déploiement et configuration de Longhorn sur OpenShift pour fournir du stockage persistant distribué. Installation via Helm, gestion des volumes, snapshots, backup S3 et intégration avec les SCC OpenShift.

8 janvier 2025

Qu’est-ce que Longhorn ?

Longhorn est un système de stockage distribué cloud-native open-source développé par Rancher (SUSE). Il fournit du stockage de blocs persistant répliqué directement sur les nœuds du cluster, sans dépendance externe. Conçu pour Kubernetes, il est désormais un projet CNCF graduated.

Avantages clés :

  • Réplication des volumes — chaque PVC peut être répliqué sur plusieurs nœuds
  • Snapshots et backups — sauvegarde vers S3, NFS, Azure Blob
  • Interface graphique — dashboard intégré pour visualiser les volumes
  • Thin provisioning — allocation à la demande
  • Live upgrade — mise à jour sans interruption de service

Prérequis sur OpenShift

Longhorn nécessite des ajustements spécifiques à OpenShift pour les permissions SELinux et les SCC.

# Vérifier que open-iscsi est disponible sur les nœuds
# Sur les nœuds RHCOS (Red Hat CoreOS), iSCSI est inclus par défaut
oc debug node/<nom-du-noeud> -- chroot /host iscsiadm --version

# Vérifier le système de fichiers supporté
oc debug node/<nom-du-noeud> -- chroot /host bash -c "modprobe nfs && echo ok"

Configurer les MachineConfig pour iSCSI (RHCOS)

apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
  labels:
    machineconfiguration.openshift.io/role: worker
  name: 99-worker-enable-iscsid
spec:
  config:
    ignition:
      version: 3.2.0
    systemd:
      units:
        - enabled: true
          name: iscsid.service

Créer la SCC pour Longhorn

apiVersion: security.openshift.io/v1
kind: SecurityContextConstraints
metadata:
  name: longhorn-scc
allowPrivilegedContainer: true
allowHostDirVolumePlugin: true
allowHostNetwork: false
allowHostPID: false
allowHostPorts: false
readOnlyRootFilesystem: false
runAsUser:
  type: RunAsAny
seLinuxContext:
  type: RunAsAny
fsGroup:
  type: RunAsAny
supplementalGroups:
  type: RunAsAny
volumes:
  - configMap
  - downwardAPI
  - emptyDir
  - hostPath
  - nfs
  - persistentVolumeClaim
  - projected
  - secret
users: []
groups: []

Installation via Helm

# Ajouter le dépôt Helm Longhorn
helm repo add longhorn https://charts.longhorn.io
helm repo update

# Créer le namespace
oc new-project longhorn-system

# Associer la SCC au ServiceAccount Longhorn
oc adm policy add-scc-to-user longhorn-scc \
  -z longhorn-service-account \
  -n longhorn-system

oc adm policy add-scc-to-user longhorn-scc \
  -z longhorn-driver-deployer \
  -n longhorn-system

# Installer Longhorn
helm install longhorn longhorn/longhorn \
  --namespace longhorn-system \
  --set defaultSettings.defaultReplicaCount=3 \
  --set defaultSettings.backupstorePollInterval=300 \
  --set ingress.enabled=false \
  --set openshift.enabled=true \
  --set openshift.ui.route=true \
  --set openshift.ui.port=443 \
  --version 1.7.2

Vérifier le déploiement :

oc get pods -n longhorn-system
oc get svc -n longhorn-system

Exposer le dashboard via une Route OpenShift

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: longhorn-ui
  namespace: longhorn-system
spec:
  to:
    kind: Service
    name: longhorn-frontend
  port:
    targetPort: http
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
oc get route longhorn-ui -n longhorn-system

Créer une StorageClass Longhorn

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-fast
  annotations:
    storageclass.kubernetes.io/is-default-class: "false"
provisioner: driver.longhorn.io
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate
parameters:
  numberOfReplicas: "3"
  staleReplicaTimeout: "2880"        # 48h
  fromBackup: ""
  fsType: ext4
  dataLocality: best-effort           # ou "strict-local"
  diskSelector: ""
  nodeSelector: ""
  recurringJobSelector: '[{"name":"backup-daily","isGroup":false}]'
---
# StorageClass pour données critiques avec réplication maximale
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-critical
provisioner: driver.longhorn.io
allowVolumeExpansion: true
parameters:
  numberOfReplicas: "3"
  dataLocality: strict-local
  fsType: ext4

Utiliser la StorageClass

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ma-base-de-donnees
  namespace: production
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn-fast
  resources:
    requests:
      storage: 20Gi

Snapshots et backup S3

Configurer un secret de backup S3

apiVersion: v1
kind: Secret
metadata:
  name: s3-backup-secret
  namespace: longhorn-system
type: Opaque
stringData:
  AWS_ACCESS_KEY_ID: "AKIAIOSFODNN7EXAMPLE"
  AWS_SECRET_ACCESS_KEY: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
  AWS_ENDPOINTS: "https://s3.eu-west-1.amazonaws.com"
  AWS_CERT: ""

Configurer le backup store

# Via la CLI ou le dashboard — BackupTarget
oc patch settings.longhorn.io backup-target \
  -n longhorn-system \
  --type=json \
  -p '[{"op":"replace","path":"/value","value":"s3://mon-bucket-longhorn@eu-west-1/backups"}]'

oc patch settings.longhorn.io backup-target-credential-secret \
  -n longhorn-system \
  --type=json \
  -p '[{"op":"replace","path":"/value","value":"s3-backup-secret"}]'

Politique de backup récurrente

apiVersion: longhorn.io/v1beta2
kind: RecurringJob
metadata:
  name: backup-daily
  namespace: longhorn-system
spec:
  cron: "0 2 * * *"       # Tous les jours à 2h
  task: backup
  groups:
    - default
  retain: 7                # Garder 7 backups
  concurrency: 2
  labels: {}

Restauration d’un volume depuis un backup

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ma-bdd-restauree
  namespace: production
  annotations:
    # Référencer le backup Longhorn à restaurer
    longhorn.io/from-backup: >
      s3://mon-bucket-longhorn@eu-west-1/backups?backup=backup-xxxxx&volume=ma-base-de-donnees
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn-fast
  resources:
    requests:
      storage: 20Gi

Maintenance : éviction d’un nœud

Avant de mettre un nœud en maintenance, évacuer les répliques Longhorn pour éviter la dégradation des volumes :

# Désactiver le scheduling sur le nœud dans Longhorn
oc patch nodes.longhorn.io <nom-du-noeud> \
  -n longhorn-system \
  --type=json \
  -p '[{"op":"replace","path":"/spec/allowScheduling","value":false}]'

# Attendre que les répliques se déplacent
watch oc get replicas.longhorn.io -n longhorn-system | grep <nom-du-noeud>

Comparaison avec les autres solutions de stockage

CritèreLonghornPortworxOpenShift Data Foundation (Ceph)
LicenceApache 2.0 (gratuit)CommercialInclus ODF (payant)
InstallationSimpleComplexeComplexe
PerformancesBonnesExcellentesTrès bonnes
Multi-tenancyLimitéAvancéAvancé
Backup intégréOui (S3/NFS)OuiOui
Cas d’usageDev, PMEEntreprise, HPCEntreprise, fichiers+blocs+objets

Conclusion

Longhorn est une solution idéale pour les clusters OpenShift qui ont besoin de stockage persistant distribué sans la complexité de Ceph ou le coût de Portworx. Son installation via Helm est rapide, son dashboard intuitif, et ses fonctionnalités de backup S3 le rendent opérationnel pour des environnements de production de taille moyenne. Pour les grandes entreprises avec des exigences IOPS élevées ou du stockage multi-accès, des solutions comme Portworx ou OpenShift Data Foundation restent plus adaptées.