
Sommaire
Lors de notre Weckathon, le hackathon annuel chez WeScale, nous avons relevé le défi de tester en une journée deux outils de chaos engineering issus de l’écosystème CNCF. Objectif : challenger ces solutions open source en simulant des pannes sur une application simple. Entre injections ciblées et comportements inattendus, le chaos s’est invité au cœur de notre infrastructure de test. Une expérience courte mais riche en enseignements !
Un peu de contexte
Le chaos engineering consiste à introduire volontairement des défaillances sur une architecture : crash, latence réseau, etc. ou sur une application pour observer sa résilience. C’est tout un programme de destruction, mais qui reste contrôlé ! L’idée n’est pas simplement de casser, mais de détecter les failles, de simuler des incidents qui pourraient arriver et d'observer et corriger le problème.
Pour la petite histoire, le chaos engineering est né chez Netflix en 2010 avec l’outil Chaos Monkey. Cet outil provoque des pannes aléatoires afin de tester la résilience du système. Cette approche a ensuite évolué vers des outils plus sophistiqués comme Gremlin, ou par de l’open source comme Chaos Mesh et Litmus, soutenus par la CNCF et sous licence Apache 2.0.
Avant de commencer
Le Weckathon se déroule souvent sur un thème ou un sujet choisi avec une équipe entre 2 et 5 personnes que nous ne connaissons pas. Le but de l’initiative est de découvrir et partager sur un sujet technique en un temps limité. Pour une journée de Weckathon optimale, avoir un environnement stable et fonctionnel le jour J est impératif, car les installations risquent de prendre plus de temps que prévu, et une journée ça passe vite… Nous avons donc installé sur l’un de nos deux laptops le nécessaire avant le jour J !
Kubernetes - L’environnement d'exécution
Les deux outils de chaos que nous allons tester sont conçus pour Kubernetes. Pour nos tests, nous avons fait le choix d’utiliser un cluster K3s, léger et simple à installer sur des VM en local. K3s a également l’avantage de disposer des principales caractéristiques d’un “vrai” cluster Kubernetes de production, ce qui devrait nous permettre de réaliser des expériences de Chaos plus réalistes.
WordPress et sa base MariaDB - L’application de test
Une fois notre environnement Kubernetes en place, il nous faut une application sur laquelle déchainer le chaos. Le choix de notre victime s’est porté sur WordPress que nous avons pu très simplement déployer un site WordPress complet en utilisant ce chart Helm.
K6 - Simulation du trafic
Pour simuler un trafic utilisateur nous avons utilisé l’outil K6 de Grafana Labs.
Un script K6 nous permet de lancer des tests de charge simples en paramétrant le nombre d’utilisateurs virtuels et la durée du test. K6 offre un premier niveau d’observabilité sur les métriques de base HTTP que sont la latence, les erreurs et le trafic : 3 des 4 golden signals à suivre.
Prometheus/Grafana - Observabilité
Afin de pouvoir observer plus finement le comportement de notre infrastructure lors des expériences de chaos, nous avons installé un stack Prometheus/Grafana à l’aide de ce Chart Helm communautaire. Il déploie Prometheus pour la collecte des métriques Kubernetes et Grafana pour consulter cette donnée dans une collection de dashboards prédéfinis. Ce qui nous permettra de gagner du temps lors de nos tests.
Un environnement prêt pour le jour J !
Nous arrivons donc le jour du Weckathon avec un environnement schématisé ci-dessous :
Sur cet environnement nous allons pouvoir :
- Déployer une solution de Chaos Engineering (Chaos Mesh / Litmus)
- Simuler du trafic sur notre site WordPress
- Observer les métriques applicatives et d’infrastructure kubernetes
- Lancer des expériences de Chaos et mesurer leurs impacts sur ces métriques.
Et c’est parti pour le chaos ! 🤘
Chaos Mesh, léger et simple
Installation
L’installation de Chaos Mesh 2.7.2 est simple à réaliser avec Helm en suivant la procédure d’installation.
Les principales étapes sont les suivantes :
- Ajouter le repo Helm Chaos Mesh :
helm repo add chaos-mesh https://charts.chaos-mesh.org
helm repo update
- Installer Chaos Mesh (namespace
chaos-mesh
) :
kubectl create namespace chaos-mesh
helm install chaos-mesh chaos-mesh/chaos-mesh -n=chaos-mesh
--set chaosDaemon.runtime=containerd
--set chaosDaemon.socketPath=/run/k3s/containerd/containerd.sock --version 2.7.2
La commande d'installation Helm ci-dessus est adaptée à k3s (socketPath spécifique pour le daemon). La procédure précise la commande à utiliser en fonction du type d’installation Kubernetes et du container runtime utilisé.
- Vérifier l'installation :
kubectl get pods -n chaos-mesh
NAME READY STATUS RESTARTS AGE
chaos-controller-manager-67b5f9d58f-9cvln 1/1 Running 2 (5h22m ago) 11d
chaos-controller-manager-67b5f9d58f-k9sv2 1/1 Running 4 (5h22m ago) 11d
chaos-controller-manager-67b5f9d58f-lqgwr 1/1 Running 3 (5h22m ago) 11d
chaos-daemon-99fft 1/1 Running 2 (5h22m ago) 11d
chaos-daemon-rxn2l 1/1 Running 2 (5h22m ago) 11d
chaos-daemon-zphdn 1/1 Running 2 (5h22m ago) 11d
chaos-dashboard-5966b8f56b-rlhxg 1/1 Running 2 (5h22m ago) 11d
chaos-dns-server-558955948b-nq2gs 1/1 Running 2 (5h22m ago) 11d
- Lancer le port-forwarding
Le pod du dashboard Chaos Mesh est associé à un service de type NodePort sur le port 2333 :
$ kubectl get services -n chaos-mesh
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
chaos-daemon ClusterIP None <none> 31767/TCP,31766/TCP 11d
chaos-dashboard NodePort 10.43.54.187 <none> 2333:32566/TCP,2334:31521/TCP 11d
chaos-mesh-controller-manager ClusterIP 10.43.116.63 <none> 443/TCP,10081/TCP,10082/TCP,10080/TCP 11d
chaos-mesh-dns-server ClusterIP 10.43.151.151 <none> 53/UDP,53/TCP,9153/TCP,9288/TCP 11d
Pour se connecter à l’interface web de Chaos Mesh, nous lançons un port-forward :
kubectl -n chaos-mesh port-forward svc/chaos-dashboard 2333:2333
Il est désormais possible de naviguer sur le dashboard de Chaos Mesh à l’adresse http://localhost:2333
Sous le capot
L'architecture de Chaos Mesh est composée de trois composants complémentaires :
- Le chaos-controller-manager joue le chef d'orchestre - il pilote toutes les expériences déclarées sous forme de Custom Resources Kubernetes.
- Le chaos-daemon sur chaque nœud du cluster via un DaemonSet - reçoit les instructions et applique les perturbations sur les pods du nœud ciblé. Cette approche distribuée marche car chaque daemon reste proche de ce qu'il doit perturber.
- Le chaos-dashboard est l’interface web, elle nous évite de jongler avec le YAML. L'interface web permet de créer ses expériences en quelques clics, de suivre ce qui se passe en temps réel et d'analyser les résultats. C'est appréciable quand on veut convaincre les équipes de se mettre au chaos engineering sans les rebuter avec de la ligne de commande.
Cette architecture modulaire, simple mais non simpliste nous permet de débuter rapidement.
Allez prenons en main l’interface et créons nos premiers scénarios de tests sans plus tarder !
Prise en main
Connexion
A la première connexion, Chaos Mesh nous demande de saisir un token pour se connecter :
Le lien “Click here to generate” nous renvoie vers une page permettant de créer ce token.
Notre approche étant de pouvoir tester l’application en mode “bac à sable” sans trop nous soucier des aspects de sécurité, nous générons ce token avec les paramètre suivants :
- Scope : cluster, pour pouvoir lancer des expériences sur tous les namespaces du cluster.
- Rôle: manager, pour nous permettre d’accéder à l’ensemble des fonctionnalités du dashboard (L’autre rôle proposé étant viewer).
L’interface ne permet pas de générer directement le token, il faudra copier le manifest et l’appliquer au cluster.
kind: ServiceAccount
apiVersion: v1
metadata:
namespace: default
name: account-cluster-manager-tuzmw
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: role-cluster-manager-tuzmw
rules:
- apiGroups: [""]
resources: ["pods", "namespaces"]
verbs: ["get", "watch", "list"]
- apiGroups: ["chaos-mesh.org"]
resources: [ "*" ]
verbs: ["get", "list", "watch", "create", "delete", "patch", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: bind-cluster-manager-tuzmw
subjects:
- kind: ServiceAccount
name: account-cluster-manager-tuzmw
namespace: default
roleRef:
kind: ClusterRole
name: role-cluster-manager-tuzmw
apiGroup: rbac.authorization.k8s.io
$ kubectl apply -f rbac.yaml
$ kubectl get sa -n default
NAME SECRETS AGE
account-cluster-manager-tuzmw 0 22h
default 0 32d
Il faut ensuite récupérer le nom du service account généré et créer un token pour celui-ci avant de le copier/coller sur le Chaos Mesh dashboard. Jusqu’ici rien de sorcier, mais nous devrons durant la matinée régénérer le token plusieurs fois. Nous aurions pu nous l’éviter en lisant la documentation jusqu’au bout grâce à l’option helm --set dashboard.securityMode=false
, mais rappelons nous que nous sommes dans les conditions d’un Weckathon ! 😀
Arrêtons-nous un moment sur les aspects sécurité; ce que nous venons de voir est une gestion assez fiable et de facto facilement intégrable en entreprise :
- Gestion de token avec une durée d'expiration de 2 heures environ pour se connecter au Chaos Dashboard.
- Il y a deux rôles possibles : viewer et manager
- La gestion des RBAC par défaut à appliquer sur le cluster
Prise en main du Dashboard
Pour prendre en main le dashboard, nous partons sur une expérience de type “Pod Fault” parmi les 12 catégories existantes. Cette catégorie propose 3 types d'expériences différentes :
- Pod failure (Rend le pod indisponible)
- Pod kill (Supprime le pod).
- Container kill (Stop un container dans le pod)
Nous choisissons l'expérience “Pod kill” pour laquelle il nous sera simple de constater son impact sur l’application.
Le dashboard est très intuitif de prime abord, on attendrait cependant un peu plus de reports sur les tests chaos, nous avons des compteurs génériques que nous n’avons pas trouvé pertinents.
Nous configurons le test, et très vite le nombre de clics devient agaçant.
Note : pour chaque test il y a deux parties à remplir : l’injection et l'expérimentation. Là encore, en termes d’UX/UI nous n’avons pas forcément trouvé cela pertinent. Pour un kill pod, les infos restent redondantes à saisir.
Sur l’expérience, nous pouvons visualiser et télécharger le YAML lié au test. Il est aussi possible d’uploader un YAML pour créer une nouvelle expérience.
L’interface nous permet de visualiser le YAML correspondant à notre expérience. Ce qui nous a nécessité pas mal d’actions et de clics dans l’interface du dashboard se traduit finalement par un manifest d’une quinzaine de lignes facile à interpréter. Le dashboard est utile pour la mise au point d'une expérience dont on ne connaît pas encore les différentes possibilités de paramétrage, mais à l’usage il sera sûrement plus simple et rapide de travailler directement avec le YAML pour l’appliquer en ligne de commande.
kind: PodChaos
apiVersion: chaos-mesh.org/v1alpha1
metadata:
namespace: wordpress
name: kill-pod-experiment-1
spec:
selector:
namespaces:
- wordpress
labelSelectors:
app.kubernetes.io/name: wordpress
mode: fixed
value: '1'
action: pod-kill
Il ne nous reste plus qu’à exécuter notre expérience et observer le résultat...
Avant le lancement de l’expérience, nos deux pods applicatifs WordPress et le pod MariaDB étaient bien en cours d'exécution :
$ kubectl get pods -n wordpress
NAME READY STATUS RESTARTS AGE
wordpress-854fbd45f-k2w7x 1/1 Running 0 18m
wordpress-854fbd45f-zxqnl 1/1 Running 0 5m49s
wordpress-mariadb-0 1/1 Running 0 29m
Après l’expérience, on constate que le pod wordpress-854fbd45f-k2w7x
a disparu et que Kubernetes l’a immédiatement remplacé par un pod wordpress-854fbd45f-4s2qf
plus récent :
$ kubectl get pods -n wordpress
NAME READY STATUS RESTARTS AGE
wordpress-854fbd45f-4s2qf 0/1 Running 0 12s
wordpress-854fbd45f-zxqnl 1/1 Running 0 6m20s
wordpress-mariadb-0 1/1 Running 0 30m
Nous avons démontré que l’on pouvait injecter une faute, en l'occurrence tuer un pod (Et au passage que Kubernetes fait bien son boulot pour maintenir le nombre de réplicas de pods défini dans le déploiement 🎉 Bon, on n’en doutait pas trop…)
Cette première expérience nous a permis d'acquérir un premier niveau de compréhension du fonctionnement de Chaos Mesh et de son dashboard. Son intérêt était cependant faible en termes d’impact sur l’application. Notre prochain objectif : trouver l'expérience qui nous permettra de mettre à genoux ce WordPress.
On fait monter la température
Pour espérer avoir plus d’impact sur notre application, nous décidons de nous intéresser à d’autres types d'expériences permettant d’injecter de la latence réseau et du stress sur les ressources des pods.
Associé à la documentation, le dashboard se révèle encore une fois une aide appréciable pour nous guider dans le paramétrage de types d’expériences que nous ne connaissons pas encore.
Chaque expérience a été configurée pour une durée de 1 minute, en lançant en parallèle le script K6 simulant une charge de 20 utilisateurs sur la même durée.
✅ Etat Normal
http_req_duration.......: avg=2.07s min=90.79ms max=5.77s
http_req_failed.........: 0.00% 0 out of 476
http_reqs...............: 476 7.718781/s
🙊 Injection d’un latence de 20ms sur tous les pods WordPress
http_req_duration.......: avg=3.93s min=95.76ms max=9.2s 💥 Latence : +45%
http_req_failed.........: 0.00% 0 out of 278
http_reqs...............: 278 4.482593/s
Impact modéré :
L'expérience induit une augmentation de 45% de la latence, mais l’impact fonctionnel est modéré (Pas de requêtes en échec).
🙉 Stress sur la mémoire sur un des deux pods applicatif pour atteindre sa “limit” (384M)
http_req_duration.......: avg=2.91s min=703.5ms max=8.21s
http_req_failed.........: 0.00% 0 out of 357
http_reqs...............: 357 5.950187/s
Impact faible :
Nous voyons bien l’impact sur la mémoire du pod mais pas grand chose sur la latence (k6). Le système absorbe bien cette dégradation partielle.
🙈 Stress sur la mémoire du pod MariaDB pour atteindre sa “limit” (384M).
http_req_duration.......: avg=22.93s min=10.05ms max=1m0s
http_req_failed.........: 15.90% 8 out of 53 💥 Requêtes en erreur
http_reqs...............: 53 0.87173/s
Impact critique :
La base de données est clairement le maillon faible de notre application. Une surcharge mémoire sur son pod provoque une forte latence et plus de 15% de requêtes failed (timeout).
Conclusion
Après seulement quelques heures de prise en main, notre mission de “Chaos Monkey” est accomplie.
Bien que très minimaliste, notre exemple avec WordPress démontre déjà l'intérêt d'un outil comme Chaos Mesh : Il nous permet de tester notre infrastructure de manière ciblée et unitaire. Combiné à des mesures d'observabilité, ces expériences nous ont aidé à identifier les composants les plus critiques de notre infrastructure, ceux sur lesquels agir en priorité pour améliorer la résilience de notre application.
Chaos Mesh est un outil simple à appréhender, léger en ressource et utile. Nous pensons que le dashboard peut encore s’améliorer en termes d’UX/UI. Nous regrettons le manque de gestion d’erreurs, une interface non homogène sur les expériences, notamment sur l’upload de YAML différents d’une page à une autre … Et il faut le dire, nous avons eu notre dose de clics pour la matinée.
A notre sens, le gros point fort de Chaos Mesh est de permettre de gérer les expériences en YAML à l’aide des Custom Resource Definitions de la solution dont la structure nous a semblé simple et intuitive. Ce type d'utilisation ouvre la voie à l’automatisation en intégrant par exemple le lancement d'expériences dans une chaîne de CI/CD (chose que nous n’avons pas testée).
Nous avons également apprécié l’approche sécurité nécessaire et suffisante et la documentation est bien fournie et didactique.
Cet outil se révèle très prometteur et s’avère être un excellent point de départ pour l'initiation au Chaos Engineering.
Notre journée de Weckathon est déjà bien avancée, mais cette première immersion dans le chaos nous donne envie d’aller plus loin. Tout au long de la journée, Litmus a souvent été mentionné comme une alternative mature et robuste par nos collègues WeScalers. Et si on se lançait dans son installation pour en faire un comparatif avec Chaos Mesh ? Ce sera l’objet de notre prochain article !
Article de Samia Kherrati et Sébastien Henne