À propos du projet

pillar-csi est un pilote CSI Kubernetes pour les clusters bare-metal auto-hébergés. Il prend des zvol ZFS locaux ou des volumes logiques LVM sur un nœud de stockage dédié et les exporte vers le reste du cluster via NVMe-oF/TCP, en écrivant directement dans le noyau via configfs plutôt qu'en s'appuyant sur SSH, des démons Python ou des CLI de cible externes. Ce n'est explicitement pas un système de fichiers distribué : il ne réplique, ne stripe ni ne met en pool le stockage entre les nœuds. L'architecture se compose de trois charges de travail. pillar-controller s'exécute en tant que Deployment et réconcilie les CRD Pillar* à portée cluster. pillar-agent s'exécute en tant que DaemonSet uniquement sur les nœuds de stockage et détient toutes les écritures configfs sur l'hôte. pillar-node s'exécute sur chaque worker et gère le service CSI Node (connexion de l'initiateur, mkfs, bind-mount). Les deux DaemonSets utilisent hostNetwork afin que le plan de données NVMe-oF/TCP puisse se lier au namespace réseau de l'hôte. La configuration est déclarative via des CRD : PillarAgent localise un agent de stockage, PillarStore décrit un pool de stockage (nom du pool ZFS, VG LVM, configuration du backend), PillarProtocol décrit la configuration du protocole réseau, et PillarStorageClass combine pool et protocole en une StorageClass générée automatiquement. Un CRD interne PillarVolumeState enregistre l'état durable pour la récupération après des échecs de provisioning partiels et le suivi des publications ; le contrôleur applique l'exclusivité des modes d'accès CSI à partir de cet enregistrement. Un élément de conception notable est le fencing des opérations obsolètes. Chaque appel d'agent qui modifie les ressources d'un volume porte un jeton de fencing composé de l'UID d'état du volume (identité de cycle de vie) et d'un compteur publicationGeneration incrémenté via compare-and-swap. L'agent conserve des marques durables par volume sur le disque local du nœud de stockage sous /var/lib/pillar-csi/agent/generations/, monté en hostPath afin que les marques survivent aux redémarrages et aux reboots. Les requêtes plus anciennes que la marque, provenant d'un cycle de vie terminé ou remplacé, ou ne portant aucun jeton sont rejetées avec FAILED_PRECONDITION. Le README signale une mise en garde lors de la mise à niveau : détachez tous les volumes avant de mettre à niveau, car les versions antérieures n'enregistraient ni publications, ni cycles de vie, ni générations, et aucun shim de migration n'est fourni. L'état de node stage est enregistré sous /var/lib/pillar-csi/node/ sur le worker, écrit atomiquement via fichier temporaire, sync et rename. NodeUnstageVolume relit l'enregistrement car le CO n'envoie ni capacité de volume ni contexte de volume lors de l'unstage. Les décisions de démontage délèguent à l'Unmount idempotent du mounter, en traitant les erreurs de sonde de montage corrompu (EIO, ENOTCONN, ESTALE, EACCES) comme toujours montées afin que kubelet puisse récupérer les pods dont le système de fichiers est entré en arrêt noyau. Matrice prise en charge : zvol ZFS et LV LVM sur NVMe-oF/TCP sont livrés ; iSCSI est conçu mais pas encore livré ; NFS pour les datasets ZFS est conçu mais pas encore livré. Les opérations CSI incluent CreateVolume, DeleteVolume, ControllerPublish/Unpublish, ControllerExpandVolume, NodeStage/Unstage, NodePublish/Unpublish, NodeExpandVolume, NodeGetVolumeStats, ValidateVolumeCapabilities et GetCapacity. Les modes d'accès sont ReadWriteOnce, ReadWriteOncePod et ReadOnlyMany ; les modes de volume sont Filesystem (ext4/xfs) et Block. L'installation se fait via Helm. mTLS entre le contrôleur et l'agent est opt-in (mode cert-manager ou mode Secret fourni) ; la valeur par défaut est gRPC en clair. Kubernetes 1.24 ou plus récent est requis. Les nœuds de stockage nécessitent les modules noyau nvmet et nvmet_tcp ; les nœuds worker nécessitent nvme_tcp et nvme_fabrics ; les init-containers exécutent modprobe au démarrage. Le README inclut un quickstart avec des exemples YAML de CRD, un dépannage via les commandes standard kubectl describe et logs, et une procédure de récupération détaillée pour les volumes hérités bloqués à ExportSpecMissing, en insistant sur des décisions explicites de l'opérateur pour bindAddress, port et aclEnabled plutôt que de deviner à partir d'observations d'exécution.