mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-08 10:04:42 +02:00
feat: funk-cluster — arrêt k8s propre avec drain + vérification NFS
Remplace le talosctl shutdown immédiat par une séquence en 6 étapes : 1. kubectl cordon tous les nœuds (empêche rescheduling) 2. kubectl drain compute-02/03 (SIGTERM pods, 30s grace, PVCs NFS libérés) 3. kubectl drain compute-01 (ArgoCD, system pods) 4. Vérification NFS : ss confirme plus de sessions :2049 actives 5. talosctl shutdown (halt propre, plus rien ne tourne) 6. Attente extinction ping Prometheus et Grafana ont 30s pour flusher WAL/SQLite avant terminaison. storage-01 (NFS server) est éteint en dernier une fois la vérification passée. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8b6f906a89
commit
a631a4ab6c
2 changed files with 86 additions and 15 deletions
|
|
@ -62,7 +62,7 @@ La connexion SSH se coupe à la fin (storage-01 s'éteint lui-même). C'est norm
|
||||||
funk-stop --k8s
|
funk-stop --k8s
|
||||||
```
|
```
|
||||||
|
|
||||||
Ordre d'arrêt automatique : hermes-agent + litellm → talosctl shutdown compute-01/02/03 → gpu-01 → qdrant + postgresql → storage-01.
|
Ordre d'arrêt automatique : hermes-agent + litellm → cordon+drain compute-02/03 → drain compute-01 → vérif NFS → talosctl shutdown → gpu-01 → qdrant + postgresql → storage-01.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -88,7 +88,13 @@ Vérifie dans l'ordre :
|
||||||
### `funk-stop [--k8s]`
|
### `funk-stop [--k8s]`
|
||||||
|
|
||||||
1. Arrête hermes-agent et litellm sur storage-01 (timeout 10s + SIGKILL si besoin)
|
1. Arrête hermes-agent et litellm sur storage-01 (timeout 10s + SIGKILL si besoin)
|
||||||
2. `--k8s` : `talosctl shutdown` sur compute-01/02/03, attend extinction
|
2. `--k8s` — arrêt propre du cluster en 6 étapes :
|
||||||
|
- **Cordon** des 3 nœuds → plus aucun pod ne peut être replanifié
|
||||||
|
- **Drain compute-02** → SIGTERM aux pods, 30s grace period, PVCs NFS démontés
|
||||||
|
- **Drain compute-03** → idem (Prometheus, Grafana flushent leur WAL/SQLite)
|
||||||
|
- **Drain compute-01** → ArgoCD, kube-state-metrics, etc.
|
||||||
|
- **Vérification NFS** → confirme que plus aucune session NFS active depuis k8s
|
||||||
|
- **talosctl shutdown** → halt propre (plus rien ne tourne, rien n'écrit)
|
||||||
3. Éteint gpu-01 (`shutdown -h now` via SSH)
|
3. Éteint gpu-01 (`shutdown -h now` via SSH)
|
||||||
4. Arrête qdrant et postgresql-16 sur storage-01
|
4. Arrête qdrant et postgresql-16 sur storage-01
|
||||||
5. Éteint storage-01 (`shutdown -h now`) — connexion SSH coupée
|
5. Éteint storage-01 (`shutdown -h now`) — connexion SSH coupée
|
||||||
|
|
@ -154,7 +160,7 @@ ssh s01 "sudo cp /tmp/funk-cluster /usr/local/bin/funk-cluster && sudo chmod +x
|
||||||
|
|
||||||
| Sujet | Détail |
|
| Sujet | Détail |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Ordre d'arrêt | Hermes/LiteLLM → k8s (optionnel) → gpu-01 → Qdrant/PG → storage-01 |
|
| Ordre d'arrêt | Hermes/LiteLLM → cordon+drain k8s (optionnel) → gpu-01 → Qdrant/PG → storage-01 |
|
||||||
| Ordre de démarrage | storage-01 (toujours déjà up) → gpu-01 → k8s (optionnel) |
|
| Ordre de démarrage | storage-01 (toujours déjà up) → gpu-01 → k8s (optionnel) |
|
||||||
| WOL compute nodes | BIOS non configuré → allumer manuellement pendant l'attente ping de `funk-start --k8s` |
|
| WOL compute nodes | BIOS non configuré → allumer manuellement pendant l'attente ping de `funk-start --k8s` |
|
||||||
| LiteLLM bloquant | `systemctl stop --timeout=10` + SIGKILL automatique si timeout |
|
| LiteLLM bloquant | `systemctl stop --timeout=10` + SIGKILL automatique si timeout |
|
||||||
|
|
|
||||||
|
|
@ -357,31 +357,96 @@ cmd_stop() {
|
||||||
|
|
||||||
if [ -n "$with_k8s" ]; then
|
if [ -n "$with_k8s" ]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo "[ cluster k8s — arrêt compute-01/02/03 ]"
|
echo "[ cluster k8s — arrêt propre compute-01/02/03 ]"
|
||||||
local alive=()
|
|
||||||
for ip in "${K8S_IPS[@]}"; do
|
# Quels nœuds sont en vie ?
|
||||||
ping -c1 -W2 "$ip" &>/dev/null && alive+=("$ip")
|
local alive_ips=() alive_names=()
|
||||||
|
for i in 0 1 2; do
|
||||||
|
if ping -c1 -W2 "${K8S_IPS[$i]}" &>/dev/null; then
|
||||||
|
alive_ips+=("${K8S_IPS[$i]}")
|
||||||
|
alive_names+=("${K8S_NAMES[$i]}")
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
if [ ${#alive[@]} -gt 0 ]; then
|
|
||||||
local nodes=$(IFS=,; echo "${alive[*]}")
|
if [ ${#alive_ips[@]} -eq 0 ]; then
|
||||||
info "talosctl shutdown → $nodes"
|
warn "Nœuds k8s déjà éteints"
|
||||||
|
else
|
||||||
|
# 1. Cordon de tous les nœuds — empêche tout rescheduling pendant le drain
|
||||||
|
info "Cordon (plus aucun pod ne peut être replanifié)..."
|
||||||
|
for name in "${alive_names[@]}"; do
|
||||||
|
$KUBECTL cordon "$name" 2>/dev/null \
|
||||||
|
&& ok "$name — cordonné" \
|
||||||
|
|| warn "$name — cordon échoué (nœud peut-être inaccessible)"
|
||||||
|
done
|
||||||
|
|
||||||
|
# 2. Drain workers en premier (compute-02, compute-03)
|
||||||
|
# Les pods reçoivent SIGTERM → flush WAL/SQLite → PVCs NFS démontés
|
||||||
|
echo ""
|
||||||
|
info "Drain workers (SIGTERM pods, 30s grace, 90s max)..."
|
||||||
|
for i in 1 2; do
|
||||||
|
if ping -c1 -W2 "${K8S_IPS[$i]}" &>/dev/null; then
|
||||||
|
info " Drain ${K8S_NAMES[$i]}..."
|
||||||
|
$KUBECTL drain "${K8S_NAMES[$i]}" \
|
||||||
|
--ignore-daemonsets \
|
||||||
|
--delete-emptydir-data \
|
||||||
|
--grace-period=30 \
|
||||||
|
--timeout=90s \
|
||||||
|
--force 2>&1 | grep -vE "^(Warning|I[0-9])" | tail -3 || true
|
||||||
|
ok "${K8S_NAMES[$i]} — pods évacués, PVCs NFS libérés"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 3. Drain control-plane (compute-01) — ArgoCD, kube-state-metrics, etc.
|
||||||
|
if ping -c1 -W2 "${K8S_IPS[0]}" &>/dev/null; then
|
||||||
|
echo ""
|
||||||
|
info "Drain control-plane (compute-01)..."
|
||||||
|
$KUBECTL drain compute-01 \
|
||||||
|
--ignore-daemonsets \
|
||||||
|
--delete-emptydir-data \
|
||||||
|
--grace-period=30 \
|
||||||
|
--timeout=90s \
|
||||||
|
--force 2>&1 | grep -vE "^(Warning|I[0-9])" | tail -3 || true
|
||||||
|
ok "compute-01 — drainé"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Vérification NFS : plus aucune session active depuis les nœuds k8s
|
||||||
|
echo ""
|
||||||
|
info "Vérification montages NFS..."
|
||||||
|
local nfs_wait=0
|
||||||
|
while ss -tn 2>/dev/null | grep ':2049' | grep -qE '10\.1[123]\.'; do
|
||||||
|
sleep 3; nfs_wait=$((nfs_wait + 3))
|
||||||
|
[ $nfs_wait -ge 30 ] && break
|
||||||
|
echo -ne " → NFS encore actif depuis nœuds k8s... ${nfs_wait}s\r"
|
||||||
|
done; echo ""
|
||||||
|
if ss -tn 2>/dev/null | grep ':2049' | grep -qE '10\.1[123]\.'; then
|
||||||
|
warn "Sessions NFS toujours actives après 30s — extinction quand même"
|
||||||
|
else
|
||||||
|
ok "NFS libéré — aucune écriture en cours depuis le cluster"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 5. Extinction via talosctl (kernel halt propre — plus rien ne tourne)
|
||||||
|
echo ""
|
||||||
|
local nodes=$(IFS=,; echo "${alive_ips[*]}")
|
||||||
|
info "talosctl shutdown → ${alive_ips[*]}"
|
||||||
if $TALOSCTL shutdown --nodes "$nodes" 2>/dev/null; then
|
if $TALOSCTL shutdown --nodes "$nodes" 2>/dev/null; then
|
||||||
ok "Shutdown envoyé aux nœuds"
|
ok "Shutdown envoyé aux nœuds"
|
||||||
else
|
else
|
||||||
warn "Erreur talosctl shutdown — extinction manuelle requise"
|
warn "Erreur talosctl shutdown — extinction manuelle requise"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# 6. Attente extinction complète (ping)
|
||||||
local tries=0
|
local tries=0
|
||||||
while [ $tries -lt 20 ]; do
|
while [ $tries -lt 20 ]; do
|
||||||
local still_up=0
|
local still_up=0
|
||||||
for ip in "${alive[@]}"; do ping -c1 -W1 "$ip" &>/dev/null && still_up=$((still_up + 1)); done
|
for ip in "${alive_ips[@]}"; do
|
||||||
|
ping -c1 -W1 "$ip" &>/dev/null && still_up=$((still_up + 1))
|
||||||
|
done
|
||||||
[ $still_up -eq 0 ] && break
|
[ $still_up -eq 0 ] && break
|
||||||
sleep 3; tries=$((tries + 1))
|
sleep 3; tries=$((tries + 1))
|
||||||
echo -ne " → Extinction k8s... $((tries * 3))s\r"
|
echo -ne " → Extinction k8s... $((tries * 3))s\r"
|
||||||
done; echo ""
|
done; echo ""
|
||||||
ok "Cluster k8s éteint"
|
ok "Cluster k8s éteint proprement"
|
||||||
else
|
|
||||||
warn "Nœuds k8s déjà éteints"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -429,7 +494,7 @@ case "$CMD" in
|
||||||
echo " start Démarre gpu-01 (WOL) + vérifie tous les services"
|
echo " start Démarre gpu-01 (WOL) + vérifie tous les services"
|
||||||
echo " start --k8s Idem + démarre le cluster k8s (compute-01/02/03)"
|
echo " start --k8s Idem + démarre le cluster k8s (compute-01/02/03)"
|
||||||
echo " stop Arrêt propre gpu-01 + services storage-01"
|
echo " stop Arrêt propre gpu-01 + services storage-01"
|
||||||
echo " stop --k8s Idem + éteint le cluster k8s (talosctl shutdown)"
|
echo " stop --k8s Idem + arrêt propre k8s (drain → NFS check → talosctl shutdown)"
|
||||||
echo " status État complet (storage-01 + gpu-01 + k8s)"
|
echo " status État complet (storage-01 + gpu-01 + k8s)"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue