Contexte de l’incident
Un service de provisioning à grande échelle crée des partitions de stockage à la demande. Pour chaque partition, il applique une politique d’accès en appelant une bibliothèque de logique de politiques. Cette même bibliothèque était déjà utilisée par un outil CLI interne, qui traitait les partitions une à une. Dans le scénario CLI, chaque appel chargeait l’état d’une partition, calculait les changements nécessaires et appliquait la politique, le tout avec une empreinte mémoire prévisible.
Mécanisme de la défaillance
Lorsque le service de provisioning a été réutilisé, le modèle d’utilisation a changé : le service peut recevoir une requête qui déclenche la création simultanée de dizaines voire de centaines de partitions. Chaque sous‑appel charge indépendamment l’état de la partition depuis le service de stockage, puis invoque la même bibliothèque. L’opération individuelle reste correcte, mais la multiplication des appels parallèles entraîne une croissance cumulative de la consommation mémoire. Au moment où la requête dépasse la capacité mémoire allouée au service, celui‑ci s’arrête, générant une panne de production. Aucun composant n’a présenté de dysfonctionnement intrinsèque ; la combinaison d’un comportement sûr en série et d’une exécution concurrente non limitée a créé une charge agrégée supérieure au budget mémoire.
Hypothèse implicite et manque de contrainte explicite
La bibliothèque de politiques contenait une hypothèse implicite : les appelants utiliseraient l’outil de façon bornée, comme le faisait le CLI. Cette hypothèse n’a jamais été traduite en contrainte système. Les tests de performance menés avant l’incident se concentraient sur le scénario séquentiel, ne mesurant pas l’impact mémoire d’un grand nombre d’appels simultanés. Ainsi, le service de provisioning n’a jamais disposé d’un mécanisme pour évaluer le coût total d’une requête avant de l’accepter.
Leçons et bonnes pratiques
Pour éviter ce type de défaillance, il faut rendre explicite le lien entre la charge de travail et les ressources disponibles. Des signaux tels que la pression mémoire, le nombre de tâches en file d’attente ou le niveau de concurrence doivent être intégrés dans la logique de décision du service. Un contrôle de la concurrence basé sur des seuils dynamiques, ajustés en fonction de la taille de la requête et de l’état actuel du système, permet de refuser ou de différer du travail lorsque le budget mémoire est menacé. De plus, les bibliothèques réutilisées dans différents contextes doivent être évaluées avec des scénarios de charge concurrente afin de valider que leurs coûts restent acceptables à l’échelle du système. Enfin, l’adoption de méthodes de sécurité système comme STPA (System‑Theoretic Process Analysis) aide à identifier les interactions dangereuses entre composants qui, individuellement, fonctionnent correctement.