❯ storage · Running

Stockage bloc distribué avec Longhorn Distributed Block Storage with Longhorn

Construction d'une stratégie de stockage deux niveaux avec Longhorn sur k3s — tagging de disques, gestion des répliques, migration de volumes et récupération après dégradation. Building a resilient, two-tier storage strategy with Longhorn on k3s — disk tagging, replica management, volume migration, and recovering from degraded state.

· 5 min de lecture 5 min read ·
k3s-clusterlonghornstoragek8s
🇬🇧 Read this article in English

Pourquoi Longhorn ?

10 volumes passés en Degraded d’un coup — c’est le prix payé pour une hypothèse de design qui semblait raisonnable sur le papier (tagger les SSD des masters critical) et qui s’est effondrée dès qu’on a désactivé le scheduling sur ces mêmes masters. Ce post raconte l’architecture de stockage deux niveaux qui a suivi.

Le stockage persistant est le problème le plus difficile à résoudre dans Kubernetes. Les solutions cloud-native (EBS, GCE PD) sont triviales dans le cloud, mais sur du bare-metal, les options sont limitées : NFS (single point of failure), Ceph (trop lourd pour des RPi), ou Longhorn.

Longhorn est un système de stockage bloc distribué développé par Rancher (maintenant CNCF). Il réplique les données sur plusieurs nœuds, expose des PersistentVolumes natifs Kubernetes, et se gère entièrement via une interface web. Sa légèreté relative en fait le choix idéal pour un cluster RPi.

Architecture deux niveaux

La première version du cluster utilisait une StorageClass unique. Avec l’expérience, j’ai adopté une stratégie deux niveaux :

TierStorageClassdiskSelectornumberOfReplicasCas d’usage
Criticalcritical-storagecritical3Bases de données, secrets, données irremplaçables
Standardstandard-storagestandard2Caches, artefacts, données reconstructibles

Le diskSelector est la clé : Longhorn ne planifie les répliques d’un volume que sur des disques ayant le tag correspondant.

Configuration des StorageClasses

# critical-storage
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: critical-storage
parameters:
  diskSelector: critical
  numberOfReplicas: '3'
  dataLocality: disabled
  replicaAutoBalance: best-effort
  fsType: ext4
  staleReplicaTimeout: '30'
provisioner: driver.longhorn.io
reclaimPolicy: Retain
volumeBindingMode: Immediate
allowVolumeExpansion: true

reclaimPolicy: Retain est crucial pour les données critiques — le volume n’est pas supprimé quand le PVC est supprimé. Il faut une action manuelle explicite.

Tagging des disques

Le tagging est géré via l’interface Longhorn (Settings → Nodes). Chaque disque sur chaque nœud peut recevoir un ou plusieurs tags.

Design initial (erreur) : les SSD des masters étaient tagués critical, ceux des workers standard. L’hypothèse était que les masters, plus stables, devraient héberger les données critiques.

Problème découvert : après désactivation du scheduling sur les masters pour alléger la charge du control-plane, les volumes critical ne pouvaient plus créer de répliques — aucun disque critical n’était schedulable. Résultat : 10 volumes en état Degraded.

Correction : ajout du tag critical sur les SSD des workers worker-1 et worker-2, puis migration des répliques via éviction séquentielle.

Leçon : les données critiques doivent vivre sur les nœuds les plus puissants (les workers RPi 5), pas sur les masters dont la mission principale est le control-plane.

Éviction et migration de répliques

Pour migrer les répliques des masters vers les workers sans interruption de service :

Pour chaque master (séquentiellement, pas en parallèle) :
1. Dans Longhorn UI → Node → Disable scheduling
2. Dans Longhorn UI → Node → Request eviction
3. Attendre que toutes les répliques soient migrées (surveiller le statut "Healthy")
4. Passer au master suivant

L’éviction séquentielle est obligatoire. Évincer deux masters simultanément avec numberOfReplicas: 2 signifie qu’aucun des deux nœuds cibles n’a assez de répliques pour maintenir le quorum — les volumes passent Degraded sans possibilité de reconstruction.

Gestion du nombre de répliques

Avec numberOfReplicas: 3 et des workers critical tagués sur worker-1, worker-2 et worker-3, les 3 répliques peuvent être planifiées. À l’époque de cet article, la configuration utilisait 3 répliques pour critical-storage et 2 pour standard-storage, ce qui correspondait au nombre de workers capables d’héberger chaque tier.

Mise à jour (2026-07) : l’architecture de StorageClasses a évolué depuis — le cluster utilise désormais 3 classes (critical, longhorn, standard) avec des règles de réplicas différentes. Voir le repo k3s-homelab pour l’état actuel.

# Vérifier l'état de tous les volumes
for vol in $(kubectl get volumes.longhorn.io -n longhorn-system -o name); do
  kubectl get $vol -n longhorn-system \
    -o custom-columns='NAME:.metadata.name,STATE:.status.state,ROBUSTNESS:.status.robustness,REPLICAS:.spec.numberOfReplicas'
done

Tous les volumes en état Healthy avec 2 ou 3 répliques selon leur StorageClass.

Monitoring de l’état des volumes

Longhorn expose des métriques Prometheus. Les alertes critiques à surveiller :

  • longhorn_volume_state ≠ 1 (1 = Healthy) → volume dégradé
  • longhorn_volume_robustness = 3 (3 = Faulted) → volume inutilisable
  • longhorn_node_status → état des nœuds de stockage
# Vérification rapide depuis kubectl
kubectl get volumes.longhorn.io -n longhorn-system \
  -o custom-columns='NAME:.metadata.name,STATE:.status.state,ROBUSTNESS:.status.robustness'

Backup vers MinIO

Longhorn supporte les backups vers un endpoint S3. Avec MinIO déployé sur le cluster, on obtient un système de backup complet sans dépendance externe.

Configuration dans Longhorn Settings :

  • Backup Target : s3://longhorn-backups@us-east-1/
  • Backup Target Credential Secret : secret contenant les credentials MinIO
  • S3 Endpoint : http://minio.minio.svc.cluster.local:9000

Les backups sont planifiés via les RecurringJobs Longhorn. Pour les volumes critiques : backup quotidien à 2h, rétention 7 jours.

Points de vigilance

Longhorn est gourmand en mémoire sur les nœuds qui hébergent des répliques actives. Sur worker-2, les processus longhorn-engine pouvaient consommer jusqu’à 1,5 Go de RAM avec de multiples volumes actifs. Surveiller la mémoire des workers est essentiel.

Ne jamais supprimer un PVC Retain sans vérification : le volume Longhorn sous-jacent persiste et consomme de l’espace. Nettoyer régulièrement les volumes orphelins via l’interface Longhorn.

dataLocality: disabled est le bon choix pour un RPi avec accès réseau Gigabit. dataLocality: best-effort ou strict-local peut sembler meilleur pour les performances, mais crée des problèmes de scheduling quand les pods migrent vers des nœuds sans réplique locale.

Cette architecture deux niveaux a globalement tenu la route — jusqu’à ce qu’une régression upstream dans l’instance-manager fasse fuir plusieurs gigaoctets de RAM sur les nœuds de stockage. Voir l’incident et le runbook associé.

k3s-clusterlonghornstoragek8s