Tests de résistance
1) Concepts et objectifs de base
Fiabilité : Probabilité de fonctionnement ; résilience (resilience) - comportement pendant et après une défaillance.
SLO/budget erroné : critères de « recevabilité » de la dégradation.
Steady-state hypothesis : attente formelle de métriques stables (par exemple, p95 <200 ms, error rate <0. 5%). L'expérience est considérée comme un succès si l'hypothèse est maintenue.
Types d'échec : réseau (latence, pertes/prises, ruptures), informatique (CPU, mémoire), storage (I/O, épuisement du disque), dépendances (5xx, timeouts, rate-limit), logique (incidents partiels, « dégradation lente »), opérationnel (sortie, configh), « sombre » (split) brain, horaires).
2) Pyramide de durabilité
1. Tests unitaires des défaillances logiques (rétroactivité, idempotence, temporisation).
2. Composants avec adaptateurs faut-inject (Testcontainers/tc-netem).
3. Intégration/système avec réseaux/bases de données/caches et profils real-world.
4. Expériences de chaos dans le pré-prod (puis limité dans la vente) sur runbook 'am.
5. Le gamday est l'enseignement scénique de l'équipe (gens + outils).
3) L'observabilité comme base
SLI : latence p50/p95/p99, taux d'erreur, saturation (CPU/heap/FD/IOPS), drop/timeout, queue depth.
Traçages : pour trouver des « goulets d'étranglement » sous échec.
Métriques de durabilité sémantique : proportion de graceful-degrade réussie, proportion de requêtes shed, taux d'auto-guérison (MTTR).
Marquage des expériences : 'chaos. experiment_id', 'phase = inject/recover' dans les événements/logs.
4) Catalogue des injections d'échec (faults)
Réseau : latence/jitter, perte/duplication/relooking, limitation de bande passante, « tempêtes » par lots, falaises TLS.
Hôte : limitation du CPU, fuites/limites de mémoire, pauses GC, épuisement des descripteurs, « clock skew ».
Stockage : croissance de la latence, EROFS, ENOSPC, dégradation de la réplique, perte du leader.
Dépendances : 5xx/429, ralentissement, flapping DNS, certificats obsolètes, rate-limit, « réponses partielles ».
Données : corruption d'enregistrement, « trous » dans les flux, prises d'événements, conflits de version.
Opérations : échec de la sortie, drapeau ficha, dérivation config, erreur manuelle (dans le cadre de la simulation).
5) Modèles de stabilité (que vérifier)
Retraits avec gitter et timeouts sur chaque RPC.
Circuit Breaker (ouverture/semi-ouverture, récupération exponentielle).
Bulkheads (isolation des pools/files d'attente sur les domaines critiques).
Load Shedding (réinitialiser les requêtes de faible priorité à saturation).
Backpressure (signaux vers le haut de la chaîne, limites de parallélisme).
Idempotency (clés d'idempotentialité sur les « effets secondaires »).
Cachets et meutes en cas de dégradation de l'origine.
Graceful Degradation (réponses simplifiées, données stale, désactivation de la fiche).
Timeout-budget (budget total de la chaîne d'appels).
Atomicité/compensation (Saga/Outbox/Transactional Inbox).
Quorum et réplication (quorum R/W, dégradation de la cohérence pour la disponibilité).
Anti-entropy/relais (récupération dans les « trous » des événements).
6) Ordonnances pour injections et attentes (pseudo-code)
Retray avec jitter et breaker
for attempt in 1..N:
if breaker. open(): return fallback()
res = call(dep, timeout = base 0. 8)
if res. ok: return res sleep(exp_backoff(attempt) jitter(0. 5..1. 5))
if attempt == N: breaker. trip()
return fallback()
Shading et backpercher
if queue. depth() > HIGH cpu. load() > 0. 85:
if request. priority < HIGH: return 503_SHED limiter. acquire () # constrain concurrency
Idempotence
key = hash("payout:"+external_id)
if store. exists(key): return store. get(key)
result = do_side_effect()
store. put(key, result, ttl=30d)
return result
7) Expériences : Scénarios et hypothèses
7. 1 « Lente dépendance »
Injection : + 400 ms p95 à l'API externe.
Attente : augmentation du délai d'attente ≤ X %, ouverture du breaker, réponses de chute, maintien du service p99 <SLA, pas de cascade dans les retraits.
7. 2 « Perte partielle de cache »
Injection : défaillance de 50 % des noeuds Redis/Kesh Shard.
Attente : mise à pied agrandie, mais pas d'avalanche à l'origine (request coalescing/TTL immuable), auto-échauffement et récupération.
7. 3 « Split-brain dans la base de données »
Injection : perte du leader, changement de réplique.
Attente : les enregistrements de déni à court terme, nous lisons du quorum, pas de perte de données, Outbox ne perd pas de message.
7. 4 « ENOSPC/disque plein »
Injection : disque à 95-100 %.
Attente : rotation d'urgence des loges, défaillance des fiches non bloquantes, conservation des journaux critiques (WAL), des alertes et des autoliquides.
7. 5 « La tempête du trafic »
Injection : × 3 RPS à l'endpoint chaud 10 min.
Attente : Shading de faible priorité, p95 stables sur les voies « nucléaires », augmentation des files d'attente dans les limites, absence de tempêtes DLQ.
7. 6 «Clock Skew»
Injection : décalage du temps du noeud de +/ − 2 min.
Attente : TTL/signatures correctes (leeway), minuteries monotoniques dans les retraits, jetons valides à la dérive admissible.
8) Environnement et sécurité des expériences
Commencez par pré-prod, des données synthétiques aussi proches que possible de la vente configi/topologie.
Dans la vente - seulement les fenêtres contrôlées, les drapeaux de ficha, l'amplitude étape par étape, le retour automatique, le « bouton rouge ».
Guardrails : limites RPS/bogues, gardes SLO, verrouillage des sorties lors d'incidents critiques.
Le runbook est obligatoire : comment faire tomber, qui appeler, où regarder.
9) Automatisation et CI/CD
Catalogue d'expériences sous forme de code (YAML/DSL) : cibles, injections, métriques, seuils, « boutons » de retour.
Smoke-chaos dans chaque version : injections courtes (par exemple 2 min + 200 ms par dépendance) dans le steidge.
Les courses nocturnes de la matrice : services × types de défaillances.
Gate to release : interdiction de déploi si la résilience est inférieure au seuil (par exemple, 'fallback coverage <95 %' sous « lente dépendance »).
10) Données et consistance
Vérifier la compensation (Saga) : les opérations partiellement exécutées doivent être portées à l'état convenu.
Testez les répétitions/prises d'événements, la livraison hors-d'ordre, les « trous » et les répliques.
Vérifiez les invariants du domaine après les pannes : le solde n'est pas négatif, les transactions ne sont pas « bloquées », les limites ne sont pas dépassées.
11) Anti-modèles
Testez uniquement happy-path et la charge sans échec.
Retrai sans jitter → tempête sous dégradation.
L'absence de budget mondial pour les temporisations → en cascade.
Un pool unique pour toutes les tâches → pas d'isolation (bulkheads).
Les files d'attente « infinies » → l'augmentation de la latence/OIM.
Télémétrie zéro des expériences → pratiques de chaos « aveugles ».
Chaos dans la vente sans retour/limites/propriétaire responsable.
12) Chèque de l'architecte
1. L'hypothèse steady-state et le SLO ont été définis ?
2. Chaque RPC a-t-il des timeouts, des retraits avec un gitter, des breakers ?
3. Bulkheads, limiteurs, backpressure, load-shedding ?
4. Le cache est stable : coalescing, protection contre les tempêtes de cache, échauffement ?
5. Outbox/Saga pour les effets secondaires, clés idempotent ?
6. Quorum/réplication/faussaire testé ?
7. Y a-t-il un catalogue d'expériences, de chaos nocturne et de gates dans CI/CD ?
8. Les métriques/traces marquent les expériences, y a-t-il des dashboards ?
9. Runbook 'et « bouton rouge » sont prêts, la responsabilité est attribuée ?
10. Jeux réguliers avec la participation de Dev/SRE/Support ?
13) Mini-outils et exemples de scénarios (sketches YAML)
Réseau (tc/netem)
yaml experiment: add-latency target: svc:payments inject:
netem:
delay_ms: 300 jitter_ms: 50 loss: 2%
duration: 10m guardrails:
error_rate: "< 1%"
p95_latency: "< 400ms"
CPU/Heap
yaml inject:
cpu_burn: { cores: 2, duration: 5m }
heap_fill: { mb: 512 }
Dépendance
yaml inject:
dependency:
name: currency-api mode: slow p95_add_ms: 500 fallback_expectation: "serve stale rates ≤ 15m old"
Conclusion
Tester la résilience n'est pas un « tour du chaos », mais une discipline qui rend le système prévisible en cas de défaillance. Les hypothèses claires, la télémétrie, le catalogue d'expériences guidées et les modèles intégrés à l'architecture (Timeouts, breakers, isolation, idempotence) transforment les incidents potentiels en scénarios contrôlés. L'équipe obtient la confiance dans les versions et les utilisateurs - un service stable même dans les conditions de refus.