0090 — nestor lit l'état RÉEL d'un cluster prod (état = K8s, pas VMs)
Accepted (2026-06-22) — mise en œuvre incrémentale suivie par
plan-nestor-pilote-prod.md (promu
Proposed → Accepted au démarrage de l’implémentation, étape 1 : champ
kubeconfig du modèle). Suite directe de
ADR 0053 (isolation banc/prod) et
ADR 0084 (sondes gatées par
target_kind).
Contexte
Section intitulée « Contexte »nestor est l’outil déclaratif du dépôt (ADR 0056). Mais en pratique il ne
sait piloter que le banc Lima : sur une stack target_kind: prod, ses
commandes de lecture mentent sur l’état réel.
Constat empirique (2026-06-22, cluster prod dirqual1-4, sain depuis 10 jours —
Ceph HEALTH_OK, CNPG 3/3, monitoring/gitops/registry en place) :
$ nestor preview # stack dirqual, target_kind: prodRÉEL (lu, non stocké) : VMs présentes : — VMs à créer : dirqual1, dirqual2, dirqual3, dirqual4 ← FAUX nœuds Ready : — ← FAUXPLAN : 10 couche(s) à installer ← DANGEREUXOr kubectl (contexte prod) montre les 4 nœuds Ready et 8 couches déjà
saines. Si l’on avait suivi ce plan (nestor up/next), nestor aurait tenté
de réinstaller K8s + Ceph par-dessus une prod saine. Le piège n’est évité que
parce qu’on a diagnostiqué à la main, en lecture seule.
Trois causes, toutes dans scripts/topology.py :
previewraisonne en VMs Lima._real_vms(target_kind)(ADR 0084) faitif target_kind != "lima": return []→ en prod, « 0 VM » → « VMs à créer : dirqual1-4 ». L’état réel d’un cluster bare-metal n’est pas une liste de VMs : les machines existent hors denestor(provisionnées en amont).- L’état réel des nœuds est gaté.
_ready_nodes(target_kind)sait lirekubectl get nodes, mais se neutralise en prod sansKUBECONFIGexplicite (ADR 0084 §repli) → renvoie vide → « nœuds Ready : — ». - Le kubeconfig prod n’est jamais choisi automatiquement.
_bench_kubeconfig()(ADR 0053) pointe/dev/nullhors banc — protection correcte contre les mutations, mais elle prive aussi la lecture prod d’une cible.
À l’inverse, nestor discover (ADR 0074) lit déjà le K8s réel par kubectl
(_discover_node_roles, _discover_namespaces, _discover_sc_provisioners,
_discover_crd_groups…). La capacité de lecture existe ; elle n’est simplement
pas branchée dans preview/l’état réel pour target_kind: prod.
Décision
Section intitulée « Décision »Quand
target_kind: prod, l’« état RÉEL » denestorest celui du cluster Kubernetes lu parkubectl(nœuds Ready, namespaces, couches via CRD/SC/ ressources), PAS une liste de VMs Lima.preview(et les commandes de lecture) comparent alors le voulu au réel K8s, et le PLAN ne propose que les couches réellement absentes.
Principes de mise en œuvre (détaillés dans le plan) :
- L’état réel est conditionné par
target_kind. Enlima, inchangé (VMslimactl+ nœuds). Enprod, l’état des machines n’est pas du ressort denestor(provisionnées en amont, RUNBOOK) : la section « VMs » disparaît au profit de « nœuds Ready (kubectl) ». Les couches présentes se déduisent du réel K8s (réutiliser les sondes_discover_*existantes), pas d’un état stocké. - Cible kubeconfig DÉCLARÉE dans la topologie. La topologie prod porte un
champ
kubeconfig: <chemin>(dans le.yamlgitignoré qui contient déjà les valeurs réelles, ADR 0023). C’est la source de vérité de la cible : la lecture prod n’est jamais laissée au~/.kube/config/contexte courant du poste (ambigu — c’est précisément ce qui a fait pointer un cluster fantôme lors du diagnostic). Résolution, par priorité : (1)KUBECONFIGexporté = intention explicite de l’opérateur (déjà respectée, ADR 0053) ; (2) sinon lekubeconfig:de la topologie ; (3) sinon, enprod, échec clair (« cible kubeconfig non déclarée ») — jamais de repli silencieux. Si le fichier porte plusieurs contextes, soncurrent-contextfait foi. Le fallback/dev/null(anti-mutation) reste pour le banc (target_kind: lima). - Un kubeconfig dédié par stack, HORS du dépôt. Convention : chaque stack a
son propre fichier
~/.kube/<stack>.config(ex.~/.kube/dirqual.config). Hors de l’arbre du dépôt → aucun risque de commit de credentials réels (les kubeconfig portent des certificats/tokens), emplacement standard kubectl, un fichier par cible (fini le~/.kube/configfourre-tout aux contextes fantômes). Lekubeconfig:de la topo pointe ce fichier. Le banc Lima garde son propre kubeconfig généré (bench/lima/.work/kubeconfig) — même esprit (un fichier par cible), emplacement distinct car généré par le harnais. nestorCOMPLÈTE la topologie à l’activation (stack select). « Lecture seule » porte sur le CLUSTER (ne jamais muter la prod K8s) — PAS sur la config locale. Quand on active une stack prod (stack select— déjà une écriture : le symlink), si la topo ne déclare paskubeconfig:,nestorpropose d’ajouter le champ~/.kube/<stack>.configau fichier (édition texte préservant commentaires, ADR 0076 §4) + propose le rapatriement, puis pose ce KUBECONFIG. Écriture confirmée (jamais silencieuse, ADR 0046), jamais en--no-input(CI : on signale seulement). C’est « nestor corrige la topologie » : la cible devient déclarée, etpreviewdit ensuite la vérité.preview, lui, reste lecture seule (il n’écrit ni le cluster ni la topo — il réoriente versstack selectsi la cible manque).- Confirmation interactive de la cible avant toute action prod. En
target_kind: prod, avant d’exécuter une commande,nestoraffiche le cluster réellement visé par le kubeconfig résolu (endpoint de l’API + nœuds vus, ex.https://10.67.2.11:6443 — dirqual1..4 Ready) et demande confirmation (« est-ce bien la stack<nom>? [y/N] »). Une réponse négative interrompt sans rien faire. C’est le garde-fou qui aurait attrapé le piège vécu lors du diagnostic (un contexte fantômegohonepointant un cluster inexistant restait sélectionné). Mode non interactif (--no-input/CI) : la confirmation est remplacée par une vérification stricte (l’endpoint résolu doit correspondre à celui attendu pour la stack), échec sinon. - Assistance au rapatriement du kubeconfig. Si le
kubeconfig:déclaré est absent ou injoignable (cluster non répondant),nestorne se contente pas d’échouer : il propose de le rapatrier depuis le control-plane — copier/etc/kubernetes/admin.confdu nœudcontrol(connu de l’inventaire SSHbootstrap/hosts.yaml) vers le~/.kube/<stack>.configdéclaré, puis re-vérifier l’accès (get nodes). L’opérateur garde la main (action proposée, confirmée),nestorautomatise la mécanique. Reste lecture seule vis-à-vis du cluster : rapatrier un kubeconfig n’est pas muter la prod. - Lecture d’abord ; les mutations restent hors périmètre de cet ADR. Cet ADR
rend
nestorhonnête en lecture sur la prod (preview/discover/santé). Faire muter la prod parnestor(up/next/remove→ délégation aux playbooks Ansible du RUNBOOK) est une décision distincte et ultérieure, avec ses propres garde-fous (confirmation explicite,target_kindre-vérifié, interdiction absolue de réinstaller un socle existant). Tant qu’elle n’est pas prise, l’installation prod reste pilotée par Ansible (RUNBOOK). - Garde-fou anti-régression d’isolation. Rien dans cet ADR n’abaisse l’ADR
0053 : on élargit la lecture, on ne débride pas la mutation. Un test
doit prouver que
previewprod en lecture ne peut pas déclencher d’écriture.
Conséquences
Section intitulée « Conséquences »Positif :
nestor previewdit la vérité sur un cluster prod existant → plus de « 10 couches à installer » sur une prod saine. Le PLAN devient fiable.- Cohérence : l’outil déclaratif du dépôt couvre enfin la prod en lecture, pas seulement le banc.
- Réutilise l’acquis : les sondes
discover(ADR 0074) deviennent la source de l’état réel prod ; peu de code neuf, surtout du branchement conditionné.
Coût / risques :
- Sensible : on touche au cœur de l’isolation banc/prod (ADR 0053/0084). Le risque est qu’une lecture prod ouvre par inadvertance une voie de mutation — d’où le périmètre lecture seule strict et le test anti-régression.
- L’« état réel » devient polymorphe (
lima= VMs+nœuds ;prod= nœuds K8s). À documenter clairement pour ne pas re-confondre. - Preuve : testable sans toucher la prod (sondes pures + stubs kubectl) ;
validation finale sur le banc (target_kind lima inchangé) + une lecture prod
réelle constatée (
previewreflètekubectl get nodes).
Neutre :
- L’installation prod reste pilotée par Ansible (RUNBOOK) tant que la décision « mutation prod par nestor » n’est pas prise séparément.
Voir aussi
Section intitulée « Voir aussi »- Plan de mise en œuvre.
- ADR 0053 — isolation banc/prod (mutations) ; cet ADR en est le pendant lecture.
- ADR 0084 — sondes gatées
par
target_kind(le mécanisme à étendre). - ADR 0074 —
discoverlit déjà le K8s réel (source des sondes réutilisées). - ADR 0056 —
nestor, outil déclaratif.