Automation
Azure Chaos Studio : borner un test de résilience avant de perturber la production
Un runbook de production pour cadrer le rayon d'impact, l'identité, les preuves, les critères d'arrêt et la restauration d'un scénario Azure Chaos Studio.
Un test de résilience peut provoquer l’incident qu’il devait prévenir. Le scénario paraît maîtrisé en préproduction, puis cible trop de ressources en production, utilise une identité surdimensionnée ou continue alors que le service dépasse déjà son budget d’erreur. Le problème n’est pas l’injection de panne elle-même. C’est l’absence d’un contrat d’exécution vérifiable.
Le cas d’usage est une API Azure déployée sur plusieurs zones, protégée par un frontal et surveillée dans Azure Monitor. L’équipe veut exécuter un scénario Azure Chaos Studio simulant la perte d’une zone ou l’indisponibilité d’un composant. L’objectif n’est pas de prouver que « la production résiste ». Il est de vérifier une hypothèse précise, sur un périmètre borné, avec une décision d’arrêt et une restauration déjà préparées.
Écrire l’hypothèse avant le scénario
Commence par formuler ce que le test doit démontrer. Une liste de fautes ne constitue pas une hypothèse. L’équipe doit pouvoir relier la perturbation à un comportement attendu, puis à une mesure observable.
test:
id: chaos-api-zone-loss-2026-08-09
service: orders-api
environment: production
hypothesis: >
The API remains available when one application zone becomes unavailable
and traffic is served by healthy instances in the remaining zones.
workspace_scope: rg-orders-prod
scenario: compute-zone-down
target_allowlist:
- app-zone-1
explicitly_excluded:
- database-primary
- shared-dns
- central-firewall
observation_window_minutes: 15
abort_if:
availability_below_percent: 99.0
p95_latency_above_ms: 900
error_rate_above_percent: 2.0
recovery_owner: platform-oncall
change_ticket: CHG-2026-0819 Ce contrat rend les exclusions aussi importantes que les cibles. Un Workspace Chaos Studio découvre des ressources dans son scope et exécute les scénarios avec son identité managée. Le scope du Workspace, les rôles de cette identité et la configuration du scénario forment donc ensemble le rayon d’impact. Pour un experiment classique, le même raisonnement s’applique, mais l’identité et les permissions sont portées par l’experiment.
Vérifier le rayon d’impact effectif
Ne valide pas seulement le nom du groupe de ressources affiché dans le portail. Relis les identifiants Azure complets des ressources ciblées, l’identité réellement utilisée et ses attributions RBAC. Une identité Contributor au niveau de la souscription invalide le confinement, même si le scénario ne montre qu’une VM.
WORKSPACE_ID="/subscriptions/<sub>/resourceGroups/rg-orders-prod/providers/Microsoft.Chaos/workspaces/chaos-orders-prod"
PRINCIPAL_ID="<workspace-managed-identity-object-id>"
az resource show --ids "$WORKSPACE_ID" --query "{id:id, identity:identity, properties:properties}" -o json
az role assignment list --assignee-object-id "$PRINCIPAL_ID" --all --query "[].{role:roleDefinitionName, scope:scope}" -o table
az resource list --resource-group rg-orders-prod --query "[].{name:name, type:type, id:id}" -o table Le contrôle doit aboutir à une liste explicite : ressources atteignables par l’identité, ressources sélectionnées par le scénario et actions autorisées. Dans le modèle classique, vérifie aussi que chaque ressource est onboardée comme target et que seules les capabilities nécessaires sont activées. Une capability absente doit faire échouer l’action ; elle ne doit pas être ajoutée en urgence pendant la fenêtre de production.
Sépare également le droit de modifier un scénario du droit de le lancer. L’opérateur qui exécute le test n’a pas besoin de pouvoir étendre le scope, ajouter une nouvelle faute et s’accorder des rôles dans la même fenêtre.
Capturer une baseline exploitable
Le test ne peut pas être évalué si l’état normal n’est pas connu. Capture une baseline juste avant l’exécution avec les mêmes signaux qui serviront aux critères d’arrêt : disponibilité, erreurs, latence et dépendances.
let TestStart = datetime(2026-08-09T08:30:00Z);
let BaselineStart = TestStart - 30m;
let TestEnd = TestStart + 15m;
AppRequests
| where TimeGenerated between (BaselineStart .. TestEnd)
| where AppRoleName == "orders-api"
| extend Window = iff(TimeGenerated < TestStart, "baseline", "chaos")
| summarize
Requests = count(),
Errors = countif(Success == false),
Availability = 100.0 * countif(Success == true) / count(),
P95DurationMs = percentile(DurationMs, 95)
by Window, bin(TimeGenerated, 1m)
| extend ErrorRate = 100.0 * Errors / Requests
| order by TimeGenerated asc Ajoute les signaux d’infrastructure propres au service : backends sains du frontal, saturation des instances restantes, backlog de messagerie, erreurs de dépendance et état des probes. Le scénario n’est pas validé parce que l’API répond encore une fois. Il est validé si le système reste dans les seuils attendus pendant toute la fenêtre et récupère sans dette cachée.
Fige aussi les changements concurrents. Un déploiement, une rotation de secret ou une modification réseau pendant le test rend la causalité difficile à établir et peut transformer un arrêt contrôlé en diagnostic ambigu.
Exécuter par paliers
Un scénario passé en préproduction ne doit pas être promu directement sur tout le périmètre de production. Utilise des paliers qui augmentent séparément la réalité du trafic, la durée et le nombre de cibles.
Gate 1 - configuration review
Exact scenario revision recorded
Target allowlist and exclusions reviewed
Workspace identity roles reviewed
Stop permission tested by the operator
Gate 2 - preproduction
Same fault family and observation queries
Recovery action executed successfully
No unexplained telemetry gap
Gate 3 - production canary
One target or one bounded zone
On-call, service owner and observer present
Deployments and infrastructure changes frozen
Gate 4 - decision
Continue only while every abort signal is healthy
Stop on missing telemetry, unexpected target or threshold breach
Never widen scope during the active run Le lancement doit produire un identifiant d’exécution corrélé au ticket de changement, aux tableaux de bord et au journal opérateur. Pour les Workspaces et Scenarios, conserve le rapport de scénario. Pour les experiments classiques, conserve les détails d’exécution et le statut de chaque action. Sans cette corrélation, l’équipe saura qu’une panne a été injectée, mais pas précisément quand ni sur quelle cible.
Traiter l’arrêt comme un début de restauration
La commande d’arrêt ou d’annulation empêche la suite du scénario, mais elle ne prouve pas que le service est revenu à son état initial. Une action déjà appliquée peut demander une compensation : redémarrer une ressource, restaurer un routage, réactiver une règle, attendre une reconnexion ou résorber un backlog.
recovery:
immediate:
- stop the active scenario run
- record the stop timestamp and last completed action
- verify that no unexpected target was affected
compensate:
- restore the target configuration from the approved baseline
- confirm traffic returns to healthy instances
- drain or replay backlog only after consumers are stable
validate:
- availability and error rate healthy for 15 minutes
- p95 latency back inside baseline tolerance
- dependencies and health probes healthy
- no remaining action or retry in progress
rollback_the_test:
- disable the scenario revision
- remove temporary target capabilities if they are no longer needed
- reduce identity assignments added only for this test
- attach evidence and decision to the change ticket Teste ce chemin avant la fenêtre de production. Vérifie en particulier que l’opérateur possède le droit d’arrêter l’exécution, que le propriétaire de chaque action compensatoire est joignable et que les commandes de restauration ne dépendent pas du composant volontairement perturbé.
Décider avec des preuves
La sortie du runbook n’est pas « test terminé ». C’est une décision parmi trois : hypothèse validée, résultat non concluant ou résilience insuffisante.
L’hypothèse est validée si seules les cibles prévues ont été touchées, si les seuils sont restés sains, si la télémétrie est complète et si la restauration est prouvée. Le résultat est non concluant si les logs manquent, si un changement concurrent brouille l’observation ou si la faute ne s’est pas exécutée comme prévu. La résilience est insuffisante si un seuil d’arrêt est franchi ou si la récupération demande une intervention non documentée.
Dans les deux derniers cas, ne relance pas immédiatement avec un scope plus large. Corrige le scénario, le système ou le runbook, puis repars du palier précédent. Un test de chaos utile ne maximise pas la perturbation. Il réduit l’incertitude sans perdre le contrôle de la production.