Ce qu'un pod a dit lui survit — Loki et Alloy, sous plafond (#38) #40

Merged
arcodange merged 6 commits from arcodange/loki-journaux into main 2026-09-07 18:06:10 +02:00
Owner

Closes #38

Ce que le cluster gardait vraiment — mesuré, et c'est pire que l'issue ne le supposait

L'issue disait « le tampon du kubelet tourne ». On a demandé à chaque journal jusqu'où il remonte, le 2026-09-07 à 15:05 UTC :

conteneur pod démarré journal remonte à
kube-system/traefik il y a 12 jours 10 minutes
tools/clickhouse-0 il y a 8 jours 2 minutes
tools/prometheus-server il y a 7 h son démarrage (pod peu bavard)
tools/grafana il y a 45 jours 10 jours (pod peu bavard)

Les deux composants les plus bavards du cluster gardent entre deux et dix minutes d'histoire.

Ce chiffre est tombé d'un désaccord entre deux instruments, et le désaccord était le résultat : une fenêtre de 10 min extrapolée ×6 donnait 13,1 Mo/h, la fenêtre d'1 h mesurait 7,9 Mo/h — 0,60 fois. Par conteneur, le rapport 1 h / 10 min vaut ~6 partout (débit stable) sauf traefik (1,18) et clickhouse (3,98) : leur fenêtre d'une heure était tronquée. D'où la vérification directe ci-dessus.

L'agent : Alloy, et pourquoi pas Promtail

Relevé sur l'index Helm de Grafana lui-même (curl https://grafana.github.io/helm-charts/index.yaml) :

chart versions dernière publication deprecated: dans l'index
promtail 141 2025-10-31 true
alloy 57 2026-08-27 absent
loki 344 2026-08-10 absent

Promtail n'est pas « bientôt en fin de vie » : son chart porte déjà le drapeau, et sa dernière publication a plus de dix mois. Installer à neuf un agent que l'amont a rangé, pour économiser de la mémoire dont le montant restait à vérifier, c'est acheter une dette à échéance connue. ARM64 vérifié au registre (manifeste multi-plateforme) et empiriquement — les pods tournent sur les Pi.

La rétention : 30 jours

Débit corrigé de la troncature (max(1 h, 10 min × 6) par conteneur) : 13 333 645 octets/h = 305 Mio/jour bruts.

volume
30 j bruts 8,94 Gio
30 j compressés (facteur 5, prudent) 1,79 Gio
30 j compressés (facteur 10, typique) 0,89 Gio

Volume posé : 10 Gi sur Longhorn (5 à 10× de marge). Le plus serré des trois nœuds Longhorn a 99 Gio libres.

Pourquoi 30 et pas 7 : les deux pannes qui motivent ce lot ont duré des semaines (la mise à l'abri, kadans#1033) ou trois jours (#36). Une rétention de 7 jours aurait perdu le début des deux. 30 jours couvre le délai réel entre « ça casse » et « quelqu'un s'en aperçoit ».

Ce qui rendrait ce chiffre faux : c'est la photo d'un mardi après-midi. Elle ne dit rien d'un pod parti en boucle d'erreur, cas où un seul conteneur peut dépasser tout le reste du cluster. La marge est là pour ça, pas pour la croissance ordinaire.

Les plafonds, parce que pi2 est à 108 %

Les défauts amont du chart Loki sont écrits pour un cluster de serveurs. Laissés tels quels sur trois Raspberry Pi, ils auraient posé :

défaut amont ce que ça donne ici
chunksCache.allocatedMemory: 8192 un memcached réclamant 8 Gio sur un nœud qui en alloue 5,6
resultsCache.enabled: true un second memcached
deploymentMode: SimpleScalable read + write + backend, trois jeux
gateway.enabled: true un nginx de plus
lokiCanary.enabled: true un DaemonSet de plus
replication_factor: 3 trois exemplaires de chaque flux
storage.type: s3 un magasin objet qu'on n'a pas

Chaque extinction est nommée avec sa raison dans loki/values.yaml, plutôt que déduite d'un deploymentMode qui « devrait » suffire.

Deux découvertes faites en déployant, pas en lisant

  1. admin_api_directory est accepté par le chart et REFUSÉ par le binaire OSS. C'est un champ de l'édition entreprise. Résultat : failed parsing config: field admin_api_directory not found in type common.FilesystemConfig, CrashLoopBackOff, 3 redémarrages en 4 min. Le chart ne valide pas la config qu'il écrit — seul le démarrage réel le dit.
  2. Le chart ajoute un side-car loki-sc-rules avec resources: {} — ni requête ni limite, dans un pod par ailleurs plafonné, sur pi2. Un conteneur non plafonné dans un pod plafonné annule le plafond. Éteint : le ruler est à 0 réplique, ce side-car surveillait des ConfigMaps inexistantes.

Un troisième relevé, hors périmètre mais à savoir

Le planificateur ne peut pas protéger pi2 : il ne voit que les requests, et sur ce cluster elles ne sont presque pas déclarées.

nœud mémoire demandée (vue du planificateur) mémoire réellement utilisée
pi1 8 % 75 %
pi2 17 % 108 %
pi3 18 % 58 %

C'est pourquoi Loki a été placé sur pi2, le nœud le plus chargé — le planificateur le croyait le plus libre. Les charts de ce lot déclarent, eux, des requêtes honnêtes.

La CI

⚠ La matrice de helmcharts.yaml est codée en dur : un chart absent de la liste n'est jamais construit et sa PR est verte quand même (le défaut raconté dans #32). loki et alloy y sont ajoutés — sans ça, ce lot n'aurait aucune preuve.


Les mesures d'empreinte après déploiement, la démonstration de survie au redémarrage et la table des sabotages arrivent en commentaire de cette PR — ils demandent que la pile tourne.

🤖 Generated with Claude Code

Closes #38 ## Ce que le cluster gardait vraiment — mesuré, et c'est pire que l'issue ne le supposait L'issue disait « le tampon du kubelet tourne ». On a demandé à chaque journal jusqu'où il remonte, le 2026-09-07 à 15:05 UTC : | conteneur | pod démarré | journal remonte à | |---|---|---| | `kube-system/traefik` | il y a **12 jours** | **10 minutes** | | `tools/clickhouse-0` | il y a **8 jours** | **2 minutes** | | `tools/prometheus-server` | il y a 7 h | son démarrage (pod peu bavard) | | `tools/grafana` | il y a 45 jours | 10 jours (pod peu bavard) | Les deux composants les plus bavards du cluster gardent **entre deux et dix minutes** d'histoire. Ce chiffre est tombé d'un désaccord entre deux instruments, et le désaccord était le résultat : une fenêtre de 10 min extrapolée ×6 donnait 13,1 Mo/h, la fenêtre d'1 h mesurait 7,9 Mo/h — 0,60 fois. Par conteneur, le rapport 1 h / 10 min vaut ~6 partout (débit stable) **sauf** traefik (1,18) et clickhouse (3,98) : leur fenêtre d'une heure était **tronquée**. D'où la vérification directe ci-dessus. ## L'agent : Alloy, et pourquoi pas Promtail Relevé sur l'index Helm de Grafana lui-même (`curl https://grafana.github.io/helm-charts/index.yaml`) : | chart | versions | dernière publication | `deprecated:` dans l'index | |---|---|---|---| | `promtail` | 141 | **2025-10-31** | **`true`** | | `alloy` | 57 | 2026-08-27 | absent | | `loki` | 344 | 2026-08-10 | absent | Promtail n'est pas « bientôt en fin de vie » : son chart **porte déjà le drapeau**, et sa dernière publication a plus de dix mois. Installer à neuf un agent que l'amont a rangé, pour économiser de la mémoire dont le montant restait à vérifier, c'est acheter une dette à échéance connue. ARM64 vérifié au registre (manifeste multi-plateforme) **et** empiriquement — les pods tournent sur les Pi. ## La rétention : 30 jours Débit corrigé de la troncature (`max(1 h, 10 min × 6)` par conteneur) : **13 333 645 octets/h = 305 Mio/jour bruts**. | | volume | |---|---| | 30 j bruts | 8,94 Gio | | 30 j compressés (facteur 5, prudent) | 1,79 Gio | | 30 j compressés (facteur 10, typique) | 0,89 Gio | Volume posé : **10 Gi** sur Longhorn (5 à 10× de marge). Le plus serré des trois nœuds Longhorn a 99 Gio libres. **Pourquoi 30 et pas 7** : les deux pannes qui motivent ce lot ont duré des **semaines** (la mise à l'abri, kadans#1033) ou trois jours (#36). Une rétention de 7 jours aurait perdu le début des deux. 30 jours couvre le délai réel entre « ça casse » et « quelqu'un s'en aperçoit ». ⚠ **Ce qui rendrait ce chiffre faux** : c'est la photo d'un mardi après-midi. Elle ne dit rien d'un pod parti en boucle d'erreur, cas où un seul conteneur peut dépasser tout le reste du cluster. La marge est là pour ça, pas pour la croissance ordinaire. ## Les plafonds, parce que pi2 est à 108 % Les défauts amont du chart Loki sont écrits pour un cluster de serveurs. Laissés tels quels sur trois Raspberry Pi, ils auraient posé : | défaut amont | ce que ça donne ici | |---|---| | `chunksCache.allocatedMemory: 8192` | un memcached réclamant **8 Gio** sur un nœud qui en alloue 5,6 | | `resultsCache.enabled: true` | un second memcached | | `deploymentMode: SimpleScalable` | read + write + backend, trois jeux | | `gateway.enabled: true` | un nginx de plus | | `lokiCanary.enabled: true` | un DaemonSet de plus | | `replication_factor: 3` | trois exemplaires de chaque flux | | `storage.type: s3` | un magasin objet qu'on n'a pas | Chaque extinction est **nommée avec sa raison** dans `loki/values.yaml`, plutôt que déduite d'un `deploymentMode` qui « devrait » suffire. ## Deux découvertes faites en déployant, pas en lisant 1. **`admin_api_directory` est accepté par le chart et REFUSÉ par le binaire OSS.** C'est un champ de l'édition entreprise. Résultat : `failed parsing config: field admin_api_directory not found in type common.FilesystemConfig`, CrashLoopBackOff, 3 redémarrages en 4 min. **Le chart ne valide pas la config qu'il écrit** — seul le démarrage réel le dit. 2. **Le chart ajoute un side-car `loki-sc-rules` avec `resources: {}`** — ni requête ni limite, dans un pod par ailleurs plafonné, sur pi2. **Un conteneur non plafonné dans un pod plafonné annule le plafond.** Éteint : le `ruler` est à 0 réplique, ce side-car surveillait des ConfigMaps inexistantes. ## Un troisième relevé, hors périmètre mais à savoir Le planificateur **ne peut pas** protéger pi2 : il ne voit que les *requests*, et sur ce cluster elles ne sont presque pas déclarées. | nœud | mémoire *demandée* (vue du planificateur) | mémoire **réellement utilisée** | |---|---|---| | pi1 | 8 % | **75 %** | | pi2 | **17 %** | **108 %** | | pi3 | 18 % | 58 % | C'est pourquoi Loki a été placé **sur pi2**, le nœud le plus chargé — le planificateur le croyait le plus libre. Les charts de ce lot déclarent, eux, des requêtes honnêtes. ## La CI ⚠ La matrice de `helmcharts.yaml` est **codée en dur** : un chart absent de la liste n'est jamais construit et sa PR est verte quand même (le défaut raconté dans #32). `loki` et `alloy` y sont ajoutés — sans ça, ce lot n'aurait **aucune** preuve. --- *Les mesures d'empreinte après déploiement, la démonstration de survie au redémarrage et la table des sabotages arrivent en commentaire de cette PR — ils demandent que la pile tourne.* 🤖 Generated with [Claude Code](https://claude.com/claude-code)
arcodange added 1 commit 2026-09-07 17:21:00 +02:00
Ce qu'un pod a dit lui survit — Loki et Alloy, sous plafond (#38)
Helm Charts / Detect changed charts (pull_request) Successful in 3m18s
Helm Charts / Library charts tool (pull_request) Skipped
Helm Charts / Application charts crowdsec (pull_request) Skipped
Helm Charts / Application charts hashicorp-vault (pull_request) Skipped
Helm Charts / Application charts minio (pull_request) Skipped
Helm Charts / Application charts prometheus (pull_request) Skipped
Helm Charts / Application charts pgbouncer (pull_request) Skipped
Helm Charts / Application charts pgcat (pull_request) Skipped
Helm Charts / Application charts redis (pull_request) Skipped
Helm Charts / Application charts chart (pull_request) Successful in 29s
Helm Charts / Application charts alloy (pull_request) Successful in 59s
Helm Charts / Application charts grafana (pull_request) Successful in 1m1s
Helm Charts / Application charts loki (pull_request) Successful in 48s
b66e79aadc
Le cluster n'avait AUCUNE collecte de journaux : la seule lecture possible
était `kubectl logs`, c'est-à-dire le tampon du kubelet, qui tourne. Mesuré
le 2026-09-07 en demandant à chaque journal jusqu'où il remonte :

  kube-system/traefik   pod démarré il y a 12 j — journal remontant à 10 MIN
  tools/clickhouse-0    pod démarré il y a  8 j — journal remontant à  2 MIN

Les deux composants les plus bavards du cluster gardent entre deux et dix
minutes d'histoire. C'est pire que ce que l'issue supposait.

Ce lot pose Loki (binaire unique, stockage fichier sur Longhorn) et Alloy
(l'agent, un pod par nœud), et branche la source de données au Grafana qui
tourne déjà.

L'AGENT : Alloy, pas Promtail — et c'est mesuré, pas une préférence. L'index
Helm de Grafana marque le chart `promtail` `deprecated: true`, dernière
publication 2025-10-31. Alloy : 2026-08-27. On n'installe pas à neuf un agent
que l'amont a déjà rangé.

LA RÉTENTION : 30 jours, sur un débit mesuré de ~305 Mio/jour bruts pour tout
le cluster, soit 0,9 à 1,8 Gio compressés. 7 jours auraient perdu le début des
deux pannes qui motivent ce lot (kadans#1033, des SEMAINES ; tools#36, 3 jours).

LES PLAFONDS NE SONT PAS OPTIONNELS : pi2 est mesuré à 108 % de sa mémoire
allouable. Les défauts amont du chart Loki y auraient posé un memcached
réclamant 8 Gio (`chunksCache.allocatedMemory: 8192`), un second memcached, un
nginx, un DaemonSet canari et trois jeux de répliques. Chaque extinction est
nommée dans `loki/values.yaml`, avec sa raison.

⚠ La CI de ce dépôt monte une matrice CODÉE EN DUR : un chart absent de la
liste n'est jamais construit et sa PR est verte quand même (tools#32). `loki`
et `alloy` y sont ajoutés — sans ça, ce lot n'aurait aucune preuve.

Deux découvertes faites en déployant, pas en lisant :
  - `admin_api_directory` est accepté par le chart mais REFUSÉ par le binaire
    OSS (champ d'édition entreprise) : CrashLoopBackOff jusqu'à ce qu'on l'ôte ;
  - le chart ajoute un side-car `loki-sc-rules` SANS aucune limite de
    ressources — un conteneur non plafonné dans un pod plafonné annule le
    plafond. Éteint (le ruler est à 0 réplique).

Closes #38

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
arcodange added 1 commit 2026-09-07 17:29:53 +02:00
Ces nœuds tournent sous Docker, et leur racine est ailleurs — la collecte lisait le vide
Helm Charts / Detect changed charts (pull_request) Successful in 41s
Helm Charts / Library charts tool (pull_request) Skipped
Helm Charts / Application charts crowdsec (pull_request) Skipped
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 / Application charts alloy (pull_request) Successful in 14s
Helm Charts / Application charts chart (pull_request) Successful in 36s
Helm Charts / Application charts loki (pull_request) Successful in 51s
Helm Charts / Application charts grafana (pull_request) Successful in 56s
Helm Charts / Application charts hashicorp-vault (pull_request) Skipped
Helm Charts / Application charts minio (pull_request) Skipped
Helm Charts / Application charts pgbouncer (pull_request) Skipped
c4720a1dfd
Trois faits mesurés au déploiement, qu'aucune lecture du chart n'aurait donnés.

1. LE CLUSTER TOURNE SOUS DOCKER, PAS SOUS CONTAINERD.
   `kubectl get nodes -o …containerRuntimeVersion` :
     pi1  docker://29.1.3
     pi2  docker://28.4.0
     pi3  docker://27.4.0
   Le commentaire du premier jet affirmait le contraire. Il était faux.

2. LES JOURNAUX NE SONT PAS SOUS /var/log — CE SONT DES LIENS.
     /var/log/pods/<ns>_<pod>_<uid>/<conteneur>/0.log
       -> /mnt/arcodange/docker/containers/<id>/<id>-json.log
   La racine Docker est déplacée sur un disque externe. Monter /var/log donne
   les liens et PAS leurs cibles : `ls` les montre, `stat` échoue dessus. Le
   drapeau `dockercontainers` du chart monterait /var/lib/docker/containers,
   qui n'existe pas ici. On monte la vraie racine, en lecture seule.
   Chemin vérifié identique sur pi1 et pi3, pod par pod.

3. LE FORMAT EST DU JSON DOCKER, DONC `stage.docker`, PAS `stage.cri`.
   Avec le mauvais décodeur, l'horodatage stocké serait celui de la LECTURE et
   non celui de l'écriture — or dater une panne à la minute est précisément
   l'usage qui motive ce lot (tools#36).

⚠⚠ CE QUI REND CE DÉFAUT DANGEREUX : IL SE PRÉSENTE COMME UNE SANTÉ PARFAITE.
Les six composants d'Alloy se déclaraient `healthy`, aucune erreur de poussée,
Loki répondait `ready`, les trois agents étaient 2/2 Running. La seule chose
qui parlait était `loki_source_file_files_active_total = 0` et l'export vide de
`local.file_match`. Une pile de journaux qui rassure sans rien garder : le
défaut même que l'issue #38 demande de ne pas reproduire.

Le hostPath est en `type: Directory` et non `DirectoryOrCreate`, exprès — si un
nœud n'a pas ce chemin, son agent doit refuser de démarrer et le DIRE, plutôt
que de monter un dossier vide et de rapporter zéro en se déclarant sain.

Corrige aussi le second conteneur non plafonné, jumeau de celui de Loki :
`config-reloader` arrive avec une REQUÊTE de 50Mi et AUCUNE limite. Une requête
sans limite n'est pas un plafond, c'est une réservation — et sur un DaemonSet
cela vaut sur les trois nœuds. On ne peut pas l'éteindre sans perdre le
rechargement à chaud : on le plafonne (32Mi / 64Mi).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
arcodange added 1 commit 2026-09-07 17:35:35 +02:00
__meta_kubernetes_pod_node_name — un relabel dont la source est vide ne dit rien
Helm Charts / Detect changed charts (pull_request) Successful in 24s
Helm Charts / Library charts tool (pull_request) Skipped
Helm Charts / Application charts crowdsec (pull_request) Skipped
Helm Charts / Application charts hashicorp-vault (pull_request) Skipped
Helm Charts / Application charts minio (pull_request) Skipped
Helm Charts / Application charts pgbouncer (pull_request) Skipped
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 / Application charts chart (pull_request) Successful in 29s
Helm Charts / Application charts loki (pull_request) Successful in 47s
Helm Charts / Application charts grafana (pull_request) Successful in 50s
Helm Charts / Application charts alloy (pull_request) Successful in 45s
1abfe7044b
L'étiquette `node` était absente de Loki sur une collecte par ailleurs saine :
`__meta_kubernetes_node_name` n'existe QUE pour `role = "node"`. Sous
`role = "pod"`, elle est vide — et un relabel dont la source est vide ne pose
pas l'étiquette, SANS erreur ni avertissement.

On ne s'en aperçoit qu'en DEMANDANT les valeurs de l'étiquette
(`/loki/api/v1/label/node/values`) et en trouvant la liste vide. Les six
composants d'Alloy restaient `healthy`, 68 fichiers activement suivis, les
lignes arrivaient. Seule l'étiquette par laquelle on aurait cherché « que
disait pi2 cette nuit-là » manquait.

Vérifié après correction : `node` rend pi1, pi2, pi3.

⚠ Relevé au passage, à ne pas oublier : le `config-reloader` n'a PAS rechargé
Alloy quand la ConfigMap a changé. Le fichier monté portait bien la correction
(horodaté 15:31), le composant en mémoire exécutait toujours l'ancienne règle.
Il a fallu un `rollout restart` pour que la nouvelle config prenne. Le
rechargement à chaud n'est donc pas une garantie — après un changement de
configuration d'Alloy, VÉRIFIER la propriété visée plutôt que supposer.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
arcodange added 1 commit 2026-09-07 17:41:22 +02:00
La date from du schéma n'est pas la date d'installation — un 500 emportait les lignes fraîches
Helm Charts / Application charts alloy (pull_request) Successful in 16s
Helm Charts / Application charts chart (pull_request) Successful in 34s
Helm Charts / Application charts grafana (pull_request) Successful in 54s
Helm Charts / Application charts loki (pull_request) Successful in 45s
Helm Charts / Detect changed charts (pull_request) Successful in 22s
Helm Charts / Library charts tool (pull_request) Skipped
Helm Charts / Application charts crowdsec (pull_request) Skipped
Helm Charts / Application charts hashicorp-vault (pull_request) Skipped
Helm Charts / Application charts minio (pull_request) Skipped
Helm Charts / Application charts pgbouncer (pull_request) Skipped
Helm Charts / Application charts pgcat (pull_request) Skipped
Helm Charts / Application charts prometheus (pull_request) Skipped
Helm Charts / Application charts redis (pull_request) Skipped
857a6d1560
C'est le défaut le plus coûteux de ce lot, et celui qui ressemblait le moins à
ce qu'il était.

SYMPTÔME : `kubectl logs` montrait 19 lignes du pod témoin, Loki en montrait 0.
L'agent se déclarait sain, ses six composants `healthy`, 74 fichiers activement
suivis, le journal disait « start tailing file » sur le bon chemin, et TOUS ses
compteurs `loki_write_dropped_entries_total` valaient zéro — quelle que soit la
raison (ingester_error, line_too_long, queue_is_full, rate_limited,
stream_limited). Seul `loki_write_sent_entries_total = 0` disait qu'il ne
passait rien, sans dire pourquoi.

CAUSE, lisible uniquement dans le journal de Loki :

  POST /loki/api/v1/push (500)
    failed to create stream: no schema config found for time 1786622254.804
  entry ... has timestamp too old: 2026-04-13T13:17:53Z

`schemaConfig.configs[0].from` était posé à la date du jour. Or `from` dit
« à partir de quand ce schéma s'applique », PAS « depuis quand on garde ».
Sous cette date, Loki n'a aucun schéma pour les horodatages antérieurs.

Et l'agent lit aussi les fichiers ROTATÉS encore sur le disque (4.log, 9.log,
10.log…), qui portent des lignes vieilles de plusieurs mois — l'une de
2026-04-13. ⚠ Une poussée étant un LOT, le 500 emporte les lignes FRAÎCHES qui
voyageaient avec les vieilles. D'où : rien n'arrive, et rien ne l'explique côté
agent.

La date passe à 2020-01-01, antérieure à tout ce que ces machines peuvent
porter. Ce qui borne la conservation reste `retention_period` (720 h) et le
compacteur, pas le schéma.

⚠ À NOTER, PARCE QUE C'EST L'ISSUE #38 EN ABYME : cette cause n'était lisible
que dans le journal du pod Loki — qu'on ne pouvait lire que parce qu'il n'avait
pas redémarré. Le défaut qui empêchait de garder les journaux ne se
diagnostiquait que par un journal non gardé.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
arcodange added 1 commit 2026-09-07 17:45:43 +02:00
reject_old_samples_max_age n'est pas la rétention — un lot refusé bloque la file derrière lui
Helm Charts / Application charts alloy (pull_request) Successful in 22s
Helm Charts / Application charts chart (pull_request) Successful in 40s
Helm Charts / Application charts loki (pull_request) Successful in 51s
Helm Charts / Application charts grafana (pull_request) Successful in 57s
Helm Charts / Detect changed charts (pull_request) Successful in 46s
Helm Charts / Library charts tool (pull_request) Skipped
Helm Charts / Application charts crowdsec (pull_request) Skipped
Helm Charts / Application charts hashicorp-vault (pull_request) Skipped
Helm Charts / Application charts redis (pull_request) Skipped
Helm Charts / Application charts minio (pull_request) Skipped
Helm Charts / Application charts pgbouncer (pull_request) Skipped
Helm Charts / Application charts pgcat (pull_request) Skipped
Helm Charts / Application charts prometheus (pull_request) Skipped
698920ec8d
Second blocage complet, découvert juste après celui du schéma et de la même
famille : un réglage lu comme « combien de temps on garde » alors qu'il dit
« quelles horloges on accepte ».

Posé à 720 h pour « coller » à la rétention, il refusait chaque lot contenant
une ligne de plus de 30 jours :

  entry ... has timestamp too old: 2026-04-13T13:47:05Z,
  oldest acceptable timestamp is: 2026-08-08T15:41:50Z

Or l'agent lit les fichiers rotatés encore présents sur le disque, dont
certains remontent à AVRIL. Et comme un lot définitivement refusé est REJOUÉ,
la file ne se vide jamais : mesuré sur l'agent de pi3,
`loki_write_sent_entries_total` valait 0 — il n'avait JAMAIS rien transmis,
pour 74 fichiers activement suivis.

Ce garde-fou existe contre les horloges décalées. On l'ouvre à 8760 h, bien
au-delà de ce que le disque peut porter. Ce qui borne la conservation reste
`retention_period` (720 h) plus le compacteur.

⚠ Conséquence assumée, écrite dans les valeurs : au premier démarrage l'agent
remonte l'historique du disque, et le compacteur supprime ensuite ce qui
dépasse 30 jours. On paie une ingestion inutile UNE fois, contre une file qui
se vide — et on récupère au passage l'histoire déjà écrite.

⚠ Un état bloqué ne se débloque pas tout seul : après avoir corrigé Loki, il a
fallu REDÉMARRER les agents. Le compteur d'un agent resté sur son ancien lot ne
repart pas parce que le serveur, lui, va mieux.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
arcodange added 1 commit 2026-09-07 17:51:18 +02:00
Le plafond de l'agent passe à 384 Mi — 256 laissait 84 % d'occupation sur pi1
Helm Charts / Detect changed charts (pull_request) Successful in 28s
Helm Charts / Library charts tool (pull_request) Skipped
Helm Charts / Application charts crowdsec (pull_request) Skipped
Helm Charts / Application charts hashicorp-vault (pull_request) Skipped
Helm Charts / Application charts minio (pull_request) Skipped
Helm Charts / Application charts pgbouncer (pull_request) Skipped
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 / Application charts loki (pull_request) Successful in 16s
Helm Charts / Application charts chart (pull_request) Successful in 36s
Helm Charts / Application charts alloy (pull_request) Successful in 51s
Helm Charts / Application charts grafana (pull_request) Successful in 55s
bb14dc38d5
Relevé sur la pile qui tourne (`kubectl top pods --containers`), pendant la
reprise de l'historique :

  agent de pi1   214 Mi   ← 84 % du plafond de 256 Mi
  agent de pi2    98 Mi
  agent de pi3    83 Mi

Aucun OOMKill constaté (0 redémarrage sur les trois), mais 84 % n'est pas une
marge. Un agent tué perd sa position de lecture, et un trou dans la collecte
est exactement ce que ce lot existe pour supprimer.

⚠ Relever un PLAFOND ne consomme rien : il borne le pire cas. C'est la REQUÊTE
(128 Mi, inchangée) que le planificateur réserve — donc rien n'est retiré à
pi2, le nœud tendu.

⚠ L'écart entre les trois nœuds n'est pas du bruit : il suit le nombre de
fichiers suivis, donc le nombre de conteneurs du nœud.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Author
Owner

La pile tourne. Voici ce qui est mesuré, et ce qui ne l'est pas.

La pile a été déployée à la main sur le cluster (helm install depuis ces mêmes répertoires — donc exactement ce qu'ArgoCD rendra après fusion) pour pouvoir mesurer et éprouver. Rien n'a été appliqué avec Tofu, rien n'a touché Vault.


1. La propriété de #38 : un message survit-il au pod qui l'a écrit ?

Oui. Vérifié, code de sortie 0.

Le protocole, et pourquoi chaque pas y est :

JETON = survie-1788795959-23800

--- 1. un pod jetable écrit la ligne, puis dort ---
    pod temoin-journal : phase=Running sur pi3

--- 3. la ligne existe-t-elle seulement ? (kubectl logs, pod VIVANT) ---
    kubectl logs voit le jeton : 2 fois

--- 2. Loki l'a-t-il ingérée ? ---
    Loki, pod VIVANT : 8 ligne(s)

--- 4. on SUPPRIME le pod, et on attend que kubectl logs n'en puisse plus rien ---
    pod supprimé (code 0)
    kubectl logs échoue désormais : oui

--- 5. LE VERDICT : Loki répond-il encore, le pod n'existant plus ? ---
    Loki, pod MORT : 28 ligne(s)

✅ PROPRIÉTÉ TENUE — la ligne survit au pod qui l'a écrite.
CODE_DE_SORTIE=0

Le pas 4 est celui qu'on est tenté de sauter. Sans lui on démontrerait seulement que Loki sait lire un pod vivant — ce que kubectl logs fait déjà, et qui n'est pas la propriété qu'on achète. Le test refuse de conclure tant que kubectl logs répond encore.


2. L'empreinte, avant / après — pi2 compris

Séries d'échantillons de kubectl top nodes (30 s d'intervalle), pas un instant unique.

nœud AVANT (n=12) APRÈS (n=7) écart
pi1 6098 Mi — 75,2 % 6376 Mi — 78,9 % +278 Mi, +3,7 pts
pi2 6269 Mi — 108,1 % 6412 Mi — 110,7 % +143 Mi, +2,6 pts
pi3 4742 Mi — 58,0 % 4899 Mi — 60,1 % +157 Mi, +2,1 pts

Oui, l'ajout pousse pi2 plus haut : de 108,1 % à 110,7 % de son allouable. Je ne l'enjolive pas. Deux nuances mesurées, qui ne l'effacent pas :

  • ce pourcentage porte sur l'allouable (5772 Mi), pas sur la capacité (7820 Mi) ; en valeur absolue pi2 utilise 6412 Mi sur 7820, soit ~1,4 Gio de marge physique réelle ;
  • Loki a été placé sur pi2, le nœud le plus chargé, parce que le planificateur ne voit que les requests — et sur ce cluster elles ne sont presque pas déclarées (pi1 8 %, pi2 17 %, pi3 18 % demandés, contre 75/108/58 % réellement utilisés). Le planificateur ne peut pas protéger pi2. Déplacer Loki sur pi3 est une ligne de nodeSelector si vous le voulez ; je ne l'ai pas fait de moi-même, parce qu'épingler un nœud dans un chart est le genre de chose qui pourrit.

Par conteneur, à l'état stabilisé :

conteneur mémoire plafond
loki 221 Mi 512 Mi
alloy (pi1) 303 Mi 384 Mi
alloy (pi2) 109 Mi 384 Mi
alloy (pi3) 83 Mi 384 Mi
config-reloader (×3) 7–8 Mi 64 Mi

Zéro redémarrage, zéro OOMKill sur les quatre pods.

Le plafond de l'agent a dû être relevé de 256 à 384 Mi, et c'est une mesure qui l'a dit : l'agent de pi1 est monté à 303 Mi — au-dessus des 256 Mi du premier jet. Il aurait été tué. Relever un plafond ne consomme rien (c'est la requête, 128 Mi, que le planificateur réserve), donc rien n'est retiré à pi2.

Disque : le volume Longhorn de Loki porte 468 Mio pour 1 273 677 lignes ingérées — l'historique de reprise inclus. Sur 10 Gi demandés.


3. La table des sabotages

# ce qu'on sabote attendu mesuré verdict
Témoin rien — chart intact rend helm template code 0 le témoin est vert
A schemaConfig.configs remplacé par une chaîne job CI rouge helm template code 0 NE MORD PAS
B YAML malformé dans loki/values.yaml job CI rouge code 1, cannot load values.yaml: … line 236 mord
B en CI la même chose, poussée en PR (#41) Application charts loki échoue job failure, étape Helm template failure ; alloy, chart, grafana restent success la gate est CÂBLÉE et discriminante
C interroger Loki avec un jeton jamais écrit 0 ligne 0 ligne, contre 43 pour le vrai jeton, même requête, même instant la preuve de survie n'est pas complaisante

⚠⚠ Le sabotage A ne mord pas, et c'est le résultat le plus important de cette table

helm template a rendu 0 sur un schemaConfig corrompu. Autrement dit : la CI de ce dépôt prouve que le chart SE REND, elle ne prouve rien de ce que Loki fera de la configuration produite. Un vert ici n'est pas un vert fonctionnel.

Ce n'est pas une hypothèse — c'est arrivé deux fois dans ce lot, et les deux fois la CI était verte :

  1. admin_api_directory — accepté par le chart, refusé par le binaire OSS (champ d'édition entreprise) → CrashLoopBackOff ;
  2. schemaConfig.from à la date du jour → POST /push (500), plus rien n'entre.

Je n'ai pas ajouté de gate qui démarrerait vraiment Loki sur la config rendue. C'est le manque le plus sérieux de cette PR, et je préfère le nommer que le maquiller.


4. Les cinq défauts trouvés en déployant, qu'aucune lecture n'aurait donnés

# défaut ce qui l'a révélé
1 admin_api_directory refusé par le binaire CrashLoopBackOff, 3 redémarrages en 4 min
2 side-car loki-sc-rules sans aucune limite kubectl get pod -o jsonpath sur les resources
3 config-reloader d'Alloy avec une requête mais pas de limite idem — une requête sans limite n'est pas un plafond
4 cluster sous Docker, racine déplacée sur /mnt/arcodange/docker ls -l : les journaux sont des liens ; stat échoue sur la cible
5 schemaConfig.from + reject_old_samples_max_age le journal de Loki, seul endroit qui le disait

⚠⚠ Le défaut 4 est le plus traître de tous : tout avait l'air sain. Les six composants d'Alloy healthy, aucune erreur de poussée, Loki ready, les trois agents 2/2 Running. Le seul relevé qui parlait était loki_source_file_files_active_total = 0 et l'export vide de local.file_match. Une pile de journaux qui rassure sans rien garder — précisément ce que #38 demande de ne pas reproduire.

⚠ Et le défaut 5 est l'issue #38 en abyme : sa cause n'était lisible que dans le journal du pod Loki, qu'on ne pouvait lire que parce qu'il n'avait pas redémarré.


5. Grafana

La source de données n'est pas encore déployée (la ConfigMap vient de main). Ce qui est vérifié, depuis le pod Grafana lui-même, à l'URL exacte que déclare la source :

$ kubectl exec grafana-c5655c5d8-b6dwz -c grafana -- \
    wget -qO- http://loki.tools.svc.cluster.local:3100/loki/api/v1/label/namespace/values
{"status":"success","data":["argocd","cert-manager","cms","dance-lessons-coach","erp",
 "erp-sandbox","kadans","kube-system","longhorn-system","prospection",
 "telegram-gateway","tools","url-shortener","webapp"]}

14 namespaces, dont kadans — l'application dont la panne muette a motivé ce lot.


6. CI — vérifiée à l'API, contextes présents et nommés

Tête bb14dc38, statut combiné success, 13 contextes présents (aucun absent) :

contexte état
Detect changed charts success
Application charts loki success (16 s)
Application charts alloy success (51 s)
Application charts chart success (36 s)
Application charts grafana success (55 s)
Library charts tool skipped
crowdsec, hashicorp-vault, minio, pgbouncer, pgcat, prometheus, redis skipped

Les skipped sont le comportement voulu : ces charts ne sont pas touchés. Les quatre qui le sont ont tourné, pas été sautés — et le sabotage B a prouvé qu'ils savent rougir.

main est rouge indépendamment de cette PR (run 6730, tête dc48d48, la fusion de #39). Ce n'est pas causé par ce lot.


7. Ce que je n'ai PAS vérifié — à lire avant de fusionner

  1. Aucune gate ne démarre Loki sur la config rendue. Le sabotage A le prouve : la CI laisse passer une config sémantiquement cassée. Les deux pannes de ce lot seraient repassées.
  2. Le comportement d'ArgoCD n'est pas éprouvé. J'ai déployé avec helm install depuis les mêmes répertoires ; je n'ai pas vu ArgoCD adopter les releases existantes. L'adoption devrait se faire, mais je ne l'ai pas constatée.
  3. La rétention n'a pas été observée s'exécuter. retention_enabled: true et retention_period: 720h sont dans la config rendue, mais aucune donnée n'a encore 30 jours ici : je n'ai jamais vu le compacteur supprimer quoi que ce soit. La propriété « le volume ne grossit pas indéfiniment » reste non démontrée.
  4. Les premières lignes d'un pod peuvent être perdues. Mesuré : le pod écrit à 15:35:47, l'agent s'attache à 15:35:52 — cinq secondes plus tard, et ce qui précède n'est pas repris. ⚠ Ce sont exactement les lignes d'un plantage au démarrage, donc les plus précieuses. Non corrigé.
  5. La tenue dans la durée est inconnue. Tout ceci tient sur environ deux heures d'observation. Rien ne dit ce que donnent l'agent et Loki après plusieurs jours, ni sous une avalanche de journaux (un pod en boucle d'erreur), cas où un seul conteneur peut dépasser tout le reste du cluster.
  6. Le débit est une photo d'un mardi après-midi, pas une moyenne. La marge de 5 à 10× sur le volume est là pour ça.
  7. /mnt/arcodange/docker/containers est vérifié sur pi1 et pi3, pod par pod. Sur pi2 je l'ai déduit du fait que son agent collecte — je n'ai pas lu le lien moi-même sur ce nœud.
  8. Le rechargement à chaud d'Alloy ne s'est pas déclenché quand sa ConfigMap a changé : le fichier monté portait la correction, le composant en mémoire exécutait l'ancienne règle. Il a fallu un rollout restart. Je n'ai pas cherché pourquoi.
  9. pi2 met plusieurs minutes à terminer un pod (jusqu'à 7 min sur un busybox), au point de bloquer un déploiement progressif. Constaté deux fois, non diagnostiqué — c'est probablement un signe de santé de ce nœud, pas de ce lot.

🤖 Generated with Claude Code

## La pile tourne. Voici ce qui est mesuré, et ce qui ne l'est pas. La pile a été déployée à la main sur le cluster (`helm install` depuis ces mêmes répertoires — donc exactement ce qu'ArgoCD rendra après fusion) pour pouvoir mesurer et éprouver. **Rien n'a été appliqué avec Tofu, rien n'a touché Vault.** --- ## 1. La propriété de #38 : un message survit-il au pod qui l'a écrit ? **Oui. Vérifié, code de sortie 0.** Le protocole, et pourquoi chaque pas y est : ``` JETON = survie-1788795959-23800 --- 1. un pod jetable écrit la ligne, puis dort --- pod temoin-journal : phase=Running sur pi3 --- 3. la ligne existe-t-elle seulement ? (kubectl logs, pod VIVANT) --- kubectl logs voit le jeton : 2 fois --- 2. Loki l'a-t-il ingérée ? --- Loki, pod VIVANT : 8 ligne(s) --- 4. on SUPPRIME le pod, et on attend que kubectl logs n'en puisse plus rien --- pod supprimé (code 0) kubectl logs échoue désormais : oui --- 5. LE VERDICT : Loki répond-il encore, le pod n'existant plus ? --- Loki, pod MORT : 28 ligne(s) ✅ PROPRIÉTÉ TENUE — la ligne survit au pod qui l'a écrite. CODE_DE_SORTIE=0 ``` ⚠ **Le pas 4 est celui qu'on est tenté de sauter.** Sans lui on démontrerait seulement que Loki sait lire un pod *vivant* — ce que `kubectl logs` fait déjà, et qui n'est pas la propriété qu'on achète. Le test refuse de conclure tant que `kubectl logs` répond encore. --- ## 2. L'empreinte, avant / après — pi2 compris Séries d'échantillons de `kubectl top nodes` (30 s d'intervalle), pas un instant unique. | nœud | AVANT (n=12) | APRÈS (n=7) | écart | |---|---|---|---| | pi1 | 6098 Mi — **75,2 %** | 6376 Mi — **78,9 %** | +278 Mi, +3,7 pts | | **pi2** | 6269 Mi — **108,1 %** | 6412 Mi — **110,7 %** | **+143 Mi, +2,6 pts** | | pi3 | 4742 Mi — 58,0 % | 4899 Mi — 60,1 % | +157 Mi, +2,1 pts | **Oui, l'ajout pousse pi2 plus haut** : de 108,1 % à 110,7 % de son allouable. Je ne l'enjolive pas. Deux nuances mesurées, qui ne l'effacent pas : - ce pourcentage porte sur l'**allouable** (5772 Mi), pas sur la **capacité** (7820 Mi) ; en valeur absolue pi2 utilise 6412 Mi sur 7820, soit ~1,4 Gio de marge physique réelle ; - Loki a été placé **sur pi2**, le nœud le plus chargé, parce que le planificateur ne voit que les *requests* — et sur ce cluster elles ne sont presque pas déclarées (pi1 8 %, pi2 17 %, pi3 18 % demandés, contre 75/108/58 % réellement utilisés). **Le planificateur ne peut pas protéger pi2.** Déplacer Loki sur pi3 est une ligne de `nodeSelector` si vous le voulez ; je ne l'ai pas fait de moi-même, parce qu'épingler un nœud dans un chart est le genre de chose qui pourrit. Par conteneur, à l'état stabilisé : | conteneur | mémoire | plafond | |---|---|---| | `loki` | 221 Mi | 512 Mi | | `alloy` (pi1) | **303 Mi** | 384 Mi | | `alloy` (pi2) | 109 Mi | 384 Mi | | `alloy` (pi3) | 83 Mi | 384 Mi | | `config-reloader` (×3) | 7–8 Mi | 64 Mi | **Zéro redémarrage, zéro OOMKill** sur les quatre pods. ⚠ **Le plafond de l'agent a dû être relevé de 256 à 384 Mi, et c'est une mesure qui l'a dit** : l'agent de pi1 est monté à 303 Mi — **au-dessus** des 256 Mi du premier jet. Il aurait été tué. Relever un plafond ne consomme rien (c'est la *requête*, 128 Mi, que le planificateur réserve), donc rien n'est retiré à pi2. **Disque** : le volume Longhorn de Loki porte **468 Mio** pour **1 273 677 lignes** ingérées — l'historique de reprise inclus. Sur 10 Gi demandés. --- ## 3. La table des sabotages | # | ce qu'on sabote | attendu | mesuré | verdict | |---|---|---|---|---| | **Témoin** | rien — chart intact | rend | `helm template` **code 0** | ✅ le témoin est vert | | **A** | `schemaConfig.configs` remplacé par une chaîne | job CI rouge | `helm template` **code 0** | ❌ **NE MORD PAS** | | **B** | YAML malformé dans `loki/values.yaml` | job CI rouge | **code 1**, `cannot load values.yaml: … line 236` | ✅ mord | | **B en CI** | la même chose, poussée en PR (#41) | `Application charts loki` échoue | job **failure**, étape `Helm template` **failure** ; `alloy`, `chart`, `grafana` restent **success** | ✅ **la gate est CÂBLÉE et discriminante** | | **C** | interroger Loki avec un jeton jamais écrit | 0 ligne | **0** ligne, contre **43** pour le vrai jeton, même requête, même instant | ✅ la preuve de survie n'est pas complaisante | ### ⚠⚠ Le sabotage A ne mord pas, et c'est le résultat le plus important de cette table `helm template` a rendu **0** sur un `schemaConfig` corrompu. Autrement dit : **la CI de ce dépôt prouve que le chart SE REND, elle ne prouve rien de ce que Loki fera de la configuration produite.** Un vert ici n'est pas un vert fonctionnel. Ce n'est pas une hypothèse — c'est arrivé **deux fois** dans ce lot, et les deux fois la CI était verte : 1. `admin_api_directory` — accepté par le chart, refusé par le binaire OSS (champ d'édition entreprise) → CrashLoopBackOff ; 2. `schemaConfig.from` à la date du jour → `POST /push (500)`, plus rien n'entre. Je n'ai **pas** ajouté de gate qui démarrerait vraiment Loki sur la config rendue. C'est le manque le plus sérieux de cette PR, et je préfère le nommer que le maquiller. --- ## 4. Les cinq défauts trouvés en déployant, qu'aucune lecture n'aurait donnés | # | défaut | ce qui l'a révélé | |---|---|---| | 1 | `admin_api_directory` refusé par le binaire | CrashLoopBackOff, 3 redémarrages en 4 min | | 2 | side-car `loki-sc-rules` **sans aucune limite** | `kubectl get pod -o jsonpath` sur les `resources` | | 3 | `config-reloader` d'Alloy avec une **requête mais pas de limite** | idem — une requête sans limite n'est pas un plafond | | 4 | cluster sous **Docker**, racine déplacée sur `/mnt/arcodange/docker` | `ls -l` : les journaux sont des **liens** ; `stat` échoue sur la cible | | 5 | `schemaConfig.from` + `reject_old_samples_max_age` | le journal de **Loki**, seul endroit qui le disait | ⚠⚠ **Le défaut 4 est le plus traître de tous : tout avait l'air sain.** Les six composants d'Alloy `healthy`, aucune erreur de poussée, Loki `ready`, les trois agents `2/2 Running`. Le seul relevé qui parlait était `loki_source_file_files_active_total = 0` et l'export vide de `local.file_match`. **Une pile de journaux qui rassure sans rien garder** — précisément ce que #38 demande de ne pas reproduire. ⚠ Et le défaut 5 est l'issue #38 **en abyme** : sa cause n'était lisible que dans le journal du pod Loki, qu'on ne pouvait lire **que parce qu'il n'avait pas redémarré**. --- ## 5. Grafana La source de données n'est pas encore déployée (la ConfigMap vient de `main`). Ce qui **est** vérifié, depuis le pod Grafana lui-même, à l'URL exacte que déclare la source : ``` $ kubectl exec grafana-c5655c5d8-b6dwz -c grafana -- \ wget -qO- http://loki.tools.svc.cluster.local:3100/loki/api/v1/label/namespace/values {"status":"success","data":["argocd","cert-manager","cms","dance-lessons-coach","erp", "erp-sandbox","kadans","kube-system","longhorn-system","prospection", "telegram-gateway","tools","url-shortener","webapp"]} ``` 14 namespaces, dont **`kadans`** — l'application dont la panne muette a motivé ce lot. --- ## 6. CI — vérifiée à l'API, contextes présents et nommés Tête `bb14dc38`, statut combiné **`success`**, **13 contextes présents** (aucun absent) : | contexte | état | |---|---| | `Detect changed charts` | **success** | | `Application charts loki` | **success** (16 s) | | `Application charts alloy` | **success** (51 s) | | `Application charts chart` | **success** (36 s) | | `Application charts grafana` | **success** (55 s) | | `Library charts tool` | skipped | | crowdsec, hashicorp-vault, minio, pgbouncer, pgcat, prometheus, redis | skipped | Les `skipped` sont le comportement voulu : ces charts ne sont pas touchés. **Les quatre qui le sont ont tourné, pas été sautés** — et le sabotage B a prouvé qu'ils savent rougir. ⚠ `main` est **rouge indépendamment de cette PR** (run 6730, tête `dc48d48`, la fusion de #39). Ce n'est pas causé par ce lot. --- ## 7. Ce que je n'ai PAS vérifié — à lire avant de fusionner 1. **Aucune gate ne démarre Loki sur la config rendue.** Le sabotage A le prouve : la CI laisse passer une config sémantiquement cassée. Les deux pannes de ce lot seraient repassées. 2. **Le comportement d'ArgoCD n'est pas éprouvé.** J'ai déployé avec `helm install` depuis les mêmes répertoires ; je n'ai pas vu ArgoCD adopter les releases existantes. L'adoption devrait se faire, mais je ne l'ai pas constatée. 3. **La rétention n'a pas été observée s'exécuter.** `retention_enabled: true` et `retention_period: 720h` sont dans la config rendue, mais aucune donnée n'a encore 30 jours ici : **je n'ai jamais vu le compacteur supprimer quoi que ce soit.** La propriété « le volume ne grossit pas indéfiniment » reste **non démontrée**. 4. **Les premières lignes d'un pod peuvent être perdues.** Mesuré : le pod écrit à 15:35:47, l'agent s'attache à 15:35:52 — **cinq secondes** plus tard, et ce qui précède n'est pas repris. ⚠ Ce sont exactement les lignes d'un plantage au démarrage, donc les plus précieuses. Non corrigé. 5. **La tenue dans la durée est inconnue.** Tout ceci tient sur environ deux heures d'observation. Rien ne dit ce que donnent l'agent et Loki après plusieurs jours, ni sous une avalanche de journaux (un pod en boucle d'erreur), cas où un seul conteneur peut dépasser tout le reste du cluster. 6. **Le débit est une photo d'un mardi après-midi**, pas une moyenne. La marge de 5 à 10× sur le volume est là pour ça. 7. **`/mnt/arcodange/docker/containers` est vérifié sur pi1 et pi3**, pod par pod. Sur pi2 je l'ai déduit du fait que son agent collecte — je n'ai pas lu le lien moi-même sur ce nœud. 8. **Le rechargement à chaud d'Alloy ne s'est pas déclenché** quand sa ConfigMap a changé : le fichier monté portait la correction, le composant en mémoire exécutait l'ancienne règle. Il a fallu un `rollout restart`. Je n'ai pas cherché pourquoi. 9. **pi2 met plusieurs minutes à terminer un pod** (jusqu'à 7 min sur un busybox), au point de bloquer un déploiement progressif. Constaté deux fois, non diagnostiqué — c'est probablement un signe de santé de ce nœud, pas de ce lot. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
Owner

Correction du point 7 de la liste « non vérifié »

Je l'avais listé comme déduit ; il est maintenant lu directement sur pi2, comme sur les deux autres :

$ kubectl exec alloy-29srr -c alloy -- sh -c 'readlink $(ls /var/log/pods/*/*/*.log | head -1)'
/mnt/arcodange/docker/containers/eb7c39e3…/eb7c39e3…-json.log

Le chemin /mnt/arcodange/docker/containers est donc vérifié pod par pod sur les trois nœuds, pas extrapolé. Les huit autres points de la liste restent valables tels quels.

État final laissé sur le cluster

pod nœud état redémarrages
loki-0 pi2 1/1 Running 0
alloy-hxrmf pi1 2/2 Running 0
alloy-29srr pi2 2/2 Running 0
alloy-2kgf6 pi3 2/2 Running 0

Le pod jetable temoin-journal est supprimé. La branche de sabotage arcodange/loki-sabotage-ci et sa PR #41 sont fermées et supprimées.

La pile a été installée à la main et reste en service — elle collecte dès maintenant. À la fusion, ArgoCD devrait adopter les deux releases Helm existantes plutôt que d'en créer de nouvelles ; c'est le point 2 de la liste des non-vérifiés, et il vaut la peine d'y jeter un œil au premier sync.

🤖 Generated with Claude Code

### Correction du point 7 de la liste « non vérifié » Je l'avais listé comme déduit ; il est maintenant **lu directement sur pi2**, comme sur les deux autres : ``` $ kubectl exec alloy-29srr -c alloy -- sh -c 'readlink $(ls /var/log/pods/*/*/*.log | head -1)' /mnt/arcodange/docker/containers/eb7c39e3…/eb7c39e3…-json.log ``` **Le chemin `/mnt/arcodange/docker/containers` est donc vérifié pod par pod sur les trois nœuds**, pas extrapolé. Les huit autres points de la liste restent valables tels quels. ### État final laissé sur le cluster | pod | nœud | état | redémarrages | |---|---|---|---| | `loki-0` | pi2 | 1/1 Running | 0 | | `alloy-hxrmf` | pi1 | 2/2 Running | 0 | | `alloy-29srr` | pi2 | 2/2 Running | 0 | | `alloy-2kgf6` | pi3 | 2/2 Running | 0 | Le pod jetable `temoin-journal` est supprimé. La branche de sabotage `arcodange/loki-sabotage-ci` et sa PR #41 sont fermées et supprimées. ⚠ **La pile a été installée à la main et reste en service** — elle collecte dès maintenant. À la fusion, ArgoCD devrait adopter les deux releases Helm existantes plutôt que d'en créer de nouvelles ; c'est le point 2 de la liste des non-vérifiés, et il vaut la peine d'y jeter un œil au premier `sync`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
Owner

⚠ Correction des chiffres d'empreinte — j'ai publié une série INCOMPLÈTE

La série « après » du premier commentaire a été lue alors qu'elle tournait encore : n=7 sur 14. La série complète est arrivée depuis, et elle déplace tous les chiffres vers le haut. Comme l'écart va dans le sens qui minore le coût, et sur le nœud que je signale précisément comme tendu, il faut le corriger plutôt que le laisser.

nœud publié (n=7) complet (n=14) écart de ma mesure
pi1 6376 Mi — 78,9 % 6400 Mi — 79,1 % +24 Mi
pi2 6412 Mi — 110,7 % 6450 Mi — 111,3 % +38 Mi
pi3 4899 Mi — 60,1 % 4904 Mi — 60,2 % +5 Mi

Le tableau avant / après qui fait foi

nœud AVANT (n=12) APRÈS (n=14) écart réel min–max après
pi1 6098 Mi — 75,2 % 6400 Mi — 79,1 % +302 Mi, +3,9 pts 6297–6630
pi2 6269 Mi — 108,1 % 6450 Mi — 111,3 % +181 Mi, +3,2 pts 6361–6525
pi3 4742 Mi — 58,0 % 4904 Mi — 60,2 % +162 Mi, +2,2 pts 4883–4959

Soit ~645 Mio ajoutés sur l'ensemble du cluster, et pi2 passe de 108,1 % à 111,3 % de son allouable — +3,2 points, pas +2,6 comme je l'avais écrit.

Le reste de l'analyse ne bouge pas : le pourcentage porte sur l'allouable (5772 Mi) et non sur la capacité (7820 Mi), donc pi2 conserve ~1,4 Gio de marge physique, et il n'y a eu aucun OOMKill ni redémarrage. Mais le coût réel sur le nœud tendu est un peu plus élevé que ce que j'ai annoncé, et c'est le chiffre n=14 qui vaut.

⚠ La leçon vaut d'être notée : lire une série qui tourne encore, c'est publier une moyenne partielle sans le dire. Les min/max ci-dessus montrent que pi1 varie de 333 Mi d'un échantillon à l'autre — une fenêtre courte n'y suffit pas.

🤖 Generated with Claude Code

### ⚠ Correction des chiffres d'empreinte — j'ai publié une série INCOMPLÈTE La série « après » du premier commentaire a été lue alors qu'elle tournait encore : **n=7 sur 14**. La série complète est arrivée depuis, et elle déplace tous les chiffres **vers le haut**. Comme l'écart va dans le sens qui *minore* le coût, et sur le nœud que je signale précisément comme tendu, il faut le corriger plutôt que le laisser. | nœud | publié (n=7) | **complet (n=14)** | écart de ma mesure | |---|---|---|---| | pi1 | 6376 Mi — 78,9 % | **6400 Mi — 79,1 %** | +24 Mi | | **pi2** | 6412 Mi — 110,7 % | **6450 Mi — 111,3 %** | **+38 Mi** | | pi3 | 4899 Mi — 60,1 % | **4904 Mi — 60,2 %** | +5 Mi | ### Le tableau avant / après qui fait foi | nœud | AVANT (n=12) | APRÈS (n=14) | écart réel | min–max après | |---|---|---|---|---| | pi1 | 6098 Mi — 75,2 % | 6400 Mi — 79,1 % | **+302 Mi, +3,9 pts** | 6297–6630 | | **pi2** | 6269 Mi — 108,1 % | 6450 Mi — **111,3 %** | **+181 Mi, +3,2 pts** | 6361–6525 | | pi3 | 4742 Mi — 58,0 % | 4904 Mi — 60,2 % | **+162 Mi, +2,2 pts** | 4883–4959 | Soit **~645 Mio ajoutés sur l'ensemble du cluster**, et **pi2 passe de 108,1 % à 111,3 %** de son allouable — +3,2 points, pas +2,6 comme je l'avais écrit. Le reste de l'analyse ne bouge pas : le pourcentage porte sur l'allouable (5772 Mi) et non sur la capacité (7820 Mi), donc pi2 conserve ~1,4 Gio de marge physique, et il n'y a eu **aucun OOMKill ni redémarrage**. Mais le coût réel sur le nœud tendu est un peu plus élevé que ce que j'ai annoncé, et c'est le chiffre `n=14` qui vaut. ⚠ La leçon vaut d'être notée : **lire une série qui tourne encore, c'est publier une moyenne partielle sans le dire.** Les min/max ci-dessus montrent que pi1 varie de 333 Mi d'un échantillon à l'autre — une fenêtre courte n'y suffit pas. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
arcodange merged commit 0c23862335 into main 2026-09-07 18:06:10 +02:00
arcodange deleted branch arcodange/loki-journaux 2026-09-07 18:06:17 +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#40