fix(redis) — il mourait toutes les 90 s, et c'est le .fr qui tombait #28

Merged
arcodange merged 1 commits from arcodange/redis-sonde into main 2026-07-29 20:23:48 +02:00
Owner

Le symptôme, et pourquoi il ment

kadans.arcodange.fr et gitea.arcodange.fr en 403, corps vide, depuis n'importe quel client extérieur — pendant que arcodange.fr et www.arcodange.fr répondaient 200. Ça ressemble à un bannissement d'IP. Ça n'en était pas un : cscli decisions list ne portait aucune décision locale (76 alertes, toutes CAPI), et le plugin journalisait isBanned:false du début à la fin.

La chaîne réelle

  1. Le sous-chart pascaliske/redis 2.1.0 fige ses sondes à timeoutSeconds: 1 sur redis-cli ping, et n'expose aucune valeur pour les surcharger.
  2. Sans réservation de ressources, le conteneur est en QoS BestEffort : sur un Raspberry Pi chargé, le simple lancement de redis-cli dépasse la seconde.
  3. Liveness probe failed: command timed out: "redis-cli ping" timed out after 1s836 fois en 23 jours, 135 redémarrages, SIGTERM après ~90 s de vie à chaque tour (exitCode: 0, reason: Completed — il ne plantait pas, il était tué).
  4. Le plugin crowdsec de Traefik utilise ce Redis comme cache de décisions. Cache injoignable ⇒ isCrowdsecStreamHealthy:falserefus par défaut de tout client absent de clientTrustedIPs ⇒ le 403.

D'où le motif trompeur : seuls les hôtes portant le middleware crowdsec tombaient, et depuis le LAN192.168.1.0/24 est dans clientTrustedIPs — tout paraissait sain, l'origine rendant son 401 d'authentification normal.

⚠ Et comme Redis clignotait (90 s debout, puis mort, puis backoff), l'accès était intermittent : ça expliquait « ça marchait tout à l'heure ».

Ce que ce commit corrige, et ce qu'il ne corrige pas

La réservation fait passer le conteneur en Burstable et lui garantit sa part. Les limites restent larges — Redis n'est pas ce qui sature ce nœud.

Ce commit ne corrige PAS la sonde elle-même. Elle reste à 1 s, et elle reste inatteignable depuis les valeurs. Si le clignotement revient malgré la réservation, il faudra un patch Kustomize au niveau de l'Application ArgoCD, ou abandonner ce sous-chart.

Une correction à chaud a été appliquée en production pour rétablir l'accès immédiatement (timeoutSeconds: 5, failureThreshold: 6 sur le StatefulSet, puis rollout restart de Traefik pour que le plugin réinitialise son cache). L'Application ArgoCD a selfHeal: true : elle sera ré-écrasée. Cette correction à chaud n'est pas le correctif — ce commit l'est.

Vérifié

helm template rend bien requests: {cpu: 50m, memory: 64Mi}, limits: {memory: 256Mi}
YAML valide
Après remise en état, kadans.arcodange.fr 401 (défi d'authentification normal)
Après remise en état, gitea.arcodange.fr 200
Plugin crowdsec cache:New initialized isRedis:true — plus aucun redis:unreachable
redis-0 1/1 Running, 0 redémarrage

Trois fausses pistes, pour mémoire

Cloudflare (le cf-ray ne prouve rien : Cloudflare relaie aussi les réponses de l'origine), un bannissement crowdsec, une règle de pare-feu. Le test qui a tranché : envoyer une requête sur un chemin unique et vérifier si l'origine la voit dans ses journaux. Elle la voyait — donc le refus venait bien du homelab.

⚠ Et un test témoin indispensable : sonder avec une IP connue bannie dans CF-Connecting-IP rendait 401, pas 403. La sonde par en-tête forgé était donc incapable de détecter un bannissement — elle ne prouvait rien, et sans ce témoin elle aurait innocenté crowdsec à tort.

## Le symptôme, et pourquoi il ment `kadans.arcodange.fr` et `gitea.arcodange.fr` en **403, corps vide**, depuis n'importe quel client extérieur — pendant que `arcodange.fr` et `www.arcodange.fr` répondaient **200**. Ça ressemble à un bannissement d'IP. Ça n'en était pas un : `cscli decisions list` ne portait **aucune** décision locale (76 alertes, toutes CAPI), et le plugin journalisait `isBanned:false` du début à la fin. ## La chaîne réelle 1. Le sous-chart `pascaliske/redis 2.1.0` **fige** ses sondes à `timeoutSeconds: 1` sur `redis-cli ping`, et n'expose **aucune valeur** pour les surcharger. 2. Sans réservation de ressources, le conteneur est en QoS **`BestEffort`** : sur un Raspberry Pi chargé, le simple lancement de `redis-cli` dépasse la seconde. 3. `Liveness probe failed: command timed out: "redis-cli ping" timed out after 1s` — **836 fois en 23 jours**, 135 redémarrages, SIGTERM après ~90 s de vie à chaque tour (`exitCode: 0`, `reason: Completed` — il ne plantait pas, il était tué). 4. Le plugin crowdsec de Traefik utilise ce Redis comme **cache de décisions**. Cache injoignable ⇒ `isCrowdsecStreamHealthy:false` ⇒ **refus par défaut** de tout client absent de `clientTrustedIPs` ⇒ le 403. D'où le motif trompeur : **seuls les hôtes portant le middleware crowdsec tombaient**, et **depuis le LAN** — `192.168.1.0/24` est dans `clientTrustedIPs` — tout paraissait sain, l'origine rendant son 401 d'authentification normal. ⚠ Et comme Redis *clignotait* (90 s debout, puis mort, puis backoff), l'accès était **intermittent** : ça expliquait « ça marchait tout à l'heure ». ## Ce que ce commit corrige, et ce qu'il ne corrige pas La réservation fait passer le conteneur en **`Burstable`** et lui garantit sa part. Les limites restent larges — Redis n'est pas ce qui sature ce nœud. ⚠ **Ce commit ne corrige PAS la sonde elle-même.** Elle reste à 1 s, et elle reste inatteignable depuis les valeurs. Si le clignotement revient malgré la réservation, il faudra un patch Kustomize au niveau de l'Application ArgoCD, ou abandonner ce sous-chart. ⚠ **Une correction à chaud a été appliquée en production** pour rétablir l'accès immédiatement (`timeoutSeconds: 5`, `failureThreshold: 6` sur le StatefulSet, puis `rollout restart` de Traefik pour que le plugin réinitialise son cache). L'Application ArgoCD a **`selfHeal: true`** : elle sera ré-écrasée. **Cette correction à chaud n'est pas le correctif — ce commit l'est.** ## Vérifié | | | |---|---| | `helm template` | rend bien `requests: {cpu: 50m, memory: 64Mi}`, `limits: {memory: 256Mi}` | | YAML | valide | | Après remise en état, `kadans.arcodange.fr` | **401** (défi d'authentification normal) | | Après remise en état, `gitea.arcodange.fr` | **200** | | Plugin crowdsec | `cache:New initialized isRedis:true` — plus aucun `redis:unreachable` | | `redis-0` | `1/1 Running`, 0 redémarrage | ## Trois fausses pistes, pour mémoire Cloudflare (le `cf-ray` ne prouve rien : Cloudflare relaie aussi les réponses de l'origine), un bannissement crowdsec, une règle de pare-feu. Le test qui a tranché : envoyer une requête sur un **chemin unique** et vérifier si l'origine la voit dans ses journaux. Elle la voyait — donc le refus venait bien du homelab. ⚠ Et un test témoin indispensable : sonder avec une IP **connue bannie** dans `CF-Connecting-IP` rendait **401**, pas 403. La sonde par en-tête forgé était donc **incapable de détecter un bannissement** — elle ne prouvait rien, et sans ce témoin elle aurait innocenté crowdsec à tort.
arcodange added 1 commit 2026-07-29 01:57:47 +02:00
fix(redis) — il mourait toutes les 90 s, et c'est le .fr qui tombait
Helm Charts / Detect changed charts (pull_request) Successful in 1m14s
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
f53c3adb7d
Symptôme observé : `kadans.arcodange.fr` et `gitea.arcodange.fr` en 403, corps
vide, depuis n'importe quel client extérieur — pendant que `arcodange.fr` et
`www` répondaient 200. Ça ressemble à un bannissement d'IP. Ça n'en était pas un.

La chaîne, remontée de bout en bout :

1. Le sous-chart fige ses sondes à `timeoutSeconds: 1` sur `redis-cli ping` et
   n'expose aucune valeur pour les surcharger.
2. Sans réservation de ressources, le conteneur est en QoS `BestEffort` : sur un
   Raspberry Pi chargé, lancer `redis-cli` dépasse la seconde.
3. « Liveness probe failed: command timed out after 1s » 836 fois en 23 jours,
   135 redémarrages, SIGTERM après ~90 s de vie à chaque tour.
4. Le plugin crowdsec de Traefik utilise ce Redis comme cache de décisions.
   Cache injoignable ⇒ `isCrowdsecStreamHealthy:false` ⇒ refus par défaut de tout
   client absent de `clientTrustedIPs` ⇒ le 403.

D'où le motif trompeur : seuls les hôtes portant le middleware crowdsec
tombaient, et depuis le LAN (IP de confiance) tout paraissait sain — l'origine
répondait 401, son défi d'authentification normal. Trois fausses pistes en sont
sorties : Cloudflare, un bannissement crowdsec, une règle de pare-feu. Aucune
n'était la bonne, et `cscli decisions list` disait `isBanned:false` du début à la
fin.

La réservation fait passer le conteneur en `Burstable` et lui garantit sa part.
Les limites restent larges : Redis n'est pas ce qui sature ce nœud.

⚠ Ce commit ne corrige PAS la sonde elle-même — elle reste à 1 s, et elle reste
inatteignable depuis les valeurs. Si le clignotement revient malgré la
réservation, il faudra un patch Kustomize au niveau de l'Application ArgoCD, ou
abandonner ce sous-chart. Une vérification en production a été appliquée à chaud
(`timeoutSeconds: 5`, `failureThreshold: 6`) pour rétablir l'accès immédiatement,
mais `selfHeal: true` la ré-écrasera : elle n'est pas la correction, ce commit
l'est.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GdUCA5Uz8QyMwa2P4Pg2hK
arcodange merged commit d2202414c0 into main 2026-07-29 20:23:48 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: arcodange-org/tools#28