Portail de maintenance
| Propriété | Valeur |
|---|---|
| URL | https://maintenance.lab.djayzone.com |
| Namespace | maintenance |
| Accès | GitHub SSO, utilisateur djayzone uniquement |
| Source | apps/ovh-primary/maintenance/ |
| Contrôleur | 1 réplica |
| Proxy SSO | 2 réplicas, anti-affinité stricte, PDB minAvailable: 1 |
Objectif
Le portail expose des actions prédéfinies par VPS sans fournir de terminal arbitraire. Il affiche l'état Ready, le cordon, les capacités, les versions Linux/K3s et la dernière phase de maintenance.
Chaque action apparaît dans « Historique et comptes rendus ». Le bouton « Voir le rapport » affiche un rapport construit à partir du Job et de son Pod : action, nœud, Job, Pod, timestamps, durée, étape, phase, reason, exit code, commande prédéfinie et sortie du conteneur. Kubernetes fusionne stdout/stderr dans le flux de logs du conteneur ; la fin de ce flux est toujours conservée afin de rendre visibles les erreurs finales d'APT.
À la terminaison du Job, le contrôleur persiste aussi une copie bornée du rapport dans les annotations du Job, avec l'étape, l'exit code, la raison Kubernetes et les timestamps. Le rapport reste ainsi consultable même si le Pod ou son flux de logs ne sont plus disponibles. Le conteneur utilise également terminationMessagePolicy: FallbackToLogsOnError comme filet de sécurité lorsque l'API de logs n'est plus exploitable.
À la fin d'une tâche, le contrôleur envoie ce même compte rendu HTML à l'adresse administrateur via le Mail Gateway interne. Le Job est annoté maintenance.djayzone.com/notified=sent afin de garantir un seul envoi.
Actions unitaires
| Action | Effet |
|---|---|
| Diagnostic complet | Uptime, mémoire, disque, service K3s, versions et paquets disponibles |
| Simuler les mises à jour | Actualise l'index APT puis exécute une simulation d'upgrade |
| Installer les mises à jour OS | apt-get update puis apt-get upgrade non interactif sur le VPS choisi |
| Cordonner | Interdit le placement de nouveaux pods sur le nœud |
| Drainer | Cordon puis évictions via l'API Kubernetes ; DaemonSets et pods miroir sont conservés |
| Redémarrer K3s | Redémarre le service k3s ; action actuellement réservée aux trois control-plane. Ne pas l'utiliser sur le worker UK, qui exécute k3s-agent |
| Redémarrer la VM | Planifie un reboot du VPS |
| Rendre planifiable | Retire le cordon |
Les actions sensibles demandent de saisir exactement le nom du nœud. Une seule tâche de maintenance sensible peut être active à la fois.
Exécution des tâches hôte
Les actions qui nécessitent d'administrer le VPS sont exécutées dans un Job privilégié, épinglé sur le nœud demandé et montant / sous /host. La commande reste une action prédéfinie dans app.py et s'exécute via chroot /host.
Le conteneur appelle directement chroot /host /bin/bash -lc <script> sous forme d'arguments Kubernetes distincts, sans /bin/sh -c intermédiaire. Le script Bash reste ainsi intact jusqu'à son interprétation dans le chroot : les variables de contrôle telles que $1, $@, $?, $step et $rc ne peuvent pas être développées prématurément par un shell extérieur.
Le Job utilise hostPID: true, hostNetwork: true et dnsPolicy: Default. Le partage du namespace réseau de l'hôte est nécessaire au chroot pour conserver le comportement réseau du système hôte, notamment lorsqu'un /etc/resolv.conf géré par systemd-resolved pointe vers un résolveur loopback tel que 127.0.0.53. Sans hostNetwork, ce loopback désigne le Pod et non le VPS.
Le nodeSelector kubernetes.io/hostname reste obligatoire et le contrôleur vérifie le nom demandé contre la liste réelle des nœuds avant de créer le Job.
Pour les actions APT, le script marque explicitement chaque étape avant exécution :
apt-updatepourapt-get update;apt-upgradepour l'installation non interactive ;apt-simulate-upgradepour la simulation.
Une commande non nulle conserve son code retour et arrête immédiatement l'action. Aucun || true n'est utilisé pour masquer un échec de update-os.
Séquence complète
- Vérifie que les quatre nœuds sont
Ready. - Cordon le VPS ciblé.
- Évince les workloads en respectant les PodDisruptionBudgets.
- S'arrête si une éviction est bloquée.
- Installe les mises à jour OS dans un Job privilégié lié au nœud.
- Planifie le reboot.
- Observe le passage
NotReady, puis le retourReady. - Uncordon automatiquement le nœud.
La mise à niveau de version K3s n'est pas incluse. Elle doit rester une opération rolling avec une version cible explicite, sauvegarde etcd et validation entre chaque control-plane.
Cas particulier du worker UK
Le worker vps-f0621bb1 exécute k3s-agent, pas k3s. L'action unitaire « Redémarrer K3s » du portail exécute actuellement systemctl restart k3s et n'est donc pas adaptée à ce nœud.
Si un redémarrage manuel de l'agent est nécessaire, utiliser une session SSH opérateur :
sudo systemctl restart k3s-agent
sudo systemctl is-active k3s-agent
Puis vérifier depuis le poste opérateur :
kubectl get node vps-f0621bb1
kubectl get pods -A -o wide --field-selector spec.nodeName=vps-f0621bb1
Ne pas transformer cette procédure manuelle en changement durable de configuration ; le support natif du worker dans le portail doit être corrigé dans son code avant d'utiliser cette action depuis l'UI.
Sécurité
- OAuth2 Proxy filtre le compte GitHub autorisé.
- Le backend vérifie également l'identité transmise par le proxy.
- NetworkPolicy : backend accessible seulement depuis le proxy et Gatus.
- RBAC limité aux nœuds, pods/évictions et Jobs de maintenance.
- Les tâches hôtes sont privilégiées parce qu'elles doivent agir sur le système du VPS ; aucune commande fournie par le navigateur n'est exécutée.
hostPID,hostNetwork,privilegedet lehostPath /sont limités aux Jobs de tâches hôte ; le contrôleur web lui-même reste non privilégié.- Les commandes sont définies dans
app.pyet versionnées par GitOps. backoffLimit: 0est conservé : une erreur réelle reste un échec explicite et n'est pas rejouée silencieusement.- La limite mémoire du Job reste à
256Mitant qu'aucun OOM n'est démontré ; un éventuelOOMKilledsera désormais conservé dans le diagnostic. - Les Jobs terminés sont conservés 7 jours pour audit et diagnostic.
- Le rapport persistant est borné afin de rester largement sous les limites de métadonnées Kubernetes ; sa fin est prioritaire pour conserver la cause d'erreur.
- L'adresse destinataire est stockée hors Git dans le Secret
maintenance-notifications. - Les rapports ne doivent contenir aucun secret, token ou variable sensible.
- Grafana expose les compteurs d'envois et d'échecs propres à l'application
maintenance.
Exploitation et dépannage
kubectl -n maintenance get deploy,pod,svc,ingress,pdb,jobs -o wide
kubectl -n maintenance logs deploy/maintenance-controller --tail=200
kubectl -n maintenance logs job/<nom-du-job>
kubectl get nodes
kubectl describe node <nom-du-noeud>
En cas d'échec APT, contrôler dans le rapport Step, Exit code, Reason et surtout les dernières lignes de la sortie. Une erreur telle que Temporary failure resolving ou Could not resolve oriente vers la résolution DNS ; OOMKilled identifie au contraire une pression mémoire du conteneur. Le rapport doit permettre ce diagnostic même après disparition du Pod.
Pour vérifier l'état APT d'un hôte dans une fenêtre de maintenance contrôlée, utiliser notamment dpkg --audit et apt-get check. dpkg --configure -a modifie l'hôte et ne doit être exécuté qu'en connaissance de cause dans la procédure prévue.
Si l'uncordon automatique n'a pas lieu, vérifier que le nœud est réellement revenu Ready, puis utiliser l'action unitaire « Rendre planifiable ». Ne jamais lancer deux séquences complètes en parallèle.