https://principlesofchaos.org
Pour vulgariser un peu cette définition, le Chaos Engineering permet de faire apparaître des erreurs en simulant des événements réels (latence réseau, pertes d’instance, etc.) sur l’environnement de production, car c’est là qu’il y a des données concrètes.
On peut retenir 3 étapes principales dans le principe de Chaos Engineering.
Etape 1 : émettre des hypothèses sur le système en se demandant “qu’est-ce qui pourrait mal tourner dans notre système”
Etape 2 : mettre en place une stack de monitoring qui va surveiller les métriques des hypothèses.
Etape 3 : lancer les expérimentations en commençant par celles qui impactent le moins le système, et réparer s’il y a des erreurs.
Le Chaos Engineering repose sur 3 aspects :
Les entreprises ont conscience de l’importance de la résilience dans leurs systèmes mais elles ne peuvent pas toutes se permettre de mettre en place le Chaos Engineering pour plusieurs raisons :
Comme on peut le voir, le Chaos Engineering est un regroupement de plusieurs aspects et certains ne peuvent pas être traités seuls. L’un des aspects, l’aspect technique, peut être un bon début pour mettre en place ce concept.
Aujourd’hui, nous n’avons pas au quotidien les moyens d’agir sur la totalité des aspects du Chaos Engineering. Cependant, l’aspect technique reste abordable et peut être mis en place sur nos projets, comme un premier pas dans la mise en place du Chaos Engineering. La problématique de comment tester la résilience d’une infrastructure de façon automatique se pose donc, indépendamment des autres aspects.
Afin de répondre à cette nouvelle problématique, nous avons décidé d’implémenter une librairie qui va permettre d’écrire des tests de résilience de manière simple et intuitive, de la même manière qu’on aurait écrit un test unitaire. A ma connaissance, une telle librairie n’existe pas, c’est pourquoi, nous avons voulu faire un PoC avec de fortes hypothèses en utilisant Docker pour l’infrastructure car il permet de simuler toute une infrastructure (noeuds, réseau, etc.).
L’implémentation de la librairie a été fait avec le langage Python. Les raisons qui nous ont poussé à utiliser la plateforme Docker sont :
Tout d’abord, nous avons commencé par implémenter des méthodes qui vont permettre d’impacter directement les conteneurs. Pour cela nous avons utilisé un SDK Docker pour Python, https://docker-py.readthedocs.io/en/stable/#. Il permet de récupérer et d’altérer le comportement des conteneurs. 3 méthodes ont été implémentées :
Ensuite, nous avons implémenté des méthodes qui vont impacter le réseau des conteneurs. Les conteneurs Docker sont sous un OS Linux, et il existe une commande qui permet de modifier les options réseaux, tc (Traffic Control). Nous utilisons “docker exec” pour accéder au contexte du conteneur.
Un exemple d’utilisation : “tc qdisc replace dev eth0 root netem delay 200ms”
Il est important aussi de noter que nous avons dû donner l’autorisation NET_ADMIN au conteneur surf lequel nous voulions simuler des problèmes réseaux. Sans cette autorisation, la simulation aurait été caduque En utilisant cette commande, on a pu implémenter 3 méthodes :
La librairie a été implémentée de manière à fournir une API avec une abstraction qui soit suffisamment élevée pour permettre de l’utiliser dans le cadre de tests au format Behaviour Driven Development. Le BDD, https://blog.octo.com/le-bdd/, permet d’écrire des tests complexes dans un langage proche de la langue orale, compréhensibles par tous.
Il y a 2 points importants pour comprendre cet exemple :
Dans cet exemple, nous allons tout d'abord utiliser 1 conteneur de Kafka Streams afin de faire monter le lag, puis de scaler le nombre de conteneurs à 3, dont un que l'on va kill. La métrique qui va être suivie pour monitorer le fonctionnement du use case illustré ci-dessus est le lag. Le lag est la différence de temps entre le moment où la donnée est produite et le moment où elle est consommée. C'est une métrique très importante pour du streaming. Nous utilisons Prometheus pour la mesure et Grafana qui permet d’illustrer l’évolution du lag, ces outils sont mis en place dans des conteneurs.
Si on prend le scénario suivant :
Dans ce scénario, on va vérifier que le conteneur existe et qu’il est bien en marche. Ensuite on exécute la commande Kill, qui va détruire le conteneur en question et attendre 3 minutes. Et en résultat, on vérifie que le conteneur s’est bien arrêté et que le lag est toujours inférieur à 100.
La librairie fournit le @Given et le @When mais pas le @Then, ce qui oblige à implémenter l’assertion que le lag est inférieur à 100.
Dans le code ci-dessus, on lance une requête à Prometheus pour récupérer les données liées au lag. Lorsqu’on lance le scénario, on obtient le résultat suivant :
Et sur Grafana on observe la courbe du lag :
Pour conclure cet exemple, on peut voir que l'écriture d'un scénario est facile et compréhensible par tout le monde. On a bien démontré la faisabilité d'un outil qui permet d'écrire des tests de résilience.
Ce qui peut être ajouté à la librairie serait des commandes qui permettent :
Ces ajouts permettraient de constater la réaction du système sur ces changements qui peuvent être causés par inadvertance.
Pour utiliser cette librairie en tant que produit et non plus un simple PoC, il est nécessaire de la rendre compatible avec différentes plateformes cloud, ce qui permettra de l’utiliser quel que soit l’environnement cible.
Il est intéressant de noter que cette librairie pourrait servir à faire un premier pas dans la mise en place du Chaos Engineering, en l’intégrant par exemple dans une CI et à une stack de monitoring. Comparée au Chaos Engineering, la librairie ne pourra pas directement être mise en place dans l’environnement de production mais plutôt dans des environnements qui s’en rapprochent (Pre-prod).
Pour conclure, un tel outil peut être intéressant à intégrer dans vos SI, car il permet d’écrire des tests de résilience qui soient facilement compréhensibles. Le fait de l’intégrer dans la CI avant la mise en production permet de faire un premier pas sans engranger les coûts associés à la mise en place d’une équipe dédiée.