4.3 KiB
Runbook — Self-healing des VM (bloc A, semaine 6)
Principe
Chaque minute, le scheduler Laravel (compte www-data, déjà en place depuis
l'étape 10) exécute php artisan labs:surveiller-vm, implémenté par
App\Services\Labs\SurveillanceVm.
Pour chaque VM (stock chaud et sessions d'élèves actives), il demande au
service correcteur (sur l'hyperviseur) une sonde de santé :
état libvirt du domaine (virsh domstate) et guest-ping de l'agent invité
QEMU. Rien n'est exécuté dans la VM — c'est une requête distincte de la
correction d'un lab ({instance, sante: true} plutôt que
{instance, lab, verification}), refusée si elle porte les deux à la fois.
- VM du stock muette 2 sondes de suite (
stock:echecscompteur Redissante:muette:{instance}) : sa stack est retirée du stock chaud et supprimée.labs:remplir-stockla remplace à la prochaine minute. Aucun élève ne reçoit jamais une VM défaillante. - VM d'élève muette 3 sondes de suite : redémarrage forcé par Nova
(
reboot --hard, ou démarrage si elle est éteinte), au plus 2 fois par heure. Au-delà, la VM est marquée irréparable : le prof la voit dans la salle d'attente (« ne répond plus malgré deux redémarrages automatiques. L'équipe technique est prévenue. »), et doit relancer le lab de cet élève à la main.
Garde-fous
- Délai de grâce de 3 minutes après la création d'une VM : elle démarre encore, on ne la sonde pas (correspond au p95 de démarrage mesuré à l'étape 13, 75 s, avec large marge).
- Correcteur injoignable : aucune action (on ne devine jamais l'état d'une VM qu'on n'a pas pu sonder).
- Panne générale : si toutes les VM sondées sont muettes à la fois
(seuil : au moins 3 VM), c'est probablement l'hyperviseur qui est en
cause, pas les VM une par une — aucune relance n'est tentée (une rafale de
redémarrages ne répare pas un hôte en panne, et l'alourdirait). Couvert
par les alertes existantes (
DisqueSature,MemoireSaturee,ServiceOpenStackArrete), pas par ce mécanisme.
Métriques (Prometheus, collecteur textfile)
Fichier /var/lib/node_exporter/textfile/sante_vm.prom (écrit par
www-data, lu par node_exporter) :
| Métrique | Sens |
|---|---|
syllabus_vm_surveillance_timestamp |
dernier passage |
syllabus_vm_sondees / syllabus_vm_muettes |
VM sondées / muettes à ce passage |
syllabus_vm_irreparables |
VM d'élèves toujours muettes après les relances |
syllabus_vm_panne_generale |
1 si aucune action n'a été tentée (panne générale ou correcteur injoignable) |
syllabus_vm_reparations_total{type=...} |
compteur cumulé : relance_session, retrait_stock, abandon |
Alertes à ajouter avant le pilote (pas encore faites, voir docs/dette.md) :
syllabus_vm_panne_generale == 1 pendant plus de 5 min, et
syllabus_vm_irreparables > 0.
Lancer une vérification manuellement
ssh paillasse
cd /var/www/portail
sudo -u www-data HOME=/tmp php8.3 artisan labs:surveiller-vm
cat /var/lib/node_exporter/textfile/sante_vm.prom
Provoquer une panne pour tester (ne jamais sur une vraie classe)
# 1. Prendre une VM réelle (une session de test, ou du stock) et la geler
# comme un noyau planté (le CPU virtuel s'arrête, l'agent ne répond plus) :
ssh paillasse "sudo docker exec nova_libvirt virsh suspend <uuid-instance>"
# 2. Observer (plusieurs minutes, ou plusieurs appels manuels) :
ssh paillasse "cd /var/www/portail && sudo -u www-data HOME=/tmp php8.3 artisan labs:surveiller-vm"
# 3. Vérifier le retour à l'état normal :
ssh paillasse "sudo docker exec nova_libvirt virsh domstate <uuid-instance>" # running
Compte-rendu du premier test réel : docs/postmortems/2026-10-12-vm-figee-self-healing.md.
Limites connues
- Ne couvre pas la panne du serveur lui-même (un seul serveur, pas de sonde
extérieure — dette connue,
docs/dette.md). - Ne couvre pas un service Kolla arrêté ni un conteneur maison arrêté : ce
sont déjà
Restart=always/unless-stoppedcôté systemd et Docker (voir relevé du 2026-10-12 dans le journal), pas ce mécanisme. - Une stack du stock chaud orpheline (ni muette, ni référencée) est déjà
traitée par
StockChaud::menage()(étape 11) ;SurveillanceVms'occupe seulement des VM qui répondent mal, pas de celles qui n'existent plus en Redis.