OpenTofu en CI/CD : migrer sans transformer l’IaC en chantier
OpenTofu a gagné en maturité, mais la migration ne se résume pas à changer un binaire : tests, state, modules et garde-fous CI/CD à prévoir.
Passer de Terraform à OpenTofu ne consiste pas à remplacer terraform par tofu dans une image de CI. Sur les configurations simples, ce changement peut effectivement sembler transparent. Dans une infrastructure réelle, la question est plus large : compatibilité des modules, résolution des providers, fichiers de verrouillage, backend de state, droits d’accès, politiques de revue et procédures d’incident.
OpenTofu est une option sérieuse pour des équipes qui veulent garder une approche déclarative de l’infrastructure tout en réduisant leur dépendance aux évolutions de licence et de distribution de Terraform. Mais une migration propre ne se mesure pas au nombre de dépôts dont le pipeline passe au vert. Elle se mesure à la capacité à produire un plan compréhensible, à préserver le state, à appliquer des changements de façon contrôlée et à revenir en arrière sans improvisation.
Ce guide propose une méthode terrain pour intégrer OpenTofu dans une chaîne CI/CD existante, sans promettre une bascule universelle ni imposer une réécriture complète de l’IaC.
Pourquoi OpenTofu est devenu une option crédible en IaC
OpenTofu est un projet open source issu du code de Terraform 1.5.6, créé après le changement de licence de Terraform par HashiCorp à partir de la version 1.6. Le projet est hébergé par la Linux Foundation. Son ambition n’est pas de réinventer immédiatement l’IaC : il vise d’abord une continuité pragmatique pour les utilisateurs de la syntaxe HCL, des modules Terraform et des principaux providers.
Pour une équipe déjà équipée, cette continuité a une valeur concrète. Les conventions connues restent utiles :
- des fichiers
.tfécrits en HCL ; - des commandes de travail familières, comme
init,validate,planetapply; - une organisation par modules réutilisables ;
- un state distant avec verrouillage lorsque le backend le permet ;
- des providers pour piloter des API d’infrastructure telles qu’AWS, Azure, Google Cloud, GitHub, Kubernetes ou Cloudflare.
Ce n’est toutefois pas une garantie de compatibilité éternelle. OpenTofu et Terraform ont une base historique commune, mais ce sont désormais deux projets distincts. Leurs comportements, leurs options et leurs écosystèmes peuvent évoluer différemment. Une équipe doit donc éviter deux réflexes opposés : déclarer qu’une migration est forcément sans impact, ou la repousser par principe au motif qu’elle impliquerait de refaire tous les modules.
La bonne question est plus précise : quels dépôts, quels providers, quels backends et quels workflows de déploiement peuvent être validés avec OpenTofu sans augmenter le risque de production ?
Cette évaluation mérite une place dans le backlog d’ingénierie, au même titre qu’un changement de version de runtime, de runner ou d’outil de build. Elle s’inscrit aussi dans une logique de pipeline explicite : une chaîne CI/CD fiable ne devrait pas dépendre d’un binaire téléchargé implicitement ni d’une version flottante. Sur ce point, les principes exposés dans la structuration d’un pipeline CI/CD fiable s’appliquent directement à l’IaC.
Ne pas confondre compatibilité de syntaxe et compatibilité opérationnelle
Un dépôt qui passe tofu validate n’est pas encore prêt pour une migration. La validation vérifie principalement la cohérence de la configuration. Elle ne prouve ni que les providers s’installent comme attendu, ni que le backend est accessible, ni que le plan obtenu est acceptable, ni que l’application préservera les ressources déjà gérées.
Dans un pipeline d’infrastructure, plusieurs couches doivent fonctionner simultanément :
- le code HCL et les variables ;
- les modules locaux, privés ou publics ;
- les providers et leurs contraintes de version ;
- le fichier de verrouillage des dépendances ;
- le backend de state ;
- les mécanismes de verrouillage du state ;
- les identités utilisées par la CI ;
- les contrôles de sécurité et les politiques de revue ;
- les conventions d’exécution propres à chaque environnement.
Par exemple, un module peut utiliser un provider AWS, un provider Kubernetes et un provider GitHub. Même si les trois s’initialisent correctement sur le poste d’un développeur, le runner CI peut avoir un réseau différent, un cache différent ou des permissions différentes. Un plan peut donc réussir localement et échouer sur un runner éphémère.
Cette différence est fréquente lorsque la CI n’utilise pas la même identité que l’exécution humaine. L’usage d’identités courtes et fédérées via OpenID Connect est souvent préférable au dépôt de clés longues durées dans les variables de pipeline. Le sujet est détaillé dans OIDC en CI/CD : sortir des secrets statiques. Une migration OpenTofu est justement une bonne occasion de vérifier que l’authentification au cloud, au backend et aux registries ne repose pas sur des secrets historiques difficiles à auditer.
Il faut également distinguer deux réalités :
- la compatibilité de configuration, observée par l’analyse et le plan ;
- la compatibilité de gestion, observée lorsque l’outil relit l’état existant, interroge les APIs et calcule un diff sans proposer de recréer des ressources légitimes.
La seconde est la plus importante. Un plan qui propose la suppression puis la recréation d’une base de données, d’un cluster ou d’un enregistrement DNS critique n’est pas un détail de migration. C’est un signal d’arrêt.
Ce qui casse réellement lors d’une migration depuis Terraform
Les incidents ne viennent généralement pas de la commande tofu plan elle-même. Ils apparaissent à la frontière entre le code, les dépendances et l’état partagé.
Les providers, leurs versions et les fichiers de verrouillage
Les providers sont les plugins qui traduisent une configuration IaC en appels d’API. Leur sélection dépend notamment des contraintes définies dans les fichiers de configuration et des métadonnées conservées dans .terraform.lock.hcl. Ce fichier doit être versionné lorsqu’il est utilisé par le dépôt : il aide les développeurs et les runners à résoudre les mêmes versions de providers.
Avant toute bascule, vérifiez que les providers réellement utilisés par le dépôt sont accessibles avec OpenTofu et que leur résolution est reproductible en CI. Ne supprimez pas le fichier de verrouillage pour « débloquer » une initialisation. Cette solution masque le problème en laissant la pipeline choisir potentiellement d’autres versions de dépendances.
Une approche plus saine consiste à tester dans une branche dédiée, à examiner les modifications du lockfile et à les traiter comme une modification de dépendances classique. Si le dépôt utilise un miroir de providers, un proxy interne ou un cache, ce composant doit faire partie du test. Un runner qui télécharge directement depuis Internet n’évalue pas le même chemin qu’un runner de production isolé.
Les modules privés et les sources d’approvisionnement
Les modules sont souvent référencés depuis Git, un registre privé ou un chemin relatif. La syntaxe peut sembler identique, mais l’accès dépend d’éléments externes : jeton Git, clé SSH, configuration réseau, certificats internes, règles de proxy ou droits sur un registre.
Une migration doit donc inclure un test d’initialisation à froid : un environnement propre, sans répertoire .terraform préexistant et sans cache local hérité. C’est le seul moyen de vérifier que le pipeline sait reconstruire son environnement depuis les sources déclarées.
Le state distant et son verrouillage
Le state est l’élément le plus sensible. Il relie les adresses déclarées dans le code aux ressources créées chez les fournisseurs. Il peut contenir des métadonnées opérationnelles et, selon les ressources et les variables, des valeurs sensibles. Il ne doit jamais être traité comme un simple fichier de build.
Ne faites pas exécuter Terraform et OpenTofu en parallèle sur le même state sans procédure explicite. Même quand les formats sont compatibles dans votre cas, deux outils et deux pipelines qui tentent de modifier le même état augmentent inutilement le risque de concurrence, de verrouillage bloqué ou de changements difficiles à expliquer.
Le backend exact compte. Amazon S3, Azure Blob Storage, Google Cloud Storage, HashiCorp Terraform Cloud ou un backend HTTP ne fournissent pas tous les mêmes modalités de stockage, de verrouillage, d’authentification et d’audit. Il faut relire la documentation du backend effectivement utilisé, pas celle d’un exemple générique trouvé dans un dépôt public.
Les différences de comportement détectées par le plan
Un plan n’est pas une approbation automatique. Il faut examiner les changements proposés, en particulier pour les ressources à cycle de vie sensible : réseaux, règles de sécurité, certificats, identités IAM, bases de données, clusters Kubernetes, ressources DNS et buckets de stockage.
Les ressources déclarées comme sensibles ne doivent pas être affichées sans précaution dans les logs de CI. De même, un fichier de plan binaire peut contenir des informations qu’il ne faut pas publier comme artefact accessible à tous. La visibilité des logs, des artefacts et des rapports de pull request fait partie du modèle de sécurité de l’IaC.
Construire une pipeline OpenTofu qui ne donne pas un faux sentiment de sécurité
Une pipeline utile sépare les contrôles rapides, le calcul du changement et l’exécution ayant un impact réel. Mélanger ces étapes dans un job unique simplifie parfois le YAML, mais complique la revue, la traçabilité et le diagnostic.
Une base raisonnable comporte au minimum les étapes suivantes :
- formatage : exécuter
tofu fmt -checkpour détecter les écarts de style ; - validation : lancer
tofu initpuistofu validatedans un environnement contrôlé ; - plan : générer un plan pour l’environnement concerné, avec les variables et l’identité adéquates ;
- revue : rendre le résumé du plan lisible pour les personnes responsables du changement ;
- apply : exécuter l’application uniquement après les protections attendues sur la branche ou l’environnement.
Le formatage et la validation sont des garde-fous nécessaires, mais ils ne testent pas l’infrastructure distante. Le plan apporte cette confrontation avec les APIs et le state. L’apply reste une opération de production : il doit être limité à une branche protégée, à un environnement protégé ou à une procédure d’approbation cohérente avec le niveau de risque.
Dans GitHub Actions, GitLab CI/CD, Jenkins ou Azure Pipelines, le principe reste le même : la CI de pull request produit des informations de revue ; le déploiement est réservé à un contexte plus contrôlé. La publication automatique d’un plan dans un commentaire de pull request peut être pratique, à condition de filtrer les données sensibles et de maîtriser qui peut lire ce commentaire.
Évitez aussi l’apply déclenché automatiquement pour chaque changement de branche principale sans distinction entre les environnements. Une modification de module partagé peut affecter plusieurs stacks. Les dépendances entre dépôts et environnements doivent être visibles avant de rendre une étape destructive automatique.
Un pipeline IaC fiable ne prouve pas seulement que la syntaxe est correcte : il rend explicites l’identité utilisée, le state ciblé, le plan revu et la condition qui autorise l’application.
Les jobs doivent être idempotents autant que possible. Une relance ne doit pas transformer une panne temporaire de réseau en enchaînement de modifications imprévues. Pour approfondir ce point, consultez comment réduire les erreurs humaines avec des jobs idempotents.
Tester OpenTofu sans toucher immédiatement au state de production
La méthode la plus sûre est de commencer par des validations non destructives sur un périmètre limité. Sélectionnez un dépôt peu critique, avec une configuration compréhensible, des providers courants et une équipe disponible pour analyser les résultats.
Pour ce module pilote, exécutez OpenTofu dans une pipeline séparée ou dans des jobs explicitement nommés. L’objectif initial est de comparer les résultats, pas de remplacer brutalement le chemin existant. Selon votre organisation, cette phase peut inclure :
- une initialisation propre avec OpenTofu ;
- une validation syntaxique ;
- un plan en lecture seule sur un environnement de développement ou de préproduction ;
- une comparaison humaine avec le plan produit par l’outillage déjà en place ;
- un contrôle des versions de providers effectivement résolues ;
- une vérification des logs, des artefacts et des permissions du runner.
Ne cherchez pas forcément une identité textuelle parfaite entre deux sorties de plan. Les outils peuvent présenter les informations différemment. En revanche, cherchez une équivalence opérationnelle : aucune destruction inattendue, aucune recréation inexpliquée, aucune dérive de ressources préexistantes, aucune dépendance manquante et aucun écart de permissions.
Les environnements non productifs ne reproduisent pas toujours les permissions, volumes de données ou contraintes réseau de production. Ils restent cependant le bon point de départ. La migration du premier state de production ne doit être envisagée qu’après des résultats stables sur un périmètre représentatif.
Préparer une migration progressive des modules et des states
Une migration progressive doit être organisée par unités réellement opérables : un dépôt, une stack, un environnement ou un ensemble cohérent de modules. Évitez une bascule par équipe si cette équipe possède des dizaines de states aux caractéristiques différentes. Le critère utile est la capacité à observer, corriger et isoler le changement.
Pour chaque unité, documentez au moins :
- le dépôt et la branche de référence ;
- le backend de state et son emplacement ;
- le mécanisme de verrouillage ;
- les providers et modules critiques ;
- l’identité CI utilisée pour le plan et l’apply ;
- les environnements affectés ;
- les propriétaires techniques et les personnes de revue ;
- les conditions de retour au workflow précédent.
Avant une opération qui modifie la manière dont le state est géré, réalisez une sauvegarde conformément aux capacités de votre backend et à vos procédures internes. Vérifiez qu’elle est récupérable, chiffrée si nécessaire et accessible uniquement aux personnes autorisées. Une sauvegarde théorique que personne ne sait localiser au moment d’un incident ne protège pas l’équipe.
La migration doit aussi être séquencée. Une bonne pratique consiste à séparer :
- le changement d’outil de la modification fonctionnelle de l’infrastructure ;
- la mise à jour des versions de providers de la bascule OpenTofu ;
- la refonte de modules de la migration de state ;
- le changement d’authentification de la première exécution d’apply.
Cette discipline réduit le nombre de variables à diagnostiquer. Si un plan change après une migration qui inclut aussi une mise à jour majeure de provider et une refonte de module, il devient très difficile de déterminer l’origine du diff.
Définir des critères de retour arrière avant le premier apply
Un retour arrière ne doit pas être une formule vague du type « on repassera sur Terraform si besoin ». Il doit préciser qui décide, dans quelles situations, et quel outil a le droit de réagir sur quel state.
Des critères objectifs peuvent inclure :
- un plan proposant des destructions ou remplacements non expliqués ;
- une impossibilité à obtenir le verrouillage attendu du state ;
- une différence non comprise dans la résolution des providers ;
- un échec d’authentification qui conduit à envisager l’ajout de secrets statiques ;
- une absence de traçabilité suffisante dans les logs ou les revues ;
- un comportement divergent sur une ressource critique non reproductible hors production.
En cas d’alerte, la première réponse doit être de stopper les apply concurrents, conserver les logs et le plan concernés, puis analyser l’état réel des ressources et du backend. L’urgence ne justifie pas d’exécuter successivement plusieurs commandes de manipulation de state sur un environnement partagé.
Les équipes gagnent à prévoir une courte revue après chaque migration pilote : écarts observés, temps de pipeline, problèmes de cache, droits manquants, qualité du plan, lisibilité des logs et ajustements de documentation. Cette boucle est plus utile qu’un programme de migration traité comme une opération purement outillage.
Gouverner OpenTofu comme un composant de la plateforme interne
Si plusieurs équipes utilisent l’IaC, OpenTofu ne doit pas devenir une collection d’images Docker, de scripts shell et de versions différentes maintenues au hasard. Une plateforme interne peut fournir un chemin par défaut : version d’OpenTofu explicitement choisie, image de runner maintenue, politiques de cache, authentification fédérée, conventions de backend et modèle de pipeline réutilisable.
Le but n’est pas de retirer toute autonomie aux équipes. Il est d’éviter que chacune redécouvre les mêmes problèmes de state, de credentials et de revue de plan. Cette logique rejoint l’intérêt des golden paths DevOps : proposer une voie sûre et rapide, tout en laissant une procédure d’exception documentée pour les besoins réellement particuliers.
Surveillez également vos flux de déploiement de bout en bout. Un statut vert dans GitHub Actions ou GitLab ne signifie pas nécessairement qu’un changement a été pris en compte par toutes les dépendances concernées. La supervision des étapes, des délais et des échecs récurrents est décrite dans la supervision des flux de déploiement.
Conclusion : traiter la migration OpenTofu comme un changement d’exploitation
OpenTofu offre une voie crédible aux équipes IaC qui veulent conserver leurs pratiques déclaratives sans transformer leur patrimoine Terraform en chantier de réécriture. Mais le succès ne dépend pas uniquement de la compatibilité HCL. Il repose sur la maîtrise des providers, des modules, du lockfile, du state, des identités CI et des conditions d’apply.
Commencez petit : choisissez un module pilote, testez une initialisation propre, analysez les plans, isolez le state et préparez un retour arrière avant tout changement de production. Une fois ce cadre validé, vous pourrez étendre la migration par lots cohérents, avec des preuves opérationnelles plutôt qu’avec des suppositions.
La prochaine étape utile est simple : inventoriez vos states et vos providers, puis sélectionnez le périmètre le moins critique mais le plus représentatif pour lancer un premier test OpenTofu en CI/CD.