mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-08 22:44:43 +02:00
Aligne la documentation sur l'état réel du cluster au 2026-06-18 : - Qdrant : crash-loop résolu le 17/06 (statut « HS / EN COURS » corrigé dans CLAUDE.md, README, admin/ia/rag.md, admin/incidents.md, admin/ia/stt.md). Précision : collection funk-docs supprimée lors de la réparation → re-ingest RAG encore à faire (pas de surévaluation du statut). - STT (assistant vocal « Jarvis ») : ajouté partout (était déployé mais non documenté). - Ghostfolio : ajouté partout (était déployé mais non documenté). - Embeddings dédiés nomic-embed-text :1238 : marqués opérationnels (roadmap README disait encore « TODO »). - llama-server : ×3 → ×4 (instance embeddings) ; gap IaC précisé (embeddings géré par le rôle, seules les 2 instances CPU restent manuelles). - Structure k8s/ corrigée dans CLAUDE.md : ajout stt/ + ghostfolio/, suppression des sous-dossiers traefik/ + metallb/ inexistants (installés via helm au bootstrap). - Namespaces et liste des secrets Vault (vault_pg_ghostfolio_password) complétés. - admin/README.md : index complété (~10 docs manquants : email, n8n, open-webui, ghostfolio, k9s, stt, rag, hermes-voice/souls/auto-improve, alertmanager-webhook). - Funk/ (conception d'origine : LM Studio + agents Goose, obsolète) déplacé sous archive/ avec bandeau « obsolète » + archive/README.md (historique git préservé). Claude-Session: https://claude.ai/code/session_017Qjq5jHiqNepnobJpHYpCa Co-authored-by: Claude <noreply@anthropic.com>
626 lines
23 KiB
Markdown
626 lines
23 KiB
Markdown
# Incidents — Historique et résolutions
|
|
|
|
## 2026-06-05 — Qdrant en crash-loop : segment funk-docs corrompu (RÉSOLU 2026-06-17)
|
|
|
|
### Symptômes
|
|
|
|
- `rag-query` et `rag-ingest` → `Connection refused` (port 6333 fermé)
|
|
- `systemctl status qdrant` → `activating (auto-restart)` en boucle, exit code 101
|
|
- **Invisible dans `systemctl --state=failed`** (l'unité reste en `activating`, jamais `failed`) — l'incident est passé inaperçu 5 jours
|
|
|
|
### Cause
|
|
|
|
Panic au démarrage de Qdrant 1.13.4 :
|
|
|
|
```
|
|
Failed to load local shard "/srv/data/qdrant/storage/collections/funk-docs/0":
|
|
Can't parse version from ".../segments/784eab54-.../version.info",
|
|
error: unexpected character 'D' while parsing minor version number
|
|
```
|
|
|
|
Le fichier `version.info` du segment contient `0.D\0` au lieu d'un numéro de version — corruption de données (première occurrence le 2026-06-05 à 21h10).
|
|
|
|
### Résolution (crash-loop résolu le 2026-06-17 ; re-ingest encore à faire)
|
|
|
|
La collection `funk-docs` est entièrement reconstructible depuis `admin/` :
|
|
|
|
```bash
|
|
sudo systemctl stop qdrant
|
|
sudo rm -rf /srv/data/qdrant/storage/collections/funk-docs
|
|
sudo systemctl start qdrant
|
|
curl -s http://127.0.0.1:6333/collections # doit répondre
|
|
/usr/local/bin/rag-ingest # ré-indexe /srv/data/rag/docs
|
|
```
|
|
|
|
> **État au 2026-06-17** : les 3 premières étapes (stop + drop `funk-docs` + start) ont été
|
|
> appliquées sur s01 pour sortir Qdrant du crash-loop (cf. `admin/ia/stt.md`, jalon 5c). Le
|
|
> service Qdrant et la mémoire STT (`stt-memory`) sont donc opérationnels, **mais** `rag-ingest`
|
|
> n'a pas encore été relancé : la collection `funk-docs` est vide → `rag-query` reste muet
|
|
> tant que l'index n'est pas reconstruit.
|
|
|
|
### Prévention
|
|
|
|
- Ajouter une alerte Prometheus sur les unités systemd en `activating` prolongé (`node_systemd_unit_state`) — un crash-loop n'apparaît ni dans `failed` ni dans les alertes actuelles
|
|
|
|
---
|
|
|
|
## Index
|
|
|
|
| Date | Composant | Résumé | Sévérité |
|
|
|---|---|---|---|
|
|
| 2026-06-05 | Qdrant | **Résolu 2026-06-17** — crash-loop corrigé (drop `funk-docs`) ; RAG à re-ingérer | Important |
|
|
| 2026-05-29 | RAID5 / sdb + storage-01 | sdb ATA bus errors sous I/O — migration /srv/data du RAID vers NVMe | Important |
|
|
| 2026-05-27 | RAID5 / sdd | Disque sdd défaillant (44 secteurs morts) — corruptions multiples en cascade | Critique |
|
|
| 2026-05-14 | Grafana | OOMKilled — limite 256Mi trop serrée pour Grafana 13 | Warning |
|
|
| 2026-05-13 | AlertManager | Receiver "null" non défini — ReconciliationFailed | Warning |
|
|
| 2026-05-13 | llama-server | `/metrics` retourne 501 Not Implemented — flag `--metrics` absent | Warning |
|
|
| 2026-05-13 | nftables storage-01 | Règle monitoring ajoutée après le drop — paquets bloqués | Warning |
|
|
| 2026-05-13 | storage-01 | Corruption EXT4 + réinstallation hermes-agent | Critique |
|
|
| 2026-05-11 | storage-01 | Boucle fsck après coupure de courant — XFS corrompu | Critique |
|
|
|
|
---
|
|
|
|
## 2026-05-29 — Migration /srv/data : RAID5 → NVMe (sdb ATA bus errors)
|
|
|
|
### Contexte
|
|
|
|
Suite à l'incident du 2026-05-27 (sdd retiré), le RAID5 tournait déjà en dégradé `[4/3] [UUU_]`. Décision prise de migrer `/srv/data` du RAID vers le LV NVMe (`almalinux-home`, 845 GB XFS) pour sortir les données d'un RAID en mauvais état.
|
|
|
|
### Symptômes déclencheurs
|
|
|
|
Lors du lancement du rsync de migration, le processus se bloque en état `D` (uninterruptible sleep) :
|
|
|
|
```
|
|
dmesg:
|
|
[ 1341.231068] sd 1:0:0:0: [sdb] FAILED Result: hostbyte=DID_OK
|
|
[ 1341.231082] I/O error, dev sdb, sector 582656 op 0x0:(READ)
|
|
[ 1358.639065] ata2.00: res 40/00:ff:ff:00:00/... Emask 0x50 (ATA bus error)
|
|
[ 1451.541751] md/raid:md0: Disk failure on sdb2, disabling device.
|
|
```
|
|
|
|
`sdb` génère des ATA bus errors sous charge I/O soutenue (câble SATA ou port instable). SMART passe (`PASSED`, aucun secteur défaillant) mais `Raw_Read_Error_Rate = 124014439` — problème d'interface, pas de plateau.
|
|
|
|
### Résolution — migration complète
|
|
|
|
**Étape 1 — Stopper les services**
|
|
```bash
|
|
sudo systemctl stop hermes-agent hermes-dashboard litellm qdrant postgresql-16 alertmanager-webhook
|
|
```
|
|
|
|
**Étape 2 — Préparer la destination NVMe**
|
|
```bash
|
|
sudo mkdir -p /home/data
|
|
sudo mount --bind /home/data /srv/data-new # vérification préalable
|
|
```
|
|
|
|
**Étape 3 — Gérer sdb (blocage rsync)**
|
|
|
|
Le premier rsync (avec sdb actif) se bloque en état `D`. Solution : marquer sdb comme défaillant pour que le RAID lise depuis sda/sdc/sdd uniquement.
|
|
|
|
```bash
|
|
sudo kill <pid_rsync_bloqué>
|
|
sudo mdadm --manage /dev/md0 --fail /dev/sdb2
|
|
# → [4/3] [U_UU] — sdb hors circuit
|
|
```
|
|
|
|
**Étape 4 — Rsync (RAID → NVMe)**
|
|
```bash
|
|
sudo nohup rsync -aHX --info=progress2 /srv/data/ /home/data/ > /tmp/rsync-migration.log 2>&1 &
|
|
# Durée : ~35s — 205 MB/s — 5106 fichiers — exit code 23 (xattr SELinux non critiques)
|
|
```
|
|
|
|
**Étape 5 — Corriger la corruption Qdrant**
|
|
|
|
Un `version.info` de segment RocksDB copié depuis le RAID avec sdb défaillant était corrompu :
|
|
```bash
|
|
sudo cat /srv/data/qdrant/storage/collections/funk-docs/0/segments/784eab54-.../version.info
|
|
# → 0.D\0 (corrompu — devrait être 0.6.0)
|
|
printf '0.6.0' | sudo tee /srv/data/qdrant/storage/collections/funk-docs/0/segments/784eab54-.../version.info
|
|
```
|
|
|
|
**Étape 6 — Basculer /srv/data vers NVMe**
|
|
```bash
|
|
sudo umount /srv/data # démonte le RAID
|
|
sudo umount /srv/data-new # démonte le mount intermédiaire
|
|
sudo mount --bind /home/data /srv/data
|
|
```
|
|
|
|
**Étape 7 — Mettre à jour fstab**
|
|
```bash
|
|
# Remplacer l'entrée RAID par le bind mount
|
|
# Avant : UUID=3add8360-... /srv/data ext4 defaults,noatime,nodiratime 0 0
|
|
# Après :
|
|
echo '/home/data /srv/data none bind 0 0' | sudo tee -a /etc/fstab
|
|
# (commenter l'ancienne ligne UUID=3add8360)
|
|
```
|
|
|
|
**Étape 8 — Redémarrer les services**
|
|
```bash
|
|
sudo systemctl start postgresql-16 qdrant litellm hermes-agent hermes-dashboard alertmanager-webhook
|
|
```
|
|
|
|
### État post-migration
|
|
|
|
| Composant | Avant | Après |
|
|
|---|---|---|
|
|
| `/srv/data` | RAID5 ext4 `/dev/md0` (dégradé) | NVMe XFS bind-mount `/home/data` |
|
|
| Espace disponible | 2.6 TB RAID (dégradé, risqué) | 801 GB NVMe (sûr) |
|
|
| RAID5 md0 | `[4/3] [UUU_]` actif | `[4/3] [U_UU]` — sdb `(F)`, **plus monté** |
|
|
| Tous les services | Stoppés | ✅ Actifs |
|
|
|
|
### Actions restantes
|
|
|
|
- **Retirer sdb physiquement** (ou le supprimer du RAID) :
|
|
```bash
|
|
sudo mdadm --manage /dev/md0 --remove /dev/sdb2
|
|
```
|
|
- **Décider du sort du RAID** : les données sont sur NVMe. Le RAID peut être démonté définitivement ou conservé pour une future migration vers un NAS.
|
|
- Vérifier câble SATA de sdb (ATA bus errors = câble ou port, pas plateau).
|
|
|
|
---
|
|
|
|
## 2026-05-27 — RAID5 : défaillance sdd — corruptions multiples en cascade
|
|
|
|
### Symptômes
|
|
|
|
Au démarrage du cluster (`funk-start --k8s`) :
|
|
|
|
- Qdrant en `CrashLoopBackOff` : `RocksDB open error: Corruption: no log_file_number ... MANIFEST-000033 may be corrupted`
|
|
- Grafana en `CrashLoopBackOff` : `pq: relation mapping file "base/24737/pg_filenode.map" contains invalid data`
|
|
- LiteLLM DB : `ERROR: invalid page in block 0 of relation base/16385/2838`
|
|
- Prometheus en `CrashLoopBackOff` : `corrupted block 01KSGFC9WP7STGTXWDNECY2FS0: read symbols: invalid checksum`
|
|
- Docker registry retournant 500 sur toutes les requêtes : `filesystem: stat ... data: input/output error`
|
|
- `sacrifice-web` en `ImagePullBackOff` (registry inaccessible)
|
|
|
|
Pattern observé : corruptions récurrentes tous les 3-4 démarrages depuis ~7 semaines.
|
|
|
|
### Cause racine
|
|
|
|
Disque `sdd` (WDC WD10EALX-009BA0, S/N WD-WCATR9001223) en défaillance progressive :
|
|
|
|
```
|
|
Current_Pending_Sector : 44 ← secteurs illisibles, non réalloués
|
|
Offline_Uncorrectable : 44 ← secteurs confirmés irrécupérables
|
|
Power_On_Hours : 52816 ← 6 ans d'utilisation (MTBF constructeur = 5 ans)
|
|
```
|
|
|
|
Historique des self-tests SMART (tous en échec) :
|
|
```
|
|
#1 Short LBA 1555355176 read failure (nouveau secteur mort)
|
|
#2 Short LBA 1413976229 read failure
|
|
#4 Extended LBA 1413976229 read failure (premier secteur mort, découvert il y a ~49 jours)
|
|
```
|
|
|
|
**Mécanisme de corruption silencieuse :**
|
|
|
|
Le RAID dit `[4/4] [UUUU]` et `State: clean` car sdd ne retourne pas d'erreur au moment de l'écriture — son write-back cache (activé) acquitte l'écriture avant de la commettre sur le plateau. La donnée qui tombait sur les secteurs défaillants était silencieusement perdue, la parité RAID5 devenait incohérente avec les données réelles. Le RAID n'en savait rien.
|
|
|
|
À chaque session d'utilisation (~10-12h), les services NFS/k8s écrivaient sur `/srv/data`. Une fraction des writes tombait sur les zones corrompues de sdd et accumulait de la corruption dans les métadonnées ext4 (directory blocks, btree). Au bout de 3-4 sessions, assez de structures critiques étaient corrompues pour faire crasher les services.
|
|
|
|
**Problèmes secondaires identifiés :**
|
|
- `sda` : `UDMA_CRC_Error_Count = 6` → câble SATA défaillant ou port SATA instable
|
|
- `sdb` : `Start_Stop_Count = 17780` pour 8847h → spin-down APM trop agressif (~49 cycles/jour)
|
|
- Tous les disques : write-back cache activé sans onduleur → risque de corruption sur coupure de courant
|
|
|
|
### Résolution — corruptions de données
|
|
|
|
**Qdrant :** collection `funk-docs` supprimée et réingérée.
|
|
```bash
|
|
sudo systemctl stop qdrant
|
|
sudo rm -rf /srv/data/qdrant/storage/collections/funk-docs
|
|
sudo systemctl start qdrant
|
|
rag-ingest # → 308 chunks réindexés
|
|
```
|
|
|
|
**PostgreSQL — bases grafana et litellm :**
|
|
```bash
|
|
sudo systemctl stop litellm
|
|
sudo -u postgres psql -c "DROP DATABASE litellm;"
|
|
sudo -u postgres psql -c "CREATE DATABASE litellm OWNER litellm;"
|
|
sudo -u postgres psql -c "DROP DATABASE grafana;"
|
|
sudo -u postgres psql -c "CREATE DATABASE grafana OWNER grafana;"
|
|
sudo systemctl start litellm
|
|
kubectl rollout restart deployment/kube-prometheus-stack-grafana -n monitoring
|
|
# → Grafana rejoue 709 migrations, recrée le schéma
|
|
```
|
|
|
|
**Prometheus TSDB :** deux blocs corrompus supprimés du NFS.
|
|
```bash
|
|
PROM_NFS="/srv/data/nfs/k8s/monitoring-prometheus-...-pvc-aa1a187f-.../prometheus-db"
|
|
sudo rm -rf "$PROM_NFS/01KSGF0DXNXJ4HC5CEZX9THT5B"
|
|
sudo rm -rf "$PROM_NFS/01KSGFC9WP7STGTXWDNECY2FS0"
|
|
kubectl delete pod prometheus-kube-prometheus-stack-prometheus-0 -n monitoring
|
|
```
|
|
|
|
**Docker registry :** PVC corrompu recréé (NFS provisioner génère un répertoire propre).
|
|
```bash
|
|
kubectl scale deployment registry -n infra --replicas=0
|
|
kubectl delete pvc registry-pvc -n infra
|
|
kubectl delete pv pvc-c5e1e86e-da56-4b31-bf52-07d5d619c9ea
|
|
# Recréer la PVC — le NFS provisioner provisionne un nouveau répertoire
|
|
kubectl apply -f - <<EOF
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: registry-pvc
|
|
namespace: infra
|
|
spec:
|
|
accessModes: [ReadWriteOnce]
|
|
storageClassName: nfs
|
|
resources:
|
|
requests:
|
|
storage: 10Gi
|
|
EOF
|
|
kubectl scale deployment registry -n infra --replicas=1
|
|
```
|
|
|
|
**sacrifice-web :** image rebuildée et pushée via tunnel SSH.
|
|
```bash
|
|
# Tunnel SSH pour atteindre le registry depuis le poste perso
|
|
ssh -f -N -L 31500:192.168.10.11:31500 storage-01
|
|
cd /path/to/Sacrifice/sacrifice-web
|
|
podman build -t localhost:31500/sacrifice-web:latest .
|
|
podman push localhost:31500/sacrifice-web:latest --tls-verify=false
|
|
kubectl rollout restart deployment/sacrifice-web -n sacrifice
|
|
```
|
|
|
|
### Résolution — cause racine (sdd retiré du RAID)
|
|
|
|
```bash
|
|
# Marquer sdd comme défaillant et le retirer
|
|
sudo mdadm --manage /dev/md0 --fail /dev/sdd1
|
|
sudo mdadm --manage /dev/md0 --remove /dev/sdd1
|
|
# → State: clean, degraded [4/3] [UUU_]
|
|
|
|
# Persister la configuration
|
|
sudo mdadm --detail --scan | sudo tee /etc/mdadm.conf
|
|
sudo dracut --force # régénérer l'initramfs
|
|
```
|
|
|
|
### État post-incident
|
|
|
|
| Service | État |
|
|
|---|---|
|
|
| RAID5 md0 | `[4/3] [UUU_]` — dégradé, **zéro redondance** jusqu'au remplacement de sdd |
|
|
| Qdrant | ✅ 308 chunks réindexés |
|
|
| PostgreSQL grafana | ✅ Schéma recréé, dashboards reprovisionnés |
|
|
| PostgreSQL litellm | ✅ Schéma recréé, config modèles intacte (perte de l'historique spend) |
|
|
| Prometheus | ✅ Running — perte des ~2 derniers blocs TSDB (quelques heures de métriques) |
|
|
| Docker registry | ✅ PVC propre, image sacrifice-web repushée |
|
|
| sacrifice-web | ✅ Running, HTTP 200 |
|
|
|
|
### Actions requises (non résolues)
|
|
|
|
- **Remplacer sdd** (1TB+, ex. WD Red ou Seagate IronWolf) et relancer la reconstruction :
|
|
```bash
|
|
sudo mdadm --manage /dev/md0 --add /dev/sdNEW1
|
|
# Reconstruction automatique ~4h, visible dans /proc/mdstat
|
|
```
|
|
- **Câble SATA sda** : remplacer le câble (UDMA_CRC_Error_Count=6)
|
|
- **APM sdb** : désactiver le spin-down (`sudo hdparm -B 254 /dev/sdb`) et persister via udev
|
|
- **Onduleur (UPS)** : indispensable — write-back cache activé sur tous les disques
|
|
- **e2fsck** : planifier une fenêtre de maintenance pour vérifier les métadonnées ext4 restantes :
|
|
```bash
|
|
sudo systemctl stop nfs-server qdrant postgresql-16 litellm hermes-agent
|
|
sudo umount /srv/data
|
|
sudo e2fsck -f /dev/md0
|
|
sudo mount /srv/data && sudo systemctl start nfs-server qdrant postgresql-16 litellm hermes-agent
|
|
```
|
|
|
|
---
|
|
|
|
## 2026-05-14 — Grafana : OOMKilled (limite mémoire trop serrée)
|
|
|
|
### Symptôme
|
|
|
|
Erreurs "No available server" intermittentes sur `grafana.lab.local`. Pod en CrashLoop.
|
|
|
|
```bash
|
|
kubectl describe pod -n monitoring -l app.kubernetes.io/name=grafana
|
|
# → Last State: Terminated, Reason: OOMKilled, Exit Code: 137
|
|
# → RESTARTS: 5
|
|
```
|
|
|
|
### Cause
|
|
|
|
Limite mémoire à 256Mi dans `k8s/infra/monitoring/values.yaml`. Grafana 13 consomme plus que ses prédécesseurs — OOM systématique. Traefik perd le backend pendant chaque redémarrage.
|
|
|
|
### Résolution
|
|
|
|
Augmenter les limites dans `k8s/infra/monitoring/values.yaml` :
|
|
|
|
```yaml
|
|
grafana:
|
|
resources:
|
|
requests:
|
|
memory: 256Mi
|
|
limits:
|
|
memory: 1Gi # était 256Mi
|
|
```
|
|
|
|
`git push` → ArgoCD applique → pod redémarre proprement.
|
|
|
|
---
|
|
|
|
## 2026-05-13 — AlertManager : ReconciliationFailed — receiver "null" non défini
|
|
|
|
### Symptôme
|
|
|
|
AlertManager en erreur dans ArgoCD. Logs :
|
|
```
|
|
level=error msg="loading configuration" err="undefined receiver \"null\" used in route"
|
|
```
|
|
|
|
### Cause
|
|
|
|
kube-prometheus-stack génère en interne une sous-route référençant le receiver `"null"` pour le heartbeat Watchdog. Une config AlertManager custom qui ne définissait pas ce receiver cassait la validation.
|
|
|
|
### Résolution
|
|
|
|
Ajouter explicitement le receiver et la route dans `values.yaml` :
|
|
|
|
```yaml
|
|
alertmanager:
|
|
config:
|
|
route:
|
|
routes:
|
|
- matchers:
|
|
- alertname = "Watchdog"
|
|
receiver: "null"
|
|
repeat_interval: 24h
|
|
receivers:
|
|
- name: "null" # obligatoire même si vide
|
|
```
|
|
|
|
---
|
|
|
|
## 2026-05-13 — llama-server : /metrics retourne 501 Not Implemented
|
|
|
|
### Symptôme
|
|
|
|
Prometheus ne scrappe rien sur les jobs `llama-server-*`. Targets en erreur avec `501 Not Implemented`.
|
|
|
|
### Cause
|
|
|
|
Le flag `--metrics` doit être passé explicitement à llama-server pour activer l'endpoint `/metrics`. Sans lui, la route existe mais répond 501.
|
|
|
|
### Résolution
|
|
|
|
Ajouter `--metrics` dans le service systemd (template Ansible `llama-server.service.j2`) :
|
|
|
|
```ini
|
|
ExecStart=/opt/llama.cpp/build/bin/llama-server \
|
|
...
|
|
--metrics \
|
|
--log-disable
|
|
```
|
|
|
|
Fix live sur les 3 instances + `daemon-reload` + restart :
|
|
```bash
|
|
# Sur gpu-01
|
|
for svc in llama-server llama-server-system llama-server-monitor; do
|
|
sudo sed -i 's/--log-disable/--metrics \\\n --log-disable/' /etc/systemd/system/$svc.service
|
|
done
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl restart llama-server llama-server-system llama-server-monitor
|
|
```
|
|
|
|
---
|
|
|
|
## 2026-05-13 — nftables storage-01 : règle monitoring bloquée par le drop
|
|
|
|
### Symptôme
|
|
|
|
Prometheus ne pouvait pas scrapper `storage-01:9100` (node_exporter) ni recevoir les webhooks AlertManager sur `:9093`. Targets en `connection refused` dans Prometheus.
|
|
|
|
### Cause
|
|
|
|
`nft add rule` ajoute la règle **en fin de chaîne**, après la règle terminale `log prefix "nft-drop:" drop`. Les paquets étaient droppés avant d'atteindre la nouvelle règle.
|
|
|
|
```bash
|
|
# Vérifier l'ordre
|
|
sudo nft -n -a list chain inet filter input
|
|
# → handle 22 : log drop (terminal)
|
|
# → handle 27 : tcp dport { 9093, 9100 } accept (ajouté APRÈS → jamais atteint)
|
|
```
|
|
|
|
### Résolution
|
|
|
|
Supprimer la règle mal placée et la réinsérer **avant** le drop avec `insert rule position` :
|
|
|
|
```bash
|
|
sudo nft delete rule inet filter input handle 27
|
|
sudo nft insert rule inet filter input position 22 \
|
|
tcp dport { 9093, 9100 } ip saddr 192.168.10.0/24 accept
|
|
```
|
|
|
|
Fix permanent dans le template Ansible `nftables.conf.j2` : placer la règle avant la règle drop.
|
|
|
|
---
|
|
|
|
## 2026-05-13 — storage-01 : corruption EXT4 après arrêt brutal + reinstall hermes-agent
|
|
|
|
### Symptômes
|
|
|
|
- `hermes-agent` en boucle de crash : `SyntaxError: source code string cannot contain null bytes`
|
|
- Erreurs EXT4 au démarrage des services : `Directory block failed checksum`, `deleted inode referenced`
|
|
- `dmesg` : `EXT4-fs (md0): error count since last fsck: 655`
|
|
- `sdb` : erreurs ATA bus (`SError: { RecovComm HostInt PHYRdyChg PHYInt }`) et I/O error sector 13405184
|
|
|
|
### Cause racine
|
|
|
|
Arrêt brutal du cluster la veille (`funk-stop --k8s`) → journal ext4 non rejoué correctement → 655 erreurs de corruption sur `/dev/md0`. `sdb` avait des erreurs transitoires mais SMART PASSED (pas de défaillance matérielle).
|
|
|
|
### Résolution étape par étape
|
|
|
|
**1. Vérifier SMART sdb**
|
|
|
|
```bash
|
|
smartctl -H /dev/sdb
|
|
# SMART overall-health self-assessment test result: PASSED → purement logiciel
|
|
```
|
|
|
|
**2. Arrêter les services et démonter**
|
|
|
|
```bash
|
|
sudo systemctl stop hermes-agent litellm qdrant postgresql-16 nfs-server
|
|
sudo umount /srv/data
|
|
```
|
|
|
|
**3. Réparer le filesystem**
|
|
|
|
```bash
|
|
sudo e2fsck -f -y /dev/md0
|
|
# 655 erreurs corrigées : HTREE invalides, blocs multiplement revendiqués,
|
|
# checksums de répertoires incorrects, compteurs d'inodes wronge
|
|
```
|
|
|
|
**4. Remonter et redémarrer les services**
|
|
|
|
```bash
|
|
sudo mount /srv/data
|
|
sudo systemctl start postgresql-16 qdrant litellm hermes-agent nfs-server
|
|
```
|
|
|
|
**5. Hermes-agent toujours en erreur après fsck**
|
|
|
|
Le e2fsck a zéroïsé des blocs appartenant à plusieurs inodes simultanément → des fichiers du venv Python et du code source `hermes_cli/` ont été corrompus (null bytes).
|
|
|
|
Tentatives de réparation du venv échouées (`pip install -e .` crash, `uv.lock` corrompu).
|
|
|
|
**6. Réinstallation complète de hermes-agent**
|
|
|
|
```bash
|
|
# Supprimer le code source corrompu (les profils dans /srv/data/hermes/profiles/ ne sont PAS touchés)
|
|
sudo rm -rf /srv/data/hermes/hermes-agent
|
|
sudo rm /opt/hermes/.local/bin/hermes
|
|
|
|
# Réinstaller depuis le script officiel (depuis un répertoire valide)
|
|
cd /srv/data/hermes
|
|
sudo -u hermes bash -c 'cd /srv/data/hermes && HOME=/opt/hermes HERMES_HOME=/srv/data/hermes curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash'
|
|
```
|
|
|
|
> Lors du `sudo rm -rf`, ne pas rester dans le répertoire supprimé — le shell perd le CWD et le script d'installation échoue avec `getcwd: cannot access parent directories`.
|
|
|
|
**Résultat** : hermes-agent réinstallé dans `/opt/hermes/.hermes/hermes-agent/` (SSD OS, plus de RAID5). Tous les profils (`funk-ai`, `brain`, `system`, `monitor`) intacts dans `/srv/data/hermes/profiles/`.
|
|
|
|
### Changement d'architecture post-incident
|
|
|
|
| Avant | Après |
|
|
|---|---|
|
|
| Code hermes-agent : `/srv/data/hermes/hermes-agent/` (RAID5) | Code hermes-agent : `/opt/hermes/.hermes/hermes-agent/` (SSD OS) |
|
|
| Venv : `/srv/data/hermes/hermes-agent/venv/` | Venv : `/opt/hermes/.hermes/hermes-agent/venv/` |
|
|
| Profils/données : `/srv/data/hermes/` | Profils/données : `/srv/data/hermes/` (inchangé) |
|
|
|
|
Le code étant désormais sur le SSD, une corruption future du RAID5 n'impactera plus l'installation — seulement les profils et données.
|
|
|
|
### Surveillance post-incident
|
|
|
|
```bash
|
|
# Santé RAID et disques
|
|
cat /proc/mdstat
|
|
smartctl -H /dev/sdb # à surveiller
|
|
|
|
# Vérifier que e2fsck n'a pas schedulé un check au prochain boot
|
|
sudo tune2fs -l /dev/md0 | grep -E "check|count|error"
|
|
```
|
|
|
|
---
|
|
|
|
## 2026-05-11 — storage-01 : boucle fsck après coupure de courant
|
|
|
|
### Symptômes
|
|
|
|
- Boucle infinie de `fsck` au démarrage sur `/dev/md0`
|
|
- `You are in emergency mode. Give root password for maintenance` — mot de passe impossible à saisir (messages défilants)
|
|
- Après résolution : `hermes-agent` en boucle d'erreurs (cause : `/srv/data` non monté)
|
|
|
|
### Architecture concernée
|
|
|
|
| Composant | Détail |
|
|
|---|---|
|
|
| Disque système | NVMe `nvme0n1` — LVM (`almalinux-root` XFS 70G, swap 14.7G, home 845G) |
|
|
| RAID données | RAID5 software `md0` — 4 disques SATA 931.5G (`sda1`, `sdb2`, `sdc1`, `sdd1`) |
|
|
| Point de montage | `/srv/data` (ext4) |
|
|
|
|
### Cause racine
|
|
|
|
La coupure de courant a corrompu le système de fichiers **XFS** sur `almalinux-root`. Au redémarrage, systemd tentait de vérifier `/srv/data` avant que le RAID `md0` soit assemblé → boucle bloquante.
|
|
|
|
### Résolution étape par étape
|
|
|
|
**1. Shell de secours via GRUB**
|
|
|
|
Au démarrage, appuyer sur `Shift` pour afficher le menu GRUB. Appuyer sur `e` pour éditer la ligne `linux` :
|
|
- Remplacer `ro` par `rw`
|
|
- Ajouter `init=/bin/bash` en fin de ligne
|
|
|
|
Démarrer avec `Ctrl+X`.
|
|
|
|
**2. Activer le LVM**
|
|
|
|
```bash
|
|
lvm vgchange -ay
|
|
# 3 logical volume(s) in volume group "almalinux" now active
|
|
```
|
|
|
|
**3. Réparer le XFS (pas fsck)**
|
|
|
|
XFS nécessite `xfs_repair`, pas `fsck` :
|
|
|
|
```bash
|
|
umount /dev/mapper/almalinux-root
|
|
xfs_repair /dev/mapper/almalinux-root
|
|
# Phases 1 à 7 — succès
|
|
```
|
|
|
|
**4. Désactiver temporairement `/srv/data` dans fstab**
|
|
|
|
```bash
|
|
vi /etc/fstab
|
|
# Commenter la ligne /srv/data pour permettre le boot sans RAID
|
|
```
|
|
|
|
**5. Reboot** → système normal, RAID intact `[4/4] [UUUU]`.
|
|
|
|
### Fix permanent — fstab
|
|
|
|
Modifier la ligne `/srv/data` dans `/etc/fstab` :
|
|
|
|
```
|
|
# Avant
|
|
UUID=3add8360-fa01-47eb-0aa1-0e84bacbbc15 /srv/data ext4 defaults,noatime,nodiratime 0 2
|
|
|
|
# Après
|
|
UUID=3add8360-fa01-47eb-0aa1-0e84bacbbc15 /srv/data ext4 defaults,noatime,nodiratime,_netdev 0 0
|
|
```
|
|
|
|
| Changement | Effet |
|
|
|---|---|
|
|
| `0 2` → `0 0` | Désactive la vérification fsck automatique au boot |
|
|
| `_netdev` | Force systemd à attendre que tous les périphériques (RAID) soient prêts avant de monter |
|
|
|
|
### Surveillance post-incident
|
|
|
|
```bash
|
|
# État du RAID
|
|
cat /proc/mdstat
|
|
|
|
# Santé des disques (sdb a généré des erreurs I/O — à surveiller)
|
|
smartctl -a /dev/sda
|
|
smartctl -a /dev/sdb
|
|
smartctl -a /dev/sdc
|
|
smartctl -a /dev/sdd
|
|
|
|
# Monter /srv/data manuellement si besoin
|
|
mount /srv/data
|
|
|
|
# Logs de boot
|
|
journalctl -xb | grep -i "error\|fail"
|
|
```
|
|
|
|
### Points d'attention
|
|
|
|
- `sdb` a généré des erreurs I/O pendant l'incident — il est revenu opérationnel mais doit être surveillé régulièrement avec `smartctl`.
|
|
- Envisager un **onduleur (UPS)** pour prévenir ce type d'incident sur coupure de courant.
|
|
- Le fix fstab (`_netdev`, `0 0`) est permanent — ne pas revenir aux valeurs précédentes.
|