Article
Ce qu’un état Terraform partagé coûte vraiment
Temps de lecture : 7 minutes
Une commande destinée à supprimer un enregistrement DNS a détruit l’infrastructure de production d’un éditeur SaaS, un vendredi après-midi. Trois personnes ont passé le week-end à la reconstruire.
Ce qui suit n’est pas le récit d’une erreur de manipulation. C’est l’analyse de ce qui a permis à une erreur de manipulation d’avoir cette portée.
Le système, tel qu’il était
Un état Terraform unique décrivait l’ensemble de l’infrastructure : les enregistrements DNS, les clusters Kubernetes, les interfaces applicatives, les images de conteneurs. Tout ce qui existait figurait dans un seul fichier, hébergé dans un compte de stockage partagé et manipulé depuis les postes de travail.
Cette configuration n’a rien d’exceptionnel. Elle est même la trajectoire par défaut : on commence par déclarer une ressource, puis une deuxième, et personne ne décide jamais explicitement de tout regrouper — c’est simplement ce qui arrive quand on ne décide rien.
Ce qui s’est passé
Une opération sur une ressource mineure. Une variable d’environnement absente au moment de l’exécution. La commande s’est appliquée à la totalité de l’état.
Le temps de comprendre ce qui se passait, la production n’existait plus.
La conclusion qu’il ne faut pas tirer
Il est tentant de s’arrêter à « il fallait faire attention ».
C’est la conclusion qui garantit que l’incident se reproduira, parce qu’elle ne change rien au système. Elle transforme une défaillance d’architecture en défaillance de vigilance, et la vigilance n’est pas une propriété qu’on peut exiger de façon fiable — surtout un vendredi à seize heures, dans une équipe de deux personnes qui ont passé la semaine à autre chose.
Un dispositif dans lequel une erreur d’inattention détruit la production est un dispositif défaillant. Cela reste vrai quelle que soit la personne qui commet l’erreur, et cela reste vrai les jours où personne ne la commet.
La cause racine
Un état unique signifie qu’il n’existe aucune limite au rayon de souffle.
C’est le point central, et il mérite d’être formulé précisément : dans cette configuration, toute commande — quelle que soit son intention, quelle que soit la ressource visée — s’exécute avec la capacité technique de détruire l’ensemble. L’écart entre « je supprime un enregistrement DNS » et « je détruis les clusters de production » n’est pas protégé par une barrière. Il est protégé par le fait que la commande est bien formée.
Trois autres manques ont amplifié l’incident.
Aucune séparation entre environnements. Rien ne distinguait techniquement ce qui pouvait être détruit sans conséquence de ce qui ne le pouvait pas.
Aucune relecture systématique du plan avant application. Terraform annonce ce qu’il s’apprête à faire ; encore faut-il que ce soit une étape obligatoire plutôt qu’une bonne habitude.
Aucune sauvegarde des charges applicatives sur Kubernetes. C’est le manque qui a coûté le plus de temps pendant le week-end. Reconstruire une infrastructure décrite en code est long mais mécanique. Reconstituer l’état applicatif qui vivait dedans, sans sauvegarde, l’est beaucoup moins.
Ce qui a été corrigé
La sauvegarde des clusters a été mise en place dans la foulée, avec Velero — ressources Kubernetes et volumes persistants. C’était le manque le plus coûteux et le plus rapide à combler.
Mais une sauvegarde ne prouve rien tant qu’elle n’a pas été restaurée. Le dispositif a donc été éprouvé : ressources Kubernetes et volumes persistants restaurés depuis les sauvegardes Velero dans un cluster de test, jusqu’au redémarrage effectif des applications.
Ce test donne ce qu’aucun rapport au vert ne donne : le temps réel de remise en service, l’ordre dans lequel les services doivent revenir, et la liste de ce qui ne revient pas tout seul. Entre deux restaurations testées, une sauvegarde n’est pas une garantie, c’est une hypothèse.
Le découpage de l’état, lui, est une correction plus lourde : elle demande de reprendre l’organisation du code, pas d’ajouter un outil.
Ce que je fais différemment aujourd’hui
Sur l’infrastructure que je construis actuellement, quatre décisions découlent directement de cet incident.
L’état est découpé selon deux axes. Le cycle de vie d’abord : ce qui ne doit jamais être détruit vit dans un état séparé de ce qui a vocation à l’être. La fréquence de changement ensuite : les ressources qu’on modifie tous les jours ne partagent pas leur état avec celles qu’on ne touche jamais. Une commande lancée dans le périmètre des enregistrements DNS n’a plus la capacité technique d’atteindre le cluster.
L’identité d’exécution est dédiée et bornée. Terraform ne s’exécute pas sous mon compte, mais sous une identité qui ne porte que les permissions de ce qu’il gère — pas de droits sur la facturation, pas de droits d’administration des identités. Les journaux d’audit distinguent ce que j’ai fait de ce que l’outil a fait.
L’état est protégé contre sa propre destruction. Le stockage qui contient l’état vit dans un projet distinct de celui qu’il décrit, et porte une protection explicite contre la suppression. Le principe : un mécanisme de reprise ne doit pas vivre dans ce qu’il répare.
Aucun secret permanent. L’authentification passe par des jetons de courte durée dérivés d’une identité, plutôt que par une clé qui traîne sur un disque.
Ce que j’en retiens
Le rayon de souffle d’une commande est une décision d’architecture, prise longtemps avant l’incident et généralement sans qu’on s’en aperçoive. On ne décide pas de tout mettre dans le même état ; on omet de décider le contraire, ce qui revient au même le jour où ça compte.
Et une sauvegarde ne vaut que par sa dernière restauration réussie.