La première fois que j’ai mis un nœud en maintenance à la main, kubectl drain s’est bloqué de longues minutes sans rien afficher — le temps que Longhorn évacue ses répliques en silence. De quoi croire le cluster planté à chaque mise à jour, jusqu’à ce que je comprenne ce qu’il attendait vraiment. Ce genre de silence angoissant, répété à chaque opération de maintenance, a fini par justifier un vrai outil plutôt qu’une checklist mentale.
La nécessité d’un outillage dédié
Certaines opérations sur le cluster sont répétitives et error-prone quand elles sont exécutées manuellement :
- Mettre un nœud en mode maintenance (drain + cordon) avant une mise à jour
- Vérifier l’état général du cluster en une commande
- Restaurer un nœud après maintenance (uncordon + vérification)
Un script bash fonctionnerait, mais un outil Node.js structuré est plus maintenable, testable, et extensible. Le résultat : homelab-admin, un CLI + interface web déployé sur le cluster.
Structure du projet
apps/homelab-admin/
├── src/
│ ├── commands/
│ │ ├── node-maintenance.ts # drain/cordon/uncordon
│ │ ├── health-check.ts # état global du cluster
│ │ └── storage-report.ts # état Longhorn
│ ├── lib/
│ │ ├── kubernetes.ts # client kubectl wrapper
│ │ └── longhorn.ts # API Longhorn
│ └── index.ts # CLI entrypoint
└── web/ # Dashboard web (optionnel)
Commande de maintenance
La mise en maintenance d’un nœud est une procédure à plusieurs étapes :
homelab-admin node maintain worker-1
# Ce que ça fait :
# 1. kubectl cordon worker-1 (empêche nouveaux pods)
# 2. kubectl drain worker-1 --ignore-daemonsets --delete-emptydir-data
# 3. Désactiver le scheduling Longhorn sur le nœud
# 4. Attendre l'éviction des répliques Longhorn
# 5. Afficher : "worker-1 est en maintenance. Safe to reboot."
La gestion du step 4 (attente éviction Longhorn) était la partie la plus délicate — l’outil interroge l’API Longhorn toutes les 10 secondes jusqu’à ce qu’aucune réplique active ne soit présente sur le nœud.
kubectl cordon <node> kubectl cordon <node>
Marque le nœud SchedulingDisabled — aucun nouveau pod ne peut y être planifié. Marks the node SchedulingDisabled — no new pod can be scheduled on it.
kubectl drain --ignore-daemonsets --delete-emptydir-data kubectl drain --ignore-daemonsets --delete-emptydir-data
Éviction de tous les pods non-DaemonSet ; les volumes Longhorn migrent vers d’autres nœuds. Eviction of all non-DaemonSet pods; Longhorn volumes migrate to other nodes.
PATCH /v1/nodes/<node> allowScheduling: false PATCH /v1/nodes/<node> allowScheduling: false
Empêche Longhorn de recréer des répliques sur ce nœud pendant la maintenance. Prevents Longhorn from recreating replicas on this node during maintenance.
Poll Longhorn API toutes les 10 s Poll the Longhorn API every 10s
Boucle jusqu’à ce que le compteur de répliques actives sur le nœud atteigne 0. Loops until the count of active replicas on the node reaches 0.
Aucune réplique active · node cordoned No active replica · node cordoned
Le nœud peut être redémarré ou mis à jour en toute sécurité. The node can be safely rebooted or updated.
Health check
$ homelab-admin health
Cluster: HEALTHY
Nodes: 6/6 Ready
Pods: 142/142 Running (0 pending, 0 failed)
Storage: 10 volumes Healthy, 0 Degraded
Ingress: 12 routes actives
⚠ worker-3: memory 87% (1.74Gi/2Gi)
Le health check agrège plusieurs sources : l’API Kubernetes, l’API Longhorn, et les métriques VictoriaMetrics. Le format terminal est optimisé pour une lecture rapide.
Déploiement sur le cluster
homelab-admin est déployé comme pod Kubernetes avec un ServiceAccount qui a les permissions RBAC nécessaires :
rules:
- apiGroups: [""]
resources: ["nodes", "pods", "namespaces"]
verbs: ["get", "list", "patch"]
- apiGroups: [""]
resources: ["pods/eviction"]
verbs: ["create"]
- apiGroups: ["apps"]
resources: ["deployments", "daemonsets"]
verbs: ["get", "list"]
L’interface web est accessible sur homelab-admin.olig-homelab-2025.win — un tableau de bord minimaliste qui affiche l’état du cluster en temps réel, sans nécessiter kubectl.
Leçons apprises
RBAC minimal : ne donner que les permissions strictement nécessaires. Un outil d’administration ne devrait pas avoir cluster-admin même si c’est plus simple — la surface d’attaque en cas de compromise est trop large.
Timeouts généreux pour le drain : kubectl drain peut prendre plusieurs minutes sur des nœuds hébergeant des pods avec PodDisruptionBudgets ou des volumes Longhorn actifs. Configurer un timeout de 10 minutes dans l’outil, avec un affichage de progression.