fix(crowdsec) — nom de machine stable : 594 LAPI fantômes s'étaient entassées en base #56

Merged
arcodange merged 1 commits from arcodange/crowdsec-machines-stables into main 2026-09-20 19:38:24 +02:00
Owner

Le constat

cscli machines list renvoyait 617 lignes le 2026-09-20, dont 594 crowdsec-lapi-* remontant au 2025-12-05. Une seule LAPI tourne à la fois : 593 étaient mortes.

Enregistrements crowdsec-lapi-* 594
Étendue 2025-12-05 → 2026-09-20 (290 jours)
Moyenne 2,05 / jour
Hashes de ReplicaSet distincts 571 (sur 594)

Le mécanisme n'est pas celui qu'on croit

Ce ne sont pas des redémarrages : un redémarrage garde le nom du pod. Les 571 hashes de ReplicaSet distincts disent autre chose — le pod template change presque à chaque fois.

Ce qui le change, c'est le rolloutRestartTargets du VaultDynamicSecret :

  # Restart these pods when secrets rotated
  rolloutRestartTargets:
  - kind: Deployment
    name: crowdsec-lapi

À chaque rotation de l'identifiant Postgres, VSO force un rollout → nouveau pod template → nouveau hash de ReplicaSet → nouveau nom de pod.

Le chart amont code en dur CUSTOM_HOSTNAME sur metadata.name, et l'entrypoint enregistre la LAPI sous ce nom :

si .login (fichier d'identifiants) == CUSTOM_HOSTNAME et machine existante
    → « Local agent already registered », rien à faire
sinon
    → cscli machines delete <CUSTOM_HOSTNAME> ; cscli machines add

Le delete ne porte que sur le nom courant. L'enregistrement du pod précédent n'est jamais supprimé — d'où l'entassement, sans borne.

Pourquoi ça compte : la LAPI stocke son état dans le PostgreSQL externe de pi2, à max_connections=100 — celui-là même qui a refusé des connexions le 2026-09-20 (SQLSTATE 53300) et fait crasher la LAPI trois fois.

Le correctif

Fixer CUSTOM_HOSTNAME à crowdsec-lapi. Le premier démarrage fait delete+add sur ce nom, tous les suivants tombent sur « already registered » et n'écrivent plus rien. Le fichier d'identifiants survit aux redémarrages (/etc/crowdsec est un lien vers le PVC crowdsec-config, vérifié sur le pod), donc la comparaison sur .login tient dans le temps.

⚠ L'entrée doit vivre dans lapi.env : le chart émet sa propre définition de CUSTOM_HOSTNAME avant d'injecter .Values.lapi.env, et Kubernetes retient la dernière occurrence en cas de doublon. C'est ce qui permet de surcharger un champ que le chart n'expose pas.

Vérifié deux fois plutôt qu'une :

  • helm template place la nôtre en position 7 contre 5 pour celle du chart ;
  • un pod de test portant les deux définitions a renvoyé RESULTAT=crowdsec-lapi, avec l'avertissement attendu hides previous definition.

⚠ Ne pas « corriger » en retirant le rolloutRestartTargets : les identifiants arrivent par secretKeyRef, qui ne se recharge pas à chaud. Sans rollout, la LAPI garderait des identifiants révoqués par Vault.

La purge, déjà faite

Les 614 enregistrements orphelins ont été supprimés en amont (cscli machines delete, par lots de 40), en excluant explicitement les trois pods vivants. Résultat : 617 → 3, heartbeats de l'agent (3 s) et de l'appsec (9 s) toujours frais, aucun pod perturbé.

cscli machines prune aurait été le mauvais outil : il filtre sur le heartbeat, or la LAPI n'en émet pas (DISABLE_AGENT=true, colonne ⚠ -). Elle aurait été supprimée avec les morts. Piège d'autant plus vicieux que 20 enregistrements morts affichaient, eux, un heartbeat — vieux de 160 à 285 jours.

🤖 Generated with Claude Code

## Le constat `cscli machines list` renvoyait **617 lignes** le 2026-09-20, dont **594 `crowdsec-lapi-*`** remontant au 2025-12-05. Une seule LAPI tourne à la fois : 593 étaient mortes. | | | |---|---| | Enregistrements `crowdsec-lapi-*` | 594 | | Étendue | 2025-12-05 → 2026-09-20 (290 jours) | | Moyenne | **2,05 / jour** | | Hashes de ReplicaSet **distincts** | **571** (sur 594) | ## Le mécanisme n'est pas celui qu'on croit Ce ne sont **pas** des redémarrages : un redémarrage garde le nom du pod. Les 571 hashes de ReplicaSet distincts disent autre chose — le *pod template* change presque à chaque fois. Ce qui le change, c'est le `rolloutRestartTargets` du [`VaultDynamicSecret`](crowdsec/templates/vaultdynamicsecret.yaml) : ```yaml # Restart these pods when secrets rotated rolloutRestartTargets: - kind: Deployment name: crowdsec-lapi ``` À chaque rotation de l'identifiant Postgres, VSO force un rollout → nouveau pod template → nouveau hash de ReplicaSet → **nouveau nom de pod**. Le chart amont code en dur `CUSTOM_HOSTNAME` sur `metadata.name`, et l'entrypoint enregistre la LAPI sous ce nom : ```sh si .login (fichier d'identifiants) == CUSTOM_HOSTNAME et machine existante → « Local agent already registered », rien à faire sinon → cscli machines delete <CUSTOM_HOSTNAME> ; cscli machines add ``` Le `delete` ne porte que sur le nom **courant**. L'enregistrement du pod précédent n'est jamais supprimé — d'où l'entassement, sans borne. **Pourquoi ça compte** : la LAPI stocke son état dans le PostgreSQL externe de pi2, à `max_connections=100` — celui-là même qui a refusé des connexions le 2026-09-20 (`SQLSTATE 53300`) et fait crasher la LAPI trois fois. ## Le correctif Fixer `CUSTOM_HOSTNAME` à `crowdsec-lapi`. Le premier démarrage fait delete+add sur ce nom, tous les suivants tombent sur « already registered » et **n'écrivent plus rien**. Le fichier d'identifiants survit aux redémarrages (`/etc/crowdsec` est un lien vers le PVC `crowdsec-config`, vérifié sur le pod), donc la comparaison sur `.login` tient dans le temps. > ⚠ L'entrée doit vivre dans `lapi.env` : le chart émet sa propre définition de `CUSTOM_HOSTNAME` **avant** d'injecter `.Values.lapi.env`, et Kubernetes retient la **dernière** occurrence en cas de doublon. C'est ce qui permet de surcharger un champ que le chart n'expose pas. Vérifié deux fois plutôt qu'une : - `helm template` place la nôtre en **position 7** contre **5** pour celle du chart ; - un pod de test portant les deux définitions a renvoyé `RESULTAT=crowdsec-lapi`, avec l'avertissement attendu `hides previous definition`. > ⚠ Ne pas « corriger » en retirant le `rolloutRestartTargets` : les identifiants arrivent par `secretKeyRef`, qui **ne se recharge pas à chaud**. Sans rollout, la LAPI garderait des identifiants révoqués par Vault. ## La purge, déjà faite Les **614** enregistrements orphelins ont été supprimés en amont (`cscli machines delete`, par lots de 40), en excluant explicitement les trois pods vivants. Résultat : 617 → 3, heartbeats de l'agent (3 s) et de l'appsec (9 s) toujours frais, aucun pod perturbé. > ⚠ `cscli machines prune` aurait été le **mauvais outil** : il filtre sur le heartbeat, or la LAPI n'en émet pas (`DISABLE_AGENT=true`, colonne `⚠ -`). Elle aurait été supprimée avec les morts. Piège d'autant plus vicieux que 20 enregistrements morts affichaient, eux, un heartbeat — vieux de 160 à 285 jours. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
arcodange added 1 commit 2026-09-20 19:36:40 +02:00
fix(crowdsec) — nom de machine stable : 594 LAPI fantômes s'étaient entassées en base
Helm Charts / Application charts pgcat (pull_request) Skipped
Helm Charts / Application charts prometheus (pull_request) Skipped
Helm Charts / Application charts redis (pull_request) Skipped
Helm Charts / Detect changed charts (pull_request) Successful in 21s
Helm Charts / Library charts tool (pull_request) Skipped
Helm Charts / Application charts alloy (pull_request) Skipped
Helm Charts / Application charts chart (pull_request) Skipped
Helm Charts / Application charts grafana (pull_request) Skipped
Helm Charts / Application charts hashicorp-vault (pull_request) Skipped
Helm Charts / Application charts loki (pull_request) Skipped
Helm Charts / Application charts minio (pull_request) Skipped
Helm Charts / Application charts pgbouncer (pull_request) Skipped
Helm Charts / Application charts crowdsec (pull_request) Successful in 51s
6404570bd7
`cscli machines list` renvoyait 617 lignes le 2026-09-20, dont 594
`crowdsec-lapi-*` remontant au 2025-12-05. Une seule LAPI tourne à la fois :
593 étaient mortes.

Le mécanisme n'est pas celui qu'on croit. Ce ne sont PAS des redémarrages — un
redémarrage garde le nom du pod. Mesuré : 571 hashes de ReplicaSet DISTINCTS
pour 594 enregistrements, soit un pod template qui change presque à chaque fois.

Ce qui le change, c'est le `rolloutRestartTargets` du VaultDynamicSecret
(crowdsec/templates/vaultdynamicsecret.yaml) : à chaque rotation de
l'identifiant Postgres, VSO force un rollout → nouveau pod template → nouveau
hash de ReplicaSet → nouveau nom de pod. Soit 2,05 par jour sur 290 jours.

Le chart amont code en dur `CUSTOM_HOSTNAME` sur `metadata.name`, et
l'entrypoint enregistre la LAPI sous ce nom :

    si .login (fichier d'identifiants) == CUSTOM_HOSTNAME et machine existante
        → « Local agent already registered », rien à faire
    sinon
        → cscli machines delete <CUSTOM_HOSTNAME> ; cscli machines add

Le `delete` ne porte que sur le nom COURANT. L'enregistrement du pod précédent
n'est jamais supprimé — d'où l'entassement, sans borne.

Ça compte parce que la LAPI stocke son état dans le PostgreSQL externe de pi2,
à `max_connections=100`, celui-là même qui a refusé des connexions le 2026-09-20
(SQLSTATE 53300) et fait crasher la LAPI trois fois.

Correctif : fixer `CUSTOM_HOSTNAME` à `crowdsec-lapi`. Le premier démarrage fait
delete+add sur ce nom, tous les suivants tombent sur « already registered » et
n'écrivent plus rien. Le fichier d'identifiants survit aux redémarrages
(/etc/crowdsec est un lien vers le PVC crowdsec-config, vérifié sur le pod),
donc la comparaison sur `.login` tient dans le temps.

⚠ L'entrée doit vivre dans `lapi.env` : le chart émet sa propre définition de
CUSTOM_HOSTNAME AVANT d'injecter `.Values.lapi.env`, et Kubernetes retient la
DERNIÈRE occurrence en cas de doublon. Vérifié deux fois : `helm template` place
bien la nôtre en position 7 contre 5 pour celle du chart, et un pod de test avec
les deux définitions a renvoyé `crowdsec-lapi`. `kubectl apply` avertit
« hides previous definition » — c'est attendu.

⚠ Ne pas « corriger » en retirant le rolloutRestartTargets : les identifiants
arrivent par secretKeyRef, qui ne se recharge pas à chaud. Sans rollout, la LAPI
garderait des identifiants révoqués par Vault.

Les 614 enregistrements orphelins ont été supprimés à la main en amont de ce
correctif (`cscli machines delete`, par lots), en excluant explicitement les
trois pods vivants. ⚠ `cscli machines prune` aurait été le mauvais outil : il
filtre sur le heartbeat, or la LAPI n'en émet pas (DISABLE_AGENT=true) — elle
aurait été supprimée avec les morts.

Co-Authored-By: Claude Opus 5 <[email protected]>
arcodange merged commit 74e2136721 into main 2026-09-20 19:38:24 +02:00
arcodange deleted branch arcodange/crowdsec-machines-stables 2026-09-20 19:38:25 +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#56