Le 2026-09-20 à 15:00:50, Traefik a redémarré et n'a pas réussi à télécharger
le plugin bouncer CrowdSec :
unable to install plugin crowdsec-bouncer: ... Get
"https://plugins.traefik.io/.../v1.3.3": context deadline exceeded
Il ne s'arrête pas pour autant. Il journalise « Plugins are disabled because an
error has occurred. » et sert quand même — sans plugin. Le middleware `crowdsec`
devient alors « invalid middleware type or middleware does not exist » et Traefik
JETTE tous les routeurs qui le référencent, c'est-à-dire presque tout l'ingress.
Mesuré : www.arcodange.lab et cms-rec.arcodange.lab en 404 pendant 3 h 18, et
zéro pull du bouncer depuis 14:30. Un `kubectl rollout restart` a tout rétabli
(404 → 200), ce qui confirme le caractère transitoire : le registre répondait en
214 ms depuis un pod de pi1 au moment du diagnostic. Un hoquet de moins de 10 s
a suffi à ouvrir l'edge et à couper les sites.
Deux causes, deux correctifs.
1. Le réseau était dans le chemin de démarrage (experimental.localPlugins)
`experimental.plugins` fait passer Traefik par RegistryDownloader.Download(),
qui appelle plugins.traefik.io à CHAQUE démarrage, avec 10 s de timeout.
⚠ Avoir déjà l'archive en cache NE DISPENSE PAS de l'appel : vérifié dans
pkg/plugins/downloader.go (v3.6.2), le cache ne sert qu'à envoyer un hash pour
obtenir un 304. Persister /plugins-storage (aujourd'hui un emptyDir) n'aurait
donc rien évité — c'était la correction évidente, elle est fausse.
`localPlugins` emprunte un autre chemin de code, SetupLocalPlugins, qui ne fait
aucune I/O réseau : Yaegi lit les sources sous /plugins-local/src/<module>. Les
sources sont posées sur un PVC par un Job Ansible, à la version déclarée.
Le réseau ne sert plus qu'au provisionnement, où l'on peut réessayer sans que
l'ingress soit en jeu (5 tentatives).
Même famille de fragilité que 2026-08-26 (résolution de la forge) : on ne fait
pas dépendre l'edge d'un service joignable à la seconde près.
2. L'échec était silencieux (abortOnPluginFailure)
Servir l'ingress sans bouncer ni captcha, en ne le disant qu'en INFO dans les
logs, n'est pas un mode dégradé acceptable pour un composant de sécurité.
Traefik >= 3.3 sait refuser de démarrer : on le lui demande. Maintenant qu'il
n'y a plus de réseau au boot, ce drapeau ne peut se déclencher que sur un PVC
vide ou corrompu — cas où l'on veut précisément qu'il refuse de démarrer.
⚠ Monter la version du plugin passe désormais par Ansible
(`--tags traefik-plugins`) et non plus par un champ que Traefik irait chercher.
Le Job est idempotent (marqueur .vendored-version) et tourne sur le nœud du
control-plane, donc il peut repeupler le PVC sans couper l'ingress.
Vérifié : `helm template` du chart v37.4.0 avec les valeurs réelles du playbook
rend bien --experimental.localPlugins.crowdsec-bouncer.moduleName et
--experimental.abortonpluginfailure=true, le montage en subPath, et plus aucun
emptyDir `plugins`.
Co-Authored-By: Claude Opus 5 <[email protected]>