⚠ À FERMER. Ne pas fusionner. Cette PR existe pour être rouge.
Elle éprouve la moitié manquante de la gate ajoutée par #40 : un job qui existe et passe ne prouve pas qu'il peut échouer. Le loki/values.yaml de cette branche porte volontairement du YAML malformé.
Attendu : Application charts lokiéchoue, pendant que les autres jobs se comportent normalement.
Le résultat est reporté en commentaire de #40, puis cette PR est fermée et sa branche supprimée.
**⚠ À FERMER. Ne pas fusionner. Cette PR existe pour être rouge.**
Elle éprouve la moitié manquante de la gate ajoutée par #40 : un job qui **existe et passe** ne prouve pas qu'il **peut échouer**. Le `loki/values.yaml` de cette branche porte volontairement du YAML malformé.
Attendu : `Application charts loki` **échoue**, pendant que les autres jobs se comportent normalement.
Le résultat est reporté en commentaire de #40, puis cette PR est fermée et sa branche supprimée.
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]>
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]>
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]>
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]>
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]>
À supprimer. Ce commit casse volontairement loki/values.yaml (YAML malformé)
pour vérifier que le job existe, s'exécute ET ÉCHOUE. Un gate incapable
d'échouer rassure sans garder.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
⚠ À FERMER. Ne pas fusionner. Cette PR existe pour être rouge.
Elle éprouve la moitié manquante de la gate ajoutée par #40 : un job qui existe et passe ne prouve pas qu'il peut échouer. Le
loki/values.yamlde cette branche porte volontairement du YAML malformé.Attendu :
Application charts lokiéchoue, pendant que les autres jobs se comportent normalement.Le résultat est reporté en commentaire de #40, puis cette PR est fermée et sa branche supprimée.
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]>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]>__meta_kubernetes_pod_node_name— un relabel dont la source est vide ne dit rienfromdu schéma n'est pas la date d'installation — un 500 emportait les lignes fraîchesC'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]>reject_old_samples_max_agen'est pas la rétention — un lot refusé bloque la file derrière luiPull request closed