<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Consul on Zwindler's Reflection</title><link>https://blog.zwindler.fr/tags/consul/</link><description>Recent content in Consul on Zwindler's Reflection</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>Licensed under CC BY-SA 4.0</copyright><lastBuildDate>Mon, 29 Aug 2022 06:45:00 +0200</lastBuildDate><atom:link href="https://blog.zwindler.fr/tags/consul/index.xml" rel="self" type="application/rss+xml"/><item><title>Avec Terragrunt, ne répétez plus vos variables Terraform 358 fois</title><link>https://blog.zwindler.fr/2022/08/29/terragrunt-ne-repetez-plus-vos-variables-terraform/</link><pubDate>Mon, 29 Aug 2022 06:45:00 +0200</pubDate><guid>https://blog.zwindler.fr/2022/08/29/terragrunt-ne-repetez-plus-vos-variables-terraform/</guid><description>&lt;img src="https://blog.zwindler.fr/2022/08/terragrunt.webp" alt="Featured image of post Avec Terragrunt, ne répétez plus vos variables Terraform 358 fois" /&gt;&lt;p&gt;Cet article a initialement été écrit avec &lt;a class="link" href="https://deezer.io/terragrunt-dont-repeat-your-terraform-variables-358-times-b6cdb4e09e9f" target="_blank" rel="noopener"
&gt;ma collègue Chahrazed Yousfi (zed) en anglais&lt;/a&gt;. C&amp;rsquo;est donc une traduction pour mes copains francophiles ;-).&lt;/p&gt;
&lt;h2 id="mais-pourquoi-tu-fais-çaaaaaa-"&gt;Mais pourquoi tu fais çaaaaaa ???
&lt;/h2&gt;&lt;p&gt;L&amp;rsquo;article qui suit parle d&amp;rsquo;un cas d&amp;rsquo;usage avancé de Terraform qui n&amp;rsquo;est probablement pas nécessaire d&amp;rsquo;aborder pour un débutant. Si jamais vous voulez un aperçu de ce qu&amp;rsquo;on peut faire avec Terraform, vous pouvez aller relire mon article &lt;a class="link" href="https://blog.zwindler.fr/2018/01/16/premiers-pas-avec-Terraform/" &gt;Premiers pas avec Terraform&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Au travail, la majorité de notre infrastructure est hébergée sur site (hors d&amp;rsquo;un cloud) et dans la plupart des cas ça nous convient.&lt;/p&gt;
&lt;p&gt;Mais maintenir un service en ligne avec des infras en propre c&amp;rsquo;est parfois compliqué et il arrive que les services proposés par les cloud providers soient plus adaptés à nos besoins que ce que nous, l&amp;rsquo;équipe SRE, pouvons apporter à nos utilisateurs (les développeurs).&lt;/p&gt;
&lt;p&gt;Pour gérer de manière &amp;ldquo;DevOps&amp;rdquo; ces services &amp;ldquo;cloud&amp;rdquo;, nous utilisons un outil d&amp;rsquo;Infrastructure as Code (IaC) : Terraform de Hashicorp.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Terraform is an open-source infrastructure as code software tool that provides a consistent CLI workflow to manage hundreds of cloud services. Terraform codifies cloud APIs into declarative configuration files.
– Terraform website&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ce que nous aimons vraiment avec Terraform c&amp;rsquo;est que cet outil nous permet de construire une infrastructure &amp;ldquo;répétable&amp;rdquo; avec seulement quelques lignes de HCL (le domain-specific-langage de Hashicorp). L&amp;rsquo;état de l&amp;rsquo;infrastructure est stocké soit en local (dans un fichier) soit sur un système de stockage externe. Seule la différence entre ce qu&amp;rsquo;on écrit dans le code et ce qui est stocké dans ce &lt;em&gt;state&lt;/em&gt; est appliquée/modifiée. Dernier point, l&amp;rsquo;outil est devenu un standard de-facto, ce qui est beaucoup à obtenir des services fiables et facilite l&amp;rsquo;onboarding des équipes de dev.&lt;/p&gt;
&lt;p&gt;Pour donner une idée de notre usage de Terraform, le répository sur lequel nous stockons notre IaC représente :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pratiquement 1000 fichiers &amp;ldquo;.tf&amp;rdquo; de Terraform, pour environ 35k lignes&lt;/li&gt;
&lt;li&gt;Environ 4000 commits, 1500 pull-requests&lt;/li&gt;
&lt;li&gt;Plus de 40 contributeurs venant de diverses équipes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="les-limites-de-terraform-"&gt;Les limites de Terraform ?
&lt;/h2&gt;&lt;p&gt;Tant que vous avez peu d&amp;rsquo;objets dans Terraform, tout va bien.&lt;/p&gt;
&lt;p&gt;Mais quand vous commencez à avoir des centaines de fichiers (comme nous), cela devient compliqué de travailler simultanément sur le même code Terraform. Le fichier qui stocke l&amp;rsquo;état de l&amp;rsquo;infrastructure doit être à jour et synchronisé entre tous les contributeurs.&lt;/p&gt;
&lt;p&gt;Cela provoque des problématiques de &amp;ldquo;locking&amp;rdquo;, le calcul des &amp;ldquo;diffs&amp;rdquo; est de plus en plus long. En scalant, l&amp;rsquo;expérience utilisateur de Terraform se dégrade dans le temps.&lt;/p&gt;
&lt;p&gt;Il y a plusieurs stratégies pour contourner cela, mais nous n&amp;rsquo;avons pas trouvé de solution qui éclipsait tous nos problèmes.&lt;/p&gt;
&lt;p&gt;Par exemple, il est possible de découper le code Terraform dans différents dépôts git et avoir un état Terraform pour chacun d&amp;rsquo;entre eux. De cette manière, chaque équipe devient autonome est peut travailler de manière indépendante sur leur infrastructure. Cependant, le code Terraform tend à être dupliqué de projet en projet, puis d&amp;rsquo;équipe en équipe (même en utilisant les modules Terraform, on en parlera plus tard).&lt;/p&gt;
&lt;p&gt;D&amp;rsquo;expérience, du code dupliqué conduit à des erreurs humaines et nous essayons donc d&amp;rsquo;éviter ça le plus possible.&lt;/p&gt;
&lt;p&gt;Une autre solution pourrait être de créer un gros &amp;ldquo;monorepo&amp;rdquo; dans lequel on dépose tous les projets Terraform dans des répertoires différents (chacun avec son &amp;ldquo;state&amp;rdquo;). On peut utiliser des modules Terraform pour factoriser le code HCL commun de ses dossiers, soit directement dans le même monorepo, soit dans des dépôts distants.&lt;/p&gt;
&lt;p&gt;Mais même comme ça, on se retrouve toujours à dupliquer toujours les mêmes variables (comme le &amp;ldquo;billing account&amp;rdquo; de votre cloud provider, par exemple, ou toute autre valeur que vous utilisez tout le temps).&lt;/p&gt;
&lt;h2 id="arrive-alors-terragrunt-"&gt;Arrive alors Terragrunt !
&lt;/h2&gt;&lt;p&gt;Pour contourner certaines des limitations de Terraform, la société &lt;a class="link" href="https://gruntwork.io/" target="_blank" rel="noopener"
&gt;Gruntwork&lt;/a&gt; a créé un outil appelé Terragrunt, qui pour le dire simplement, est un wrapper de Terraform.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note :&lt;/strong&gt; vous connaissez peut-être déjà Gruntwork pour certains autres outils &amp;ldquo;cloud native&amp;rdquo;, notamment &amp;ldquo;&lt;a class="link" href="https://terratest.gruntwork.io/" target="_blank" rel="noopener"
&gt;Terratest&lt;/a&gt;&amp;rdquo; (qui permet de tester son code Terraform), &amp;ldquo;AWS Infrastructure as Code Library”, &amp;ldquo;Gruntwork Landing Zone for AWS&amp;rdquo;, etc.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;idée principale mise en avant par Terragrunt est que le code Terraform devrait pouvoir être écrit de manière à ne jamais avoir à répéter quoique ce soit (philosophie DRY pour &lt;a class="link" href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" target="_blank" rel="noopener"
&gt;Don&amp;rsquo;t Repeat Yourself&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Dans ce post, je vous montrerai donc une façon (opinionated) d&amp;rsquo;utiliser les fonctions principales de Terragrunt, pour vous montrer qu&amp;rsquo;on peut éviter de se répéter 358 fois ;-).&lt;/p&gt;
&lt;h2 id="on-se-prépare"&gt;On se prépare
&lt;/h2&gt;&lt;p&gt;La première chose à faire pour commencer à travailler avec Terragrunt est bien sûr de l&amp;rsquo;installer ;-). Le &lt;a class="link" href="https://github.com/gruntwork-io/terragrunt" target="_blank" rel="noopener"
&gt;code source de Terragrunt est disponible ici&lt;/a&gt; et les &lt;a class="link" href="https://github.com/gruntwork-io/terragrunt/releases" target="_blank" rel="noopener"
&gt;binaires précompilés sont disponibles là&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pour avoir une bonne idée des fonctionnalités offerts par Terragrunt, je vous propose d&amp;rsquo;utiliser un environnement cloud de démo avec la hiérarchie suivante :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/08/gcp-org.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note :&lt;/strong&gt; Pour cet exemple on a choisi &lt;em&gt;Google Cloud Platform&lt;/em&gt; comme cloud provider, mais Terragrunt peut évidemment être utile dans bien d&amp;rsquo;autres contextes. L&amp;rsquo;avantage de GCP dans ce cas là, c&amp;rsquo;est qu&amp;rsquo;il existe des &lt;em&gt;folders&lt;/em&gt; et des &lt;em&gt;projects&lt;/em&gt;, qui nous permettent de gérer les droits par département, équipe, etc.&lt;/p&gt;
&lt;p&gt;Dans cette démo, on va utiliser un dépôt git, qui contient initialement du code Terraform classique, et on va ensuite le dé-dupliquer étape par étape avec l&amp;rsquo;aide de Terragrunt.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/deezer/terragrunt-example/" target="_blank" rel="noopener"
&gt;github.com/deezer/terragrunt-example/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pour des raisons de lisibilité, on va décrire les actions étapes par étapes mais pas afficher le code entier à chaque fois. Vous pouvez naviguer entre les commits pour voir le résultat.&lt;/p&gt;
&lt;h2 id="factoriser-les-variables"&gt;Factoriser les variables
&lt;/h2&gt;&lt;p&gt;Avoir beaucoup de projets différents implique qu&amp;rsquo;on va avoir beaucoup de variables à déclarer. Et beaucoup de ces variables vont souvent être identiques &lt;strong&gt;ou&lt;/strong&gt; similaires d&amp;rsquo;un projet à l&amp;rsquo;autre. Le souci, c&amp;rsquo;est que copier le code d&amp;rsquo;un projet devient alors source importante d&amp;rsquo;erreurs humaines. Si on oublie de changer une variable au milieu de celles qui doivent être copiées, le résultat peut être fâcheux.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est d&amp;rsquo;abord pour cette raison que nous avons cherché une solution pour factoriser nos variables Terraform (nous ne pouvions pas être les seuls à avoir ce problème).&lt;/p&gt;
&lt;p&gt;Nous cherchions également une solution qui serait compatible avec un système d&amp;rsquo;héritage et nous avons trouvé Terragrunt !&lt;/p&gt;
&lt;p&gt;La capture d&amp;rsquo;écran qui suit est un aperçu de ce qu&amp;rsquo;on a pu faire avec Terragrunt pour les variables d&amp;rsquo;un &amp;ldquo;projet&amp;rdquo; GCP. Nous disposons maintenant d&amp;rsquo;un moyen pour factoriser la quasi-totalité de nos variables à différents niveaux hiérarchiques, et je vais vous montrer comment ! 😉&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/08/before_after.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="un-fichier-de-configuration"&gt;Un fichier de configuration
&lt;/h2&gt;&lt;p&gt;La première chose qu&amp;rsquo;on va faire est de créer un fichier terragrunt.hcl qui va contenir les informations utilisées par Terragrunt pour fonctionner.&lt;/p&gt;
&lt;p&gt;Ce fichier est écrit dans la même syntaxe que Terraform (c&amp;rsquo;est du HCL), avec en plus des &lt;a class="link" href="https://terragrunt.gruntwork.io/docs/reference/built-in-functions/" target="_blank" rel="noopener"
&gt;fonctions supplémentaires&lt;/a&gt;. Pour plus de détails, vous pouvez aller voir &lt;a class="link" href="https://terragrunt.gruntwork.io/docs/getting-started/configuration/" target="_blank" rel="noopener"
&gt;la page officielle de documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pour notre démo, j&amp;rsquo;ai besoin de créer le fichier terragrunt.hcl à 2 niveaux dans mon repository :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un premier au niveau de mon projet (là où sont mes fichiers .tf), pour indiquer à Terragrunt qu&amp;rsquo;il peut s&amp;rsquo;éxecuter ici. Pour faire simple j&amp;rsquo;appelerai ça le &amp;ldquo;fichier de configuration local&amp;rdquo;&lt;/li&gt;
&lt;li&gt;un second au niveau de la racine de mon dépôt git, où on mettra toute la configuration qui sera commune à tous les répertoires. Je l&amp;rsquo;appellerai &amp;ldquo;fichier de configuration global&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le dépôt va avoir la structure suivante :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/08/folders.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Au niveau du projet (dans le fichier de conf &amp;ldquo;local&amp;rdquo;), on va ajouter un bloc &lt;strong&gt;include&lt;/strong&gt;, suivi par la fonction &lt;em&gt;find_in_parent_folders()&lt;/em&gt;. Cette fonction recherche dans les répertoires parents jusqu&amp;rsquo;à trouver un autre fichier terragrunt.hcl. La fonction renvoie ensuite le chemin pour retrouver le fichier terragrunt.hcl &amp;ldquo;global&amp;rdquo; (situé à la racine), qui contient toute la configuration commune à tous les fichiers terragrunt.hcl.&lt;/p&gt;
&lt;p&gt;Ce bloc nous permet donc de récupérer la configuration déclarée à la racine. Les projets ne contiennent donc pas de configuration spécifique, puisque vous est basé sur la configuration &amp;ldquo;globale&amp;rdquo;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;include&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;path&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;find_in_parent_folders(&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;terragrunt.hcl&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="variables-globales"&gt;Variables globales
&lt;/h2&gt;&lt;p&gt;Admettons maintenant qu&amp;rsquo;on veut qu&amp;rsquo;un certain nombre de variables soient identiques pour tous les projets, comme pour le &amp;ldquo;billingID&amp;rdquo; par exemple. Pour le faire, on va ajouter des &lt;a class="link" href="https://terragrunt.gruntwork.io/docs/features/inputs/#inputs" target="_blank" rel="noopener"
&gt;inputs&lt;/a&gt; dans le fichier de configuration globale :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;inputs&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;billing_account&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;012345-ABCDEF-UVWXYZ&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;organization_id&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;12345678&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;region&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;europe-west1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;zone&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;europe-west1-b&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Les &lt;strong&gt;inputs&lt;/strong&gt; permettent de remplacer des variables déclarées (mais vides) dans les projets. Souvent, on déclare ces variables dans un fichier variables.tf, au niveau du projet lui-même.&lt;/p&gt;
&lt;p&gt;Une fois que vous déclarez la variable et son type, elle sera automatiquement remplacée par la valeur déclarée globalement (plus haut), par Terragrunt.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;billing_account&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;type&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;De cette manière, on peut donc déclarer une seule fois les variables qui sont valables pour TOUS les projets.&lt;/p&gt;
&lt;p&gt;Mais comment faire si jamais on a envie de mutualiser des valeurs qu&amp;rsquo;avec une partie de nos projets et pas tous ?&lt;/p&gt;
&lt;h2 id="variables-intermédiaires"&gt;Variables intermédiaires
&lt;/h2&gt;&lt;p&gt;Contrairement aux fonctions, qui ne sont utilisables que dans le fichier de configuration terragrunt.hcl, il est possible de configurer des &lt;strong&gt;inputs&lt;/strong&gt; dans d&amp;rsquo;autres fichiers &amp;ldquo;.hcl&amp;rdquo;. On peut donc les mettre où on veut dans notre dépôt, idéalement à un endroit intelligent dans notre hiérarchie de dossiers, histoire que tous les projets similaires héritent des mêmes variables.&lt;/p&gt;
&lt;p&gt;Pour le faire, on va utiliser la fonction &lt;em&gt;read_terragrunt_config&lt;/em&gt; dans la configuration globale pour tous les fichiers &amp;ldquo;.hcl&amp;rdquo; qu&amp;rsquo;on va vouloir inclure, puis fusionner tout ça ensemble.&lt;/p&gt;
&lt;p&gt;Pour donner un exemple, si pour dossier et sous-dossiers donné on a un même tag &amp;ldquo;team leader&amp;rdquo; ou &amp;ldquo;point de contact&amp;rdquo;, on va positionner un fichier team.hcl dans le dossier qui les englobe tous.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;inputs&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;merge(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;read_terragrunt_config(find_in_parent_folders(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;global.hcl&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;)).inputs,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;read_terragrunt_config(find_in_parent_folders(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;team.hcl&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;)).inputs,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Dans le cas de la team-a, ce fichier pourrait être placé ici : &lt;em&gt;dept-datascience/team-a/team.hcl&lt;/em&gt;, avec les valeurs suivantes :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;inputs&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;tech_lead&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;Freddie Mercury&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;contact&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;fmercury@gmail.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pour la team-b, &lt;em&gt;dept-datascience/team-b/team.hcl&lt;/em&gt; et les valeurs :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;inputs&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;tech_lead&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;Abel Tesfaye&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;contact&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;atesfaye@gmail.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notre arborescence d&amp;rsquo;exemple devrait ressembler à ça maintenant :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2022/08/folders2.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="variables-non-factorisables"&gt;Variables non factorisables
&lt;/h2&gt;&lt;p&gt;On ne peut pas toujours factoriser toutes les variables pour tous les projets. Il arrive qu&amp;rsquo;il soit nécessaire de faire des exceptions, par exemple, un projet va être déployé dans une région inhabituelle.&lt;/p&gt;
&lt;p&gt;Si jamais vous avez besoin d&amp;rsquo;écraser la valeur par défaut, déclarée dans un niveau supérieur, c&amp;rsquo;est possible. Il suffit de déclarer un &lt;em&gt;inputs&lt;/em&gt; dans la configuration locale de Terragrunt en utilisant le même nom.&lt;/p&gt;
&lt;h2 id="allez-plus-haut"&gt;Allez plus haut
&lt;/h2&gt;&lt;p&gt;En tant que SREs, on cherche toujours à automatiser toujours plus de tâches manuelles.&lt;/p&gt;
&lt;p&gt;Grâce aux fonctions de Terragrunt, nous avons trouvé comment automatiser la configuration de la variable &amp;ldquo;name&amp;rdquo; de nos projets GCP. Nous avons décidé que tous les projets (name + ID) devraient être définis directement par le nom du répertoire dans lequel le code Terraform/Terragrunt est stocké.&lt;/p&gt;
&lt;p&gt;On peut le faire de la façon suivante dans le fichier de configuration global&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;inputs&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;project_name&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;basename(get_terragrunt_dir())&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;De cette manière, nous n&amp;rsquo;avons plus à ne pas oublier de changer le &lt;em&gt;project_name&lt;/em&gt; ou &lt;em&gt;projet_id&lt;/em&gt; dans nos ressources Terraform ou notre variables.tf quand on copie du code. On se base simplement sur la variable &lt;em&gt;project_name&lt;/em&gt;, qui est déduite automatiquement du dossier concerné.&lt;/p&gt;
&lt;h2 id="configuration-du-backend-terraform"&gt;Configuration du backend Terraform
&lt;/h2&gt;&lt;p&gt;Au travail, pour stocker nos états Terraform (les fameux fichiers de state), nous utilisons un bucket GCS. Tous les états des projets sont stockés dans des chemins différents et parfois dans des buckets GCS différents. Mais ce chemin doit toujours contenir le nom du projet et le nom du bucket concerné.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;backend&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;gcs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;bucket&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;tfstate-team-a&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;prefix&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;team-a-proj-product1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Avec Terraform, il est impossible de variabiliser cette partie &lt;strong&gt;backend&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a backend block cannot refer to named values (like input variables, locals, or data source attributes).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Heureusement, Terragrunt propose lui la possibilité de le faire, dans un bloc &lt;em&gt;remote_state&lt;/em&gt; à ajouter dans le fichier de configuration global.&lt;/p&gt;
&lt;p&gt;Dans notre exemple, nous avons décidé de créer des buckets qui seraient mutualisés pour quelques projets chacun.&lt;/p&gt;
&lt;p&gt;On les définit donc dans un fichier backend.hcl placé au plus haut des sous dossiers que le bucket va gérer. On réutilise la même technique que précédemment (inputs + &lt;em&gt;find_in_parent_folders()&lt;/em&gt; + &lt;em&gt;read_terragrunt_config()&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;Par exemple, tous les projets de la team-a utilisent le même &amp;ldquo;tfstate-teamA&amp;rdquo;, on va donc créer le backend.hcl à la racine du dossier team-a.&lt;/p&gt;
&lt;p&gt;Pour ce qui est du préfixe (le chemin du state dans le bucket), on utilise ensuite une fonction &lt;em&gt;path_relative_to_include&lt;/em&gt;() qui renvoie le chemin relatif depuis la racine du dépôt.&lt;/p&gt;
&lt;p&gt;Dans l&amp;rsquo;exemple, le path pour team-a-proj-product1 ça serait &lt;em&gt;dept-datascience/team-a/product1/team-a-proj-product1&lt;/em&gt;. Ca nous permet de nous assurer que le state est toujours stocké dans un endroit unique.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;remote_state&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;backend&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;gcs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;config&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;bucket&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;read_terragrunt_config(find_in_parent_folders(&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;backend.hcl&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;)).inputs.bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;prefix&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;path_relative_to_include()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note : dans cet exemple particulier, on voit bien que la façon dont on nomme nos dossiers ainsi que la hiérarchie des dossiers est très importante pour faciliter la façon dont on décrit notre configuration. Pour autant, ce n&amp;rsquo;est qu&amp;rsquo;un exemple et on peut tout à fait gérer cela différemment tout en profitant des fonctions de Terragrunt.&lt;/p&gt;
&lt;p&gt;Dans notre projet, on devra remplacer la configuration du backend par l&amp;rsquo;extrait suivant. La configuration du backend sera automatiquement remplie par terragrunt à partir de la configuration globale.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;backend&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;gcs&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="une-commande-pour-les-contrôler-toutes"&gt;Une commande pour les contrôler toutes&amp;hellip;
&lt;/h2&gt;&lt;p&gt;Une commande que nous n&amp;rsquo;attendions pas et que nous avons découverte avec Terragrunt est l&amp;rsquo;ajout d&amp;rsquo;un &lt;code&gt;run-all&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;run-all est une commande de la CLI Terragrunt qui permet de lancer de manière terragrunt dans tous les sous-dossiers contenant un terragrunt.hcl.&lt;/p&gt;
&lt;p&gt;Si vous avez changé une des globales variables, vous pouvez appliquer le changement à tous vos projets d&amp;rsquo;un seul coup avec la commande suivante :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ terragrunt run-all apply
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On peut également utiliser cette fonction dans une CI/CD pour s&amp;rsquo;assurer que l&amp;rsquo;infrastructure est toujours à jour et qu&amp;rsquo;il n&amp;rsquo;y a pas eu de &amp;ldquo;drift&amp;rdquo;.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;J&amp;rsquo;espère vous avoir convaincu que Terragrunt peut réellement être utile lorsque vous travaillez avec un grand nombre de fichiers Terraform.&lt;/p&gt;
&lt;p&gt;Cela nécessite un peu de rigueur et de réflexion pour créer une hiérarchie de dossiers, de manière à mutualiser de manière intelligente les variables dans l&amp;rsquo;arborescence.&lt;/p&gt;
&lt;p&gt;Même si Terragrunt ajoute un peu de complexité, il permet également d&amp;rsquo;obtenir de nouvelles fonctions et facilite l&amp;rsquo;automatisation et la factorisation du code.&lt;/p&gt;
&lt;p&gt;Tout ceci permet ensuite d&amp;rsquo;avoir du code plus propre, plus maintenable, moins dupliqué.&lt;/p&gt;
&lt;p&gt;Je ne conseille pas de commencer directement avec Terragrunt si vous débutez dans Terraform (ça ajoute quand même un peu de complexité pour peu de gain). Cependant, si vous commencez à avoir beaucoup de fichier, de contributeurs, vous devriez clairement le tester.&lt;/p&gt;
&lt;h2 id="dautres-ressources-externes-sur-le-sujet"&gt;D&amp;rsquo;autres ressources externes sur le sujet
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://deezer.io/terragrunt-dont-repeat-your-terraform-variables-358-times-b6cdb4e09e9f" target="_blank" rel="noopener"
&gt;L&amp;rsquo;article en anglais co-écrit par ma collègue &lt;strong&gt;zed&lt;/strong&gt; et moi même&lt;/a&gt; (EN)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/deezer/terragrunt-example" target="_blank" rel="noopener"
&gt;github.com/deezer/terragrunt-example - le code de l&amp;rsquo;article&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.zwindler.fr/talks/2022-terraform-vraiment-factorise-terragrunt/index.html" target="_blank" rel="noopener"
&gt;Mon support de conférence &amp;ldquo;Du code Terraform VRAIMENT factorisé avec Terragrunt&lt;/a&gt; (FR)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://medium.com/cncf-cloud-native-landscape-by-sphinxgaia-j%C3%A9r%C3%B4me/et-si-on-emballait-Terraform-de-hashicorp-b815b78dd178" target="_blank" rel="noopener"
&gt;Jérôme Masson - Terraform : remote state configuration DRY avec Terragrunt&lt;/a&gt; (FR)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://ichi.pro/fr/terragrunt-comment-garder-votre-code-terraform-sec-et-maintenable-270595294583256" target="_blank" rel="noopener"
&gt;Ichi pro - Gardez votre code terraform &amp;ldquo;sec&amp;rdquo;&lt;/a&gt; (FR)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://easyteam.fr/terraform-remote-state-configuration-dry-avec-terragrunt/" target="_blank" rel="noopener"
&gt;easyteam FR - Configuration DRY avec terragrunt&lt;/a&gt; (FR)&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.padok.fr/en/blog/Terraform-code-terragrunt" target="_blank" rel="noopener"
&gt;Blog de Padok - Reduce redundancy in your Terraform code with Terragrunt&lt;/a&gt; (EN)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gaunacode.com/using-terragrunt-to-deploy-to-azure" target="_blank" rel="noopener"
&gt;gaunacode - on Azure&lt;/a&gt; (EN)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://myshittycode.com/2019/10/30/terragrunt-plan-all-while-passing-outputs-between-modules/" target="_blank" rel="noopener"
&gt;myshittycode - run-all &amp;amp; outputs&lt;/a&gt; (EN)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://transcend.io/blog/why-we-use-terragrunt/" target="_blank" rel="noopener"
&gt;transcend - why we use terragrunt&lt;/a&gt; (EN)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://medium.com/geekculture/terragrunt-cheat-sheet-bedafbf9d61f" target="_blank" rel="noopener"
&gt;geekculture - terragrunt cheat sheet&lt;/a&gt; (EN)&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/gruntwork-io/terragrunt-infrastructure-live-example" target="_blank" rel="noopener"
&gt;Gruntwork.io - L&amp;rsquo;exemple officiel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/paddymorgan84/terragrunt-tutorial/tree/terragrunt" target="_blank" rel="noopener"
&gt;paddymorgan84 - terragrunt example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/pie-r/terragrunt-vs-terraspace" target="_blank" rel="noopener"
&gt;pie-r - terragrunt vs terraspace&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Premiers pas avec Terraform</title><link>https://blog.zwindler.fr/2018/01/16/premiers-pas-avec-terraform/</link><pubDate>Tue, 16 Jan 2018 12:45:42 +0000</pubDate><guid>https://blog.zwindler.fr/2018/01/16/premiers-pas-avec-terraform/</guid><description>&lt;img src="https://blog.zwindler.fr/2017/11/terraform.webp" alt="Featured image of post Premiers pas avec Terraform" /&gt;&lt;h2 id="terraform-"&gt;Terraform ?
&lt;/h2&gt;&lt;p&gt;Si vous avec passé un peu de temps sur Twitter, LinkedIn ou dans n’importe quel conf un peu orientée DevOps, vous ne pouvez pas avoir loupé &lt;a class="link" href="https://www.terraform.io/" target="_blank" rel="noopener"
&gt;Terraform&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Terraform est un outil d’Infrastructure as Code développé par &lt;a class="link" href="https://www.hashicorp.com/?_ga=2.237048704.181949482.1515658044-1057723858.1515658044" target="_blank" rel="noopener"
&gt;Hashicorp&lt;/a&gt;. Que le nom de cette entreprise vous dise quelque chose ou pas, vous avez très probablement entendu parlé de &lt;strong&gt;Vagrant&lt;/strong&gt; (eh oui c’est eux) et de &lt;strong&gt;Consul&lt;/strong&gt; (peut être même de Packer, Vault ou Nomad). Bref, l’entreprise propose un certain nombre d’outils pour faciliter l’exploitation et l’automatisation de ressources, particulièrement dans le cloud.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/01/hashicorp_tools.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="ok-mais-terraform-cest-quoi-"&gt;Ok, mais Terraform c’est quoi ?
&lt;/h2&gt;&lt;p&gt;Des fois le plus simple est de laisser les développeurs en parler d’eux même ;-)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What is Terraform?&lt;br&gt;
Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently. Terraform can manage existing and popular service providers as well as custom in-house solutions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Il y a deux phrases, et les deux sont importantes. En Français :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Terraform est un outil pour construire, changer, versionner l’infrastructure de manière sécurisée et efficace (efficiente?).&lt;/li&gt;
&lt;li&gt;Terraform peut gérer des fournisseurs de services (comprenez cloud plublic) mais aussi des solutions maison sur site (comprenez cloud privé).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="pourquoi-cest-important-"&gt;Pourquoi c’est important ?
&lt;/h3&gt;&lt;p&gt;Comme je le disais un peu plus haut, même s’ils disent le contraire, Terraform est quand même (historiquement) plutôt à destination des cloud providers.&lt;/p&gt;
&lt;p&gt;C’est là où Terraform a apporté la plus-value qui a fait sa renommée. Il permet une gestion plus agnostique des ressources et permet de passer facilement d’un cloud à l’autre.&lt;/p&gt;
&lt;h3 id="et-mon-cluster-vmwareopenstack-on-premise-alors-"&gt;Et mon cluster VMware/Openstack on-premise alors ?
&lt;/h3&gt;&lt;p&gt;Heureusement, l’outil s’enrichit de jour en jour et on dispose aujourd’hui de beaucoup de providers au delà des AWS, Azure et GCP et s’ouvre à d’autres usages comme MySQL, Kubernetes, Grafana, &amp;hellip; La liste complète est &lt;a class="link" href="https://www.terraform.io/docs/providers/index.html" target="_blank" rel="noopener"
&gt;disponible sur le site de Hashicorp&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Le tutoriel « officiel » est &lt;a class="link" href="https://www.terraform.io/intro/getting-started/install.html" target="_blank" rel="noopener"
&gt;disponible à l’adresse suivante&lt;/a&gt;, mais on reste un peu sur sa faim. Et surtout on ne voit pas comment faire du on-premise (ou que vous êtes allergiques à AWS).&lt;/p&gt;
&lt;h2 id="quelques-concepts"&gt;Quelques concepts
&lt;/h2&gt;&lt;p&gt;Je ne peux pas faire un article sans vous donner un minimum de concepts pour appréhender Terraform. La première chose à savoir est que Terraform utilise un langage de configuration appelé HCL qui lui est propre &lt;a class="link" href="https://www.terraform.io/docs/configuration/syntax.html" target="_blank" rel="noopener"
&gt;HashiCorp Configuration Language&lt;/a&gt;. C’est avec ce langage de configuration qu’on va décrire l’infrastructure à construire et &lt;em&gt;l’état&lt;/em&gt; dans lequel on souhaite avoir cette infrastructure. Moi qui suis habitué au YAML, dommage&amp;hellip;&lt;/p&gt;
&lt;p&gt;On va donc devoir décrire un &lt;em&gt;&lt;strong&gt;provider&lt;/strong&gt;&lt;/em&gt;, qui sera notre point d’entrée pour créer/interagir avec l’infrastructure (un login/mdp pour AWS, un serveur vCenter et les logins/mdp privilégiés, etc). Il est très probable qu’on ait plusieurs providers.&lt;/p&gt;
&lt;p&gt;Ensuite on pourra commencer à décrire nos &lt;em&gt;&lt;strong&gt;ressources&lt;/strong&gt;&lt;/em&gt; (tout objet nécessaire pour notre application, que ce soit une VM, un container, un réseau virtuel, une URL dans un loadbalancer, etc).&lt;/p&gt;
&lt;h2 id="assez-de-théorie-la-pratique-"&gt;Assez de théorie, la pratique !
&lt;/h2&gt;&lt;p&gt;Pour voir autre chose et mettre un peu plus les mains dans le cambouis, je vous propose donc un petit exemple avec un cluster VMware que vous auriez sous la main.&lt;/p&gt;
&lt;p&gt;La première chose à faire est sans surprise de récupérer terraform (&lt;a class="link" href="https://www.terraform.io/downloads.html" target="_blank" rel="noopener"
&gt;ici&lt;/a&gt;)&lt;/p&gt;
&lt;h3 id="installer-et-configurer-terraform"&gt;Installer et configurer Terraform
&lt;/h3&gt;&lt;p&gt;Si vous travaillez sur un Linux, un petit curl et on en parle plus.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl https://releases.hashicorp.com/terraform/0.10.6/terraform_0.10.6_linux_amd64.zip -o terraform_0.10.6_linux_amd64.zip
unzip terraform_0.10.6_linux_amd64.zip
mv terraform /usr/local/bin
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sous Windows, le plus simple est de télécharger le binaire, de le déposer dans un dossier de votre disque et d’alimenter le PATH (modifier les variables d’environnement du systèmes)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/01/terraform3-640x470.png"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;On peut maintenant tester que la commande répond correctement :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/10/terraform4.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="mon-premier-script-terraform"&gt;Mon premier script Terraform
&lt;/h2&gt;&lt;p&gt;Dans cet exemple, je me base sur le &lt;em&gt;provider&lt;/em&gt; vSphere, dont vous retrouvez &lt;a class="link" href="https://www.terraform.io/docs/providers/vsphere/index.html" target="_blank" rel="noopener"
&gt;la documentation ici&lt;/a&gt;. Ce simple script va se connecter à mon vcenter, créer un répertoire test à la racine du cluster, puis créer une VM dans ce répertoire.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cat example_vsphere.tf
# Configure the VMware vSphere Provider
provider &amp;#34;vsphere&amp;#34; {
user = &amp;#34;root&amp;#34;
password = &amp;#34;xxxx&amp;#34;
vsphere_server = &amp;#34;vcenter.zwindler.fr&amp;#34;
# if you have a self-signed cert
allow_unverified_ssl = true
}
# Create a folder
resource &amp;#34;vsphere_folder&amp;#34; &amp;#34;test&amp;#34; {
path = &amp;#34;test&amp;#34;
datacenter = &amp;#34;VMware zwindler&amp;#34;
}
# Create a virtual machine within the folder
resource &amp;#34;vsphere_virtual_machine&amp;#34; &amp;#34;test&amp;#34; {
name = &amp;#34;terraform-test&amp;#34;
datacenter = &amp;#34;VMware zwindler&amp;#34;
cluster = &amp;#34;Cluster_VMware&amp;#34;
folder = &amp;#34;${vsphere_folder.test.path}&amp;#34;
vcpu = 2
memory = 4096
network_interface {
label = &amp;#34;Virtual Network&amp;#34;
ipv4_address = &amp;#34;192.168.1.100&amp;#34;
ipv4_prefix_length = &amp;#34;24&amp;#34;
ipv4_gateway = &amp;#34;192.168.1.1&amp;#34;
}
disk {
template = &amp;#34;tmpl-rhel-7-3&amp;#34;
datastore = &amp;#34;VMFS01&amp;#34;
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On récapitule. Le premier objet de base dans terraform est le « provider », qui nous permet de prendre le contrôle du cluster. Les deux autres objets sont les « ressources » qu’on souhaite créer/modifier.&lt;/p&gt;
&lt;h2 id="its-alive"&gt;It’s alive!
&lt;/h2&gt;&lt;p&gt;La première commande à lancer est &lt;strong&gt;terraform init&lt;/strong&gt;, dans le dossier qui contient notre fichier de définition de l’infrastructure. Cela permet d’initialiser le contexte recherché ainsi que des variables. &lt;strong&gt;terraform plan&lt;/strong&gt; permet ensuite de faire un essai à blanc des modifications pour s’assurer que tout fonctionnera bien comme attendu (dry run).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;terraform init
terraform plan
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/10/terraform5.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/10/terraform6.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Et pour finir, on exécute notre plan avec &lt;strong&gt;terraform apply&lt;/strong&gt; (création du dossier et génération de la machine virtuelle) :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A l’issue de ces commandes, une VM devrait être créée dans votre cluster comme spécifiée. Vous remarquerez également la présence dans le même dossier que votre fichier &lt;strong&gt;example_vsphere.tf&lt;/strong&gt; un fichier &lt;strong&gt;terraform.state&lt;/strong&gt;. Ce fichier &lt;strong&gt;terraform.tfstate&lt;/strong&gt; (qui enregistre l’état dans lequel est l’infrastructure) est important et doit être disponible &lt;strong&gt;pour tous les postes/utilisateurs&lt;/strong&gt; qui utilisent terraform pour cette infrastructure (sinon ça ne marche pas).&lt;/p&gt;
&lt;p&gt;Hashicorp conseille d’utiliser un moyen de &lt;em&gt;rendre ce fichier disponible à distance&lt;/em&gt;, par exemple avec un serveur &lt;strong&gt;Consul&lt;/strong&gt; (de Hashicorp, bien sûr). On peut utiliser &lt;strong&gt;etcd&lt;/strong&gt; ou &lt;strong&gt;artifactory&lt;/strong&gt; ou même un simple partage mais il y aura des risques d’accès concurrents (il n’y aura pas de locking au niveau Terraform).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;With remote state, Terraform stores the state in a remote store. Terraform supports storing state in Terraform Enterprise, Consul, S3, and more.&lt;br&gt;
Remote state is a feature of backends. Configuring and using backends is easy and you can get started with remote state quickly. If you want to migrate back to using local state, backends make that easy as well.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Si vous voulez en savoir plus, &lt;a class="link" href="https://www.terraform.io/docs/state/remote.html" target="_blank" rel="noopener"
&gt;allez lire cette page&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;J’ai essayé de faire bref pour vous donner un aperçu très rapide de ce qu’est Terraform et de ce qu’on peut faire avec mais il reste forcément encore beaucoup de choses à dire. Déjà, j’ai résumé à l’extrême la partie théorie et n’ai pratiquement expliqué aucun concept. Ensuite, je n’ai pas beaucoup exploré les limites de Terraform, notamment dans l’utilisation à plusieurs et les manques par rapport à d’autres outils.&lt;/p&gt;
&lt;p&gt;Pour ma part j’ai trouvé l’outil intéressant mais je ne peux pas m&amp;rsquo;empêcher de faire le parallèle avec &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=ansible" &gt;Ansible&lt;/a&gt;, que je maitrise beaucoup mieux.&lt;/p&gt;
&lt;p&gt;Que peut faire Terraform que ne peux pas faire &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=ansible" &gt;Ansible&lt;/a&gt; ? Peut être une meilleure gestion de fournisseurs de services autres que AWS Azure et GCP (Dyn, Datadog ou Mailgun).&lt;/p&gt;
&lt;p&gt;A l’inverse, Ansible permet de faire beaucoup &lt;em&gt;plus&lt;/em&gt; de choses que Terraform, car c’est un outil bien plus fourni (à date) et surtout plus généraliste, qui sert à la fois à déployer ET à configurer.&lt;/p&gt;
&lt;p&gt;Pour autant, je ne m’interdis pas de l’utiliser dans un prochain contexte professionnel qui devrait justement me demander plus d’interaction avec les clouds public.&lt;/p&gt;
&lt;p&gt;Have fun !&lt;/p&gt;
&lt;h2 id="bonuslife-in-graphic-its-fantastic"&gt;[Bonus]Life in graphic, it’s fantastic
&lt;/h2&gt;&lt;p&gt;Une fonctionnalité sympathique de Terraform est la possibilité offerte de générer un « graphe » de vos ressources et de leurs dépendances les unes aux autres. Certes, dans des cas concrets et complexes c’est peut être un peu gadget, mais l’idée est bonne.&lt;/p&gt;
&lt;p&gt;En réalité, c’est même pour cette raison que je me suis intéressé à Terraform. A la base, on m’a demandé de trouver un outil permettant de visualiser une infrastructure complexe. Or celle ci étant changeante car en pleine conception, je n’avais pas envie de repasser 50 fois sur un diagramme de type Visio. J’ai donc cherché une solution pour le faire de manière automatique.&lt;/p&gt;
&lt;p&gt;Voilà le genre de résultats que vous pouvez attendre de Terraform :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2017/10/terraform-7-2-graph.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Notre example_vsphere.tf donne ceci en graphe&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pour se faire, installez simplement la bibliothèque &lt;strong&gt;graphviz&lt;/strong&gt; et utilisez la commande &lt;strong&gt;terraform graph&lt;/strong&gt;.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;yum install graphviz
terraform graph | dot -Tpng &amp;gt; terraform-graph.png
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A noter : je n’ai pas trouvé la solution satisfaisante et c’est pour ça que j’ai commencé à développer ma propre bibliothèque Python pour grapher des infrastructures. Quand ça ressemblera à quelque chose je ferai un article dessus (#Teasing).&lt;/p&gt;</description></item></channel></rss>