Chaos testing de la demo
Des pannes injectees dans un mode deploye de la demo, une a la fois, chacune avec ce qu’elle doit montrer : ce qui tient, par quel mecanisme du serveur, en combien de temps.
demo/k3s/demo.sh chaos cluster # toutes les experiences qui s'appliquent
demo/k3s/demo.sh chaos cluster s3-one # une seule
demo/k3s/demo.sh pods cluster # l'etat de chaque pod, en JSON
Le meme depuis l’onglet Chaos de la page de pilotage, qui montre aussi l’etat des pods en direct et une carte par experience.
Le deroulement d’une experience
| Temps | Quoi |
|---|---|
| prerequis | le mode, le nombre de pods, les options (--with-s3, --with-oidc) que demande l’experience ; sinon SKIP, la raison dite |
| etat initial | chaque pod pret et /readyz 200, le nombre de replicas du mode, les backends up, en mode cluster chaque pair joignable et aucun detecteur actif, aucun Deployment en cours, aucune NetworkPolicy d’une experience ; sinon refus (REFUSED), et all s’arrete |
| injection | une panne, notee sur la frise ; avec --with-otel, une annotation Grafana (etiquettes cfg-demo, chaos) |
| signaux | ce que l’hypothese attend, chacun avec son delai mesure depuis l’injection et une echeance : lignes du journal (kubectl logs -f), evenements de /admin/events, surveillance d’une ConfigMap, kubectl wait, metriques, /readyz |
| retour | la panne retiree (une annotation), puis les signaux du retour, leur delai mesure depuis lui |
| remise en etat | ce que l’experience a change, defait quoi qu’il arrive (fin, erreur, Ctrl-C) ; puis l’etat initial attendu de nouveau, 300 s au plus |
Verdict : OK quand chaque signal est venu a temps, KO sinon, ERROR
quand l’experience s’est arretee avant son dernier signal. Chaque run :
demo/k3s/.work/<mode>/chaos/<date>-<experience>.json (hypothese,
mecanisme, regles, frise horodatee, verdict, delay_s, recovery_s,
restored, lien Grafana). Les attentes sont des signaux ; ou rien ne
previent (une regle de kube-proxy, la fin d’un delai de 60 s du serveur,
l’etat d’un pair lu chaque seconde), une interrogation courte et bornee,
dite dans demo/k3s/chaos.sh. Les experiences sont decrites dans
demo/k3s/chaos.json, que lisent le script et la page.
Les experiences
| Experience | Prerequis | Injection | Ce qu’elle montre | Regles |
|---|---|---|---|---|
pod-kill | aucun | kubectl delete pod du pod qui recoit un depot SFTP (6 Mio a 1 Mio/s) | le pod quitte le service au signal (/readyz 503), le depot finit entier dans la grace, graceful shutdown complete ; une nouvelle session est servie par un autre pod (en single, par le remplacant) | R-SHUTDOWN-002, 004, 009 |
isolate | cluster, 3 pods | deux NetworkPolicy de sortie : le dernier pod ne joint aucun pair, les autres ne le joignent pas | le pod coupe se dit isole (detector isolated, craftfilegate_cluster_isolated 1), ses pairs le voient injoignable, personne ne quitte le service : unreadyWhen: auto ne nomme pas isolated | R-CLUSTER-006, 015, 016 |
s3-one | cluster, --with-s3 | une NetworkPolicy : le dernier pod ne joint plus RustFS | storage_alone, le retrait du service (/readyz withdrawn_by, hors des endpoints de gate-api), toujours pair ; retour apres ready_after_secs | R-AVAIL-002, R-CLUSTER-015, 016 |
s3-all | --with-s3 | RustFS a 0 replica | chaque pod voit archive en panne, aucun ne se retire, le backend local sert | R-AVAIL-002, R-CLUSTER-016 |
k8s-api | aucun | une NetworkPolicy : les pods du serveur ne joignent plus le serveur d’API (l’adresse du noeud), leurs connexions ouvertes coupees (conntrack) | un acces temporaire et un ban decides pendant la coupure tiennent sur leur pod (local_only), les pods restent prets ; au retour, l’acces et le ban arrivent dans les ConfigMaps et chez les pairs, et un ban decide apres le retour aussi | R-GRANT-005, R-BAN-017 |
keycloak | --with-oidc | une NetworkPolicy : les pods ne joignent plus Keycloak, qui signe toujours ; une cle neuve dans le realm | les cles JWKS en cache verifient les jetons deja signes ; un jeton de la nouvelle cle est refuse pendant la coupure, accepte au retour sans redemarrage | R-AUTH-026, 027 |
auth-burst | aucun | des mauvais mots de passe sur l’API de fichiers, d’un pod a l’autre, jusqu’au premier 403 | un ban, tenu par chaque pod (ban.added), leve partout ; en single, apres max_failures echecs au plus (ceux encore dans la fenetre comptent) | R-BAN-004, R-CLUSTER-011, R-BAN-017 |
hash-pool | aucun | les pods relances avec CRAFT_FILE_GATE_HASH_QUEUE=1 (2 places), puis des connexions de demo, 4 a la fois, sur un pod, le temps des sondes | 503 password checks saturated avec Retry-After: 1, craftfilegate_password_hash_pool_full_total qui monte, pendant que /livez, /readyz et la console repondent | R-AUTH-011, R-K8S-002 |
Les limites
| Experience | Limite |
|---|---|
| toutes | un seul noeud : une coupure est une NetworkPolicy, pas un lien perdu ; le noeud (le kubelet, le conteneur d’outils, kubectl) joint toujours chaque pod |
pod-kill | un depot plus long que shutdown_grace_period_secs est coupe ; kube-proxy retire le pod de ses regles a son rythme, la nouvelle session est retentee 10 s |
isolate, s3-one | les delais suivent la configuration de la demo (sonde 5 s, unready_after_secs 10, ready_after_secs 5) ; aux defauts, un retrait prend 2 min environ |
s3-all | les pods voient la panne a quelques secondes d’ecart : storage_alone peut s’allumer un instant sur l’un, sans retrait (la frise compte ces lignes) |
k8s-api | en single, les bans sont dans un fichier : seul l’acces est essaye |
keycloak | apres un chargement en echec, un kid inconnu attend 60 s : le nouveau jeton est redemande toutes les 2 s, 75 s au plus |
auth-burst | l’etat d’un pair est lu chaque seconde : une rafale plus rapide passe jusqu’a max_failures echecs par pod avant que la somme la rattrape (la frise donne le nombre d’essais et peer_failures) |
hash-pool | une adresse tient 4 places au plus (hash_per_address) : le pool est reduit pour qu’une seule adresse le remplisse ; deux deploiements progressifs, un a l’injection, un au retour |