<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>script on Zwindler's Reflection</title><link>https://blog.zwindler.fr/categories/script/</link><description>Recent content in script 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/categories/script/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>Récupérer les informations sur la distribution avec les facts Ansible</title><link>https://blog.zwindler.fr/2018/11/21/recuperer-les-informations-sur-la-distribution-avec-les-facts-ansible/</link><pubDate>Wed, 21 Nov 2018 12:45:40 +0000</pubDate><guid>https://blog.zwindler.fr/2018/11/21/recuperer-les-informations-sur-la-distribution-avec-les-facts-ansible/</guid><description>&lt;img src="https://blog.zwindler.fr/2018/10/ansible_logo.webp" alt="Featured image of post Récupérer les informations sur la distribution avec les facts Ansible" /&gt;&lt;h2 id="les-facts-dansible"&gt;Les facts d’Ansible
&lt;/h2&gt;&lt;p&gt;Si vous suivez le blog, vous savez que &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=ansible" &gt;j’utilise énormément Ansible&lt;/a&gt;. J’ai même été faire un &lt;a class="link" href="https://blog.zwindler.fr/2018/11/09/bdx-i-o-2018-ami-developpeur-deviens-un-ops-sans-effort-avec-ansible" &gt;talk sur le sujet à BDX I/O 2018, à l’ENSEIRB&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Aujourd’hui, plutôt que de vous donner un playbook tout fait pour installer sans effort une des multiples applications dont j’ai automatisé le déploiement avec Ansible, je vous propose d’explorer une des features les plus importantes et utiles d’Ansible, les &lt;strong&gt;facts&lt;/strong&gt;, par le biais d’un petit exemple.&lt;/p&gt;
&lt;h2 id="cest-quoi-les-facts-dans-ansible"&gt;C’est quoi les facts dans Ansible
&lt;/h2&gt;&lt;p&gt;Si vous avez déjà lancé un playbook, vous avez sûrement remarqué lors de son exécution, que la première tâche qui est réalisée n’est pas une tâche que vous avez demandée explicitement.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ansible-playbook -i inventory/prod/blop -u blop --private-key=blop.key configure-blop.yml
[...]]
TASK [Gathering Facts] *********************************************************
ok: [blop-vm1]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cette tâche &lt;strong&gt;[Gathering Facts]&lt;/strong&gt;, qui ne fait à première vue rien, correspond en fait à la connexion à la ou les machines sur lesquelles seront exécutées les playbooks. Si la connexion échoue, le playbook échouera sur cette cible, et continuera éventuellement sur les autres (s’il en reste). Si l’hôte répond, alors Ansible en profite pour récupérer moult informations en rapport avec cette machines et les stockent dans une variable &lt;strong&gt;ansible_facts&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="a-quoi-ça-ressemble-"&gt;A quoi ça ressemble ?
&lt;/h2&gt;&lt;p&gt;Comme je ne disais, à première vue, cette commande de fait rien. Si on ne sait pas qu’elle stocke des informations dans une variables, on ne peut rien en faire.&lt;/p&gt;
&lt;p&gt;Un bon moyen d’avoir un premier aperçu de ce qu’on peut en faire est de les afficher. On peut faire ça avec &lt;a class="link" href="http://docs.ansible.com/ansible/latest/collections/ansible/builtin/setup_module.html" target="_blank" rel="noopener"
&gt;le module « setup »&lt;/a&gt;, qui est en réalité le même module qui est appelé lors de l’étape &lt;strong&gt;[Gathering facts]&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Le retour se fera au format JSON, ce qui est certes peu digeste, mais facilitera grandement les manipulations de type « filtre » (via le flag filter intégré ou via l’utilitaire &lt;strong&gt;jq&lt;/strong&gt; par exemple).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ansible blop-vm1 i inventory/prod/blop -m setup
blop-vm1 | SUCCESS =&amp;gt; {
&amp;#34;ansible_facts&amp;#34;: {
&amp;#34;ansible_all_ipv4_addresses&amp;#34;: [
&amp;#34;10.1.1.10&amp;#34;
],
&amp;#34;ansible_apparmor&amp;#34;: {
&amp;#34;status&amp;#34;: &amp;#34;enabled&amp;#34;
},
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Je ne vous copie-colle pas tout, rien que pour cette machine, j’ai 719 lignes&amp;hellip; La quantité d’informations disponible est impressionnante, et on peut même en venir à se demander à quoi ça va bien pouvoir nous servir.&lt;/p&gt;
&lt;h2 id="ok-on-en-fait-quoi-"&gt;Ok, on en fait quoi ?
&lt;/h2&gt;&lt;p&gt;Du coup je profite de cet article pour faire un tuto tout simple et qui peut être utile dans de nombreux cas, réaliser des opérations différentes en fonction de la distribution de la machine concernée.&lt;/p&gt;
&lt;p&gt;L’information qui va nous intéresser ici concerne donc les remontées en tant que « nom » ou « version » d’une distribution. Je vais vous économiser la lecture de nos 700+ lignes, et vous indiquer que vous pouvez trouver ces informations en filtrant sur les mots clés « ansible_distribution&amp;hellip; » et « ansible_os&amp;hellip; »&lt;/p&gt;
&lt;p&gt;Voilà ce qu’on pourrait obtenir sur une machine CentOS :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ansible blop-vm1 -m setup -a &amp;#39;filter=ansible_distribution*&amp;#39;
blop-vm1 | SUCCESS =&amp;gt; {
&amp;#34;ansible_facts&amp;#34;: {
&amp;#34;ansible_distribution&amp;#34;: &amp;#34;CentOS&amp;#34;,
&amp;#34;ansible_distribution_major_version&amp;#34;: &amp;#34;7&amp;#34;,
&amp;#34;ansible_distribution_release&amp;#34;: &amp;#34;Core&amp;#34;,
&amp;#34;ansible_distribution_version&amp;#34;: &amp;#34;7.2.1511&amp;#34;
},
&amp;#34;changed&amp;#34;: false
}
ansible blop-vm1 -m setup -a &amp;#39;filter=ansible_os_family&amp;#39;
blop-vm1 | SUCCESS =&amp;gt; {
&amp;#34;ansible_facts&amp;#34;: {
&amp;#34;ansible_os_family&amp;#34;: &amp;#34;RedHat&amp;#34;
},
&amp;#34;changed&amp;#34;: false
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et sur une machine Ubuntu :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ansible blop-vm2 -m setup -a &amp;#39;filter=ansible_distribution*&amp;#39;
ansible blop-vm2 | SUCCESS =&amp;gt; {
&amp;#34;ansible_facts&amp;#34;: {
&amp;#34;ansible_distribution&amp;#34;: &amp;#34;Ubuntu&amp;#34;,
&amp;#34;ansible_distribution_file_parsed&amp;#34;: true,
&amp;#34;ansible_distribution_file_path&amp;#34;: &amp;#34;/etc/os-release&amp;#34;,
&amp;#34;ansible_distribution_file_variety&amp;#34;: &amp;#34;Debian&amp;#34;,
&amp;#34;ansible_distribution_major_version&amp;#34;: &amp;#34;16&amp;#34;,
&amp;#34;ansible_distribution_release&amp;#34;: &amp;#34;xenial&amp;#34;,
&amp;#34;ansible_distribution_version&amp;#34;: &amp;#34;16.04&amp;#34;
},
&amp;#34;changed&amp;#34;: false
}
ansible blop-vm2 -m setup -a &amp;#39;filter=ansible_os*&amp;#39;
blop-vm2 | SUCCESS =&amp;gt; {
&amp;#34;ansible_facts&amp;#34;: {
&amp;#34;ansible_os_family&amp;#34;: &amp;#34;Debian&amp;#34;
},
&amp;#34;changed&amp;#34;: false
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="utiliser-les-facts-dans-un-playbook"&gt;Utiliser les facts dans un playbook
&lt;/h2&gt;&lt;p&gt;Pour continuer dans l’exemple, on va faire une chose qu’il ne faut jamais faire : désactiver le firewall et SELinux.&lt;/p&gt;
&lt;p&gt;Imaginons que vous souhaitiez quand même le faire. Si vous lancez ce playbook sur tout votre parc et qu’il n’est pas homogène, vous allez tomber sur des groupes de machines Ubuntu, CentOS 5, 6, 7&amp;hellip;&lt;/p&gt;
&lt;p&gt;Un moyen de gérer les cas particuliers pourrait être de les classer tous vos hosts dans des groupes, et de créer un playbook pour chaque OS/version, restreint à un groupe de machines uniquement.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;---
- hosts: rhelcentos6only
tasks:
[…]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ce n’est d’ailleurs pas une mauvaise idée, surtout pour gérer les distrib aussi différentes que RHEL et Ubuntu par exemple.&lt;/p&gt;
&lt;p&gt;En revanche, dans le cas de RHEL, on a des différences qui apparaissent à partir de la RHEL 7, notamment la gestion du Firewall qui passe de IPtables à firewalld.&lt;/p&gt;
&lt;p&gt;On va donc faire appel à la clause &lt;strong&gt;when:&lt;/strong&gt; de ansible, qui conditionne l’exécution d’une tâche (ou d’un rôle ou d’un block) à une validation. Et ça donnerait quelque chose comme ça :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;---
- hosts: rhelcentos6only
tasks:
- name: &amp;#34;shutdown and disable IPtables for RHEL &amp;lt;= 6&amp;#34;
service:
name=iptables
state=stopped
enabled=no
when: (ansible_distribution == &amp;#34;CentOS&amp;#34; or ansible_distribution == &amp;#34;RedHat&amp;#34;) and
(ansible_distribution_major_version &amp;lt;= &amp;#34;6&amp;#34;)
- name: &amp;#34;shutdown and disable firewalld for RHEL &amp;gt;= 7&amp;#34;
service:
name=firewalld
state=stopped
enabled=no
when: (ansible_distribution == &amp;#34;CentOS&amp;#34; or ansible_distribution == &amp;#34;RedHat&amp;#34;) and
(ansible_distribution_major_version &amp;gt;= &amp;#34;7&amp;#34;)
- name: &amp;#34;disable selinux&amp;#34;
selinux:
state=disabled
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Dans cet exemple, lors de l’exécution du playbook, on aura donc, pour chaque VM CentOS ou RHEL, une tâche qui sera exécutée, et l’autre qui sera marquée « skipping » (en bleu clair) et le playbook marchera pour toutes les RHEL, quelque soit leur version.&lt;/p&gt;
&lt;h2 id="aller-plus-loin"&gt;Aller plus loin
&lt;/h2&gt;&lt;p&gt;Il existe une page spécifique sur la documentation d’Ansible pour parler des conditions dans les playbooks, accessible à l’adresse suivante : &lt;a class="link" href="https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_conditionals.html" target="_blank" rel="noopener"
&gt;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_conditionals.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Vous pouvez aussi utiliser les facts dans les options des tasks, et dans les templates, en encadrant le nom de la variable souhaitée avec des « doubles curly braces » : &lt;code&gt;{{ xxx }}&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;- command: &amp;#34;echo {{ ma_super_variable }}&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="sources"&gt;Sources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="http://docs.ansible.com/ansible/latest/collections/ansible/builtin/setup_module.html" target="_blank" rel="noopener"
&gt;docs.ansible.com/ansible/latest/collections/ansible/builtin/setup_module.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_conditionals.html" target="_blank" rel="noopener"
&gt;docs.ansible.com/ansible/latest/playbook_guide/playbooks_conditionals.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Sortie d’Ansible 2.7 et ma première contribution</title><link>https://blog.zwindler.fr/2018/10/10/sortie-dansible-2-7-et-ma-premiere-contribution/</link><pubDate>Wed, 10 Oct 2018 12:15:12 +0000</pubDate><guid>https://blog.zwindler.fr/2018/10/10/sortie-dansible-2-7-et-ma-premiere-contribution/</guid><description>&lt;img src="https://blog.zwindler.fr/2018/10/ansible_logo.webp" alt="Featured image of post Sortie d’Ansible 2.7 et ma première contribution" /&gt;&lt;h2 id="sortie-dansible-27"&gt;Sortie d’Ansible 2.7
&lt;/h2&gt;&lt;p&gt;Hier soir, la dernière version d’Ansible (2.7) est sortie. Cette release s’est concentrée sur une amélioration de la performance et de la stabilité, même si de très nombreux modules ont fait leur apparition, comme à chaque nouvelle version.&lt;/p&gt;
&lt;h3 id="python"&gt;Python
&lt;/h3&gt;&lt;p&gt;Le support de Python 2.6 est abandonné, au profit de Python 2.7. Cela signifie que l’hôte qui exécutera le playbook devra disposer de Python 2.7 au minimum (même si Python 2.6 est toujours supporté sur la machine cible).&lt;/p&gt;
&lt;h3 id="écritures-concurrentes"&gt;Écritures concurrentes
&lt;/h3&gt;&lt;p&gt;Un problème auquel j’ai déjà eu affaire est la gestion des écritures concurrentes sur un même fichier (par exemple si plusieurs hôtes écrivent sur un même fichier distant ou alors un delegate_to). A priori il existe maintenant un « lock » pour éviter d’écraser les modifications. Il faudra que je teste pour voir si ça marche bien.&lt;/p&gt;
&lt;h3 id="performances-accrues-généralisation-du-ssh-pipelining-"&gt;Performances accrues, généralisation du SSH pipelining ?
&lt;/h3&gt;&lt;p&gt;La plus grosse modification, qui va nécessiter des tests approfondis, est la modification de la manière dont sont déclenchées les actions/modules sur les serveurs distants. Précédemment, les tasks nécessitaient 2 commandes SSH au lieu d’une maintenant. Effectivement, le temps d’exécution de playbooks contenant des actions simple mais très nombreuses pouvait être très long.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ansible-2.7 changes the Ansiballz strategy for running modules remotely so that invoking a module only needs to invoke python once per module on the remote machine instead of twice.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Un gain de performance dans ce genre de cas où on passe plus de temps à lancer des commandes que les exécuter est forcément une bonne nouvelle. Je me demande si ce n’est pas simplement une activation « par défaut » de la variable d’environnement ANSIBLE_SSH_PIPELINING=1 (que j’utilise déjà dans ce genre de cas).&lt;/p&gt;
&lt;p&gt;A priori non &lt;a class="link" href="https://github.com/ansible/ansible/issues/36275" target="_blank" rel="noopener"
&gt;si j’en crois cette issue&lt;/a&gt;, mais pour l’instant je n’ai pas remarqué de différence significative sur mes playbooks les plus gourmands en temps d’exécution.&lt;/p&gt;
&lt;h3 id="module-reboot"&gt;Module reboot
&lt;/h3&gt;&lt;p&gt;A noter, la plupart des gens remontent l’arrivée d’un module « reboot » (et son équivalent « win_reboot ») qui redémarre une machine et ré-initie une connexion une fois que la machine a refait surface. Personnellement je n’utilise pas ce genre de fonctionnalité mais j’imagine que c’est une feature « nice to have » plutôt que d’utiliser le module « pause » ou la fonctionnalité « retry » en attendant que l’hôte refasse surface.&lt;/p&gt;
&lt;h2 id="les-nouveaux-modules"&gt;Les nouveaux modules
&lt;/h2&gt;&lt;p&gt;Je ne vais pas en faire la liste complète (disponible &lt;a class="link" href="https://github.com/ansible/ansible/tree/stable-2.7/changelogs" target="_blank" rel="noopener"
&gt;dans le changelog&lt;/a&gt;), mais cette version a visiblement été l’occasion pour les équipes de plusieurs cloud providers de se mettre en avant.&lt;/p&gt;
&lt;p&gt;On peut noter les équipes de Google Cloud comme grands vainqueurs avec 39 nouveaux modules. Ils sont suivi par Azure (+21, avec l’apport des bases de données et des webapps), Vultr (13), et 8 pour Scaleway.&lt;/p&gt;
&lt;p&gt;Tout ça m’intéresse beaucoup car, notamment pour Scaleway, de nombreux objets étaient encore indisponibles et il a fallut que j’écrive des scripts à la main pour curler l’API, ne serait ce que pour &lt;a class="link" href="https://docs.ansible.com/ansible/2.7/modules/scaleway_image_facts_module.html#scaleway-image-facts-module" target="_blank" rel="noopener"
&gt;récupérer les IDs des templates de VMs&lt;/a&gt; que je voulais utiliser (impossible à lister autrement).&lt;/p&gt;
&lt;p&gt;Avant :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl -X GET -H &amp;#34;X-Auth-Token: $SCW_API_KEY&amp;#34; -H &amp;#39;Content-Type: application/json&amp;#39; https://cp-par1.scaleway.com/images | jq -r &amp;#39;.images[] | select(.name|contains(&amp;#34;CentOS&amp;#34;)) | .id,.name,.arch,.modification_date&amp;#39;
37832f54-c18f-4338-a552-113e4302a236
CentOS 7.4
x86_64
2018-09-06T10:40:08.145552+00:00
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Maintenant, je peux sois l’exécuter à la main directement depuis Ansible, soit requêter le serveur Scaleway pour avoir une liste des images disponible directement dans mes playbooks :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ansible localhost -m scaleway_image_facts -a region=par1
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match &amp;#39;all&amp;#39;
localhost | SUCCESS =&amp;gt; {
&amp;#34;ansible_facts&amp;#34;: {
&amp;#34;scaleway_image_facts&amp;#34;: [
{
&amp;#34;arch&amp;#34;: &amp;#34;x86_64&amp;#34;,
&amp;#34;creation_date&amp;#34;: &amp;#34;2018-09-14T10:01:24.268850+00:00&amp;#34;,
&amp;#34;default_bootscript&amp;#34;: {
&amp;#34;architecture&amp;#34;: &amp;#34;x86_64&amp;#34;,
&amp;#34;bootcmdargs&amp;#34;: &amp;#34;LINUX_COMMON scaleway boot=local nbd.max_part=16&amp;#34;,
&amp;#34;default&amp;#34;: false,
&amp;#34;dtb&amp;#34;: &amp;#34;&amp;#34;,
&amp;#34;id&amp;#34;: &amp;#34;15fbd2f7-a0f9-412b-8502-6a44da8d98b8&amp;#34;,
[...]
- name: Gather Scaleway images facts 
scaleway_image_facts: 
region: par1
register: images_facts
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et tant qu’on est dans le genre module qui vient remplacer des trucs que je faisais à la mimine, on peut aussi citer &lt;a class="link" href="https://docs.ansible.com/ansible/2.7/modules/docker_swarm_module.html#docker-swarm-module" target="_blank" rel="noopener"
&gt;docker_swarm&lt;/a&gt; + &lt;a class="link" href="https://docs.ansible.com/ansible/2.7/modules/docker_swarm_service_module.html#docker-swarm-service-module" target="_blank" rel="noopener"
&gt;docker_swarm_service&lt;/a&gt; pour gérer un cluster docker Swarm (comme son nom l’indique), ou &lt;a class="link" href="https://docs.ansible.com/ansible/2.7/modules/k8s_facts_module.html#k8s-facts-module" target="_blank" rel="noopener"
&gt;k8s_facts&lt;/a&gt; pour récupérer des objets dans Kubernetes.&lt;/p&gt;
&lt;h2 id="et-ma-première-contribution-"&gt;Et ma première contribution !
&lt;/h2&gt;&lt;p&gt;Même si j’ai déjà contribué sur plusieurs projets open source (traductions du site de Shinken, petites contributions à plusieurs plugins Nagios et à XWiki, ouverture d’issues dans de nombreux projects open source), j’ai également résolu ma première issue sur un gros projet grâce à Ansible et l’équipe d’Azure.&lt;/p&gt;
&lt;p&gt;Il y a peu, Microsoft a mis à disposition sur Azure de machine virtuelle disposant gratuitement d’interface physique dédiées (non virtualisées donc) à 30 Gbps et avec une latence moindre (plus d’info sur &lt;a class="link" href="https://docs.microsoft.com/fr-fr/azure/virtual-network/create-vm-accelerated-networking-cli" target="_blank" rel="noopener"
&gt;la documentation officielle&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Comme il s’agissait d’un simple flag à ajouter dans l’API et que &lt;a class="link" href="https://github.com/ansible/ansible/issues/41218" target="_blank" rel="noopener"
&gt;l’issue avait été taguée en « easy fix » par les maintainer&lt;/a&gt;, j’ai sauté sur l’occasion et j’ai pris l’issue à mon compte.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/10/accelerated_network_ansible1.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Au final, sur les 70 lignes de mon commit, il n’y a que 10 lignes de codes (le reste étant des tests et de la documentation, obligatoires pour toute soumission), mais je suis quand même content car ça marche bien ;)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/10/accelerated_network_ansible2.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Champomy !!&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>Minikube sur Hyper-V part 2 : troubleshooting de l’installation</title><link>https://blog.zwindler.fr/2018/10/02/minikube-sur-hyper-v-part-2-troubleshooting-de-linstallation/</link><pubDate>Tue, 02 Oct 2018 11:45:54 +0000</pubDate><guid>https://blog.zwindler.fr/2018/10/02/minikube-sur-hyper-v-part-2-troubleshooting-de-linstallation/</guid><description>&lt;img src="https://blog.zwindler.fr/2018/09/minikube.webp" alt="Featured image of post Minikube sur Hyper-V part 2 : troubleshooting de l’installation" /&gt;&lt;h2 id="minikube-le-retour"&gt;Minikube, le retour
&lt;/h2&gt;&lt;p&gt;Il y a deux semaines, j’ai fais un article sur l’installation de Minikube sur un poste Windows 10. Petite subtilité, l’article en question explique comment installer Minikube sur Hyper-V, nativement présent avec Windows 10, plutôt qu’avec Virtual Box, le choix par défaut mais qui nécessite un téléchargement et une installation complémentaire. Si vous l’avez loupé, &lt;a class="link" href="https://blog.zwindler.fr/2018/09/12/installer-minikube-sur-windows-10-et-hyper-v-part-1/" &gt;c’est par ici&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="option-2--expectations-meet-life"&gt;Option 2 : Expectations meet life
&lt;/h2&gt;&lt;p&gt;On s’était arrêté dans l’article précédent à un monde merveilleux ou tout marche du premier coup.&lt;br&gt;
Mais, vous vous en doutez, dans la vie (et particulièrement dans l’IT), rien ne se passe jamais comme prévu.&lt;/p&gt;
&lt;p&gt;Voilà donc un petit florilège des problèmes que vous pourriez (ou avez) rencontrer (et leur résolution !)&lt;/p&gt;
&lt;h3 id="vboxmanage-not-found"&gt;VBoxManage not found
&lt;/h3&gt;&lt;p&gt;Si vous en venez à vous demander comment l’installer sur Hyper-V, c’est probablement que vous avez commencé par lancer la commande « minikube start » sans arguments&amp;hellip; L’installeur a donc bêtement assumé que vous utilisiez Virtual Box (pourquoi ?) et vous vous retrouvez avec l’erreur suivante :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Error getting state for host: VBoxManage not found. Make sure VirtualBox is installed and VBoxManage is in the path.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pourtant, vous avez beau forcer le start avec le flag suivant, rien y fait, ce n’est pas pris en compte.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;--vm-driver hyperv
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pour trouver comment résoudre ce problème, vous pouvez jeter à œil à cette &lt;a class="link" href="https://github.com/kubernetes/minikube/issues/2901" target="_blank" rel="noopener"
&gt;issue sur github&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En réalité, une fois le premier « start » lancé, les fichiers de configuration sont générés dans &lt;strong&gt;C:\users[votrelogin].minikube&lt;/strong&gt; (et en particulier dans profiles\minikube\config.json).&lt;/p&gt;
&lt;p&gt;Impossible d’expliquer à l’installeur que vous avez changé d’avis (oui oui&amp;hellip;), il faut donc de supprimer tout le dossier &lt;em&gt;.minikube&lt;/em&gt; et recommencer avec les bons paramètres la prochaine fois (enfin c’est le plus simple, on va dire).&lt;/p&gt;
&lt;h3 id="minikube-v0xxxiso-le-chemin-daccès-spécifié-est-introuvable"&gt;minikube-v0.xx.x.iso: Le chemin d’accès spécifié est introuvable&amp;hellip;
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;minikube-v0.28.1.iso: Le chemin d’accès spécifié est introuvable...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, ça ne marche toujours pas. On passe en mode verbose pour avoir l’erreur exacte :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PS C:\windows\system32&amp;gt; minikube start --vm-driver hyperv --hyperv-virtual-switch &amp;#34;Primary Virtual Switch&amp;#34; -v=7
Starting local Kubernetes v1.10.0 cluster...
Starting VM...
[...]
[stderr =====&amp;gt;] :
Downloading D:\Users\zwindler\.minikub\cache\boot2docker.iso from file://D:/Users/zwindler/.minikub/cache/iso/minikube-v0.28.1.iso...
E0906 15:10:27.568262 14484 start.go:174] Error starting host: Error creating host: Error executing step: Creating VM.: open /Users/zwindler/.minikub/cache/iso/minikub-v0.28.1.iso: Le chemin d’accès spécifié est introuvable..
Retrying.
E0906 15:10:27.873612 14484 start.go:180] Error starting host: Error creating host: Error executing step: Creating VM.
: open /Users/zwindler/.minikube/cache/iso/minikube-v0.28.1.iso: Le chemin d’accès spécifié est introuvable.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pourtant le fichier existe. Et c’est reparti pour un tour sur Github pour avoir plus de détails !&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/minikube/issues/1310" target="_blank" rel="noopener"
&gt;github.com/kubernetes/minikube/issues/1310&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/minikube/issues/2564" target="_blank" rel="noopener"
&gt;github.com/kubernetes/minikube/issues/2564&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ici, c’est donc tout simplement le script Minikube qui ne sait pas que vous avez un disque **D:**&amp;hellip; Alors qu’il vient de le déposer lui même dans *&lt;em&gt;D:*&lt;/em&gt; une ligne plus haut !!! La solution donc :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;you can specify the path for the .minikub directory by setting the MINIKUBE_HOME env variable&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Bon en vrai la bonne syntaxe sous Windows (dans Powershell en tout cas) c’est :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$MINIKUBE_HOME=&amp;#34;D:\Users\[votrelogin]\&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On oublie pas de nettoyer la tentative précédente avec un :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;minikube delete
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="flmnh--error-deleting-machine-profile-config"&gt;FLMNH : « Error deleting machine profile config »
&lt;/h3&gt;&lt;p&gt;Si jamais en essayant de nettoyer votre environnement (pour recommencez, vous essayez un « minikube delete » et que vous vous prenez une erreur).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;minikube delete
Deleting local Kubernetes cluster...
Machine deleted.
Error deleting machine profile config
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Rebelotte, on supprime le dossier &lt;strong&gt;D:\Users[votrelogin].minikube&lt;/strong&gt; à la main.&lt;/p&gt;
&lt;h3 id="error-starting-host-error-starting-stopped-host-exit-status-1"&gt;Error starting host: Error starting stopped host: exit status 1
&lt;/h3&gt;&lt;p&gt;Tout à l’air de fonctionner. Vous croyez que vous vous en êtes sortis ? Pauvres fous ;)&lt;/p&gt;
&lt;p&gt;Au moment où tout se termine, le script vérifie que le cluster est opérationnel. Et après avoir boucler un moment : PAF !&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Error starting host: Error starting stopped host: exit status 1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;L’erreur n’est pas très explicite. En gros, vous êtes dans le cas où tout est bien installé, mais le curl pour vérifier que le cluster est UP échoue, pour un souci réseau. La plupart du temps, il s’agit de l’erreur suivante :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/minikube/issues/1967" target="_blank" rel="noopener"
&gt;github.com/kubernetes/minikube/issues/1967&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/minikube/issues/1945" target="_blank" rel="noopener"
&gt;github.com/kubernetes/minikube/issues/1945&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;After some troubleshooting and head banging, it became apparent that the external network adapter had an ethernet adapter selected that was not connected to a network. (ethernet selected, instead of the wireless adapter). Of course an IP wont be allocated on an external network if none is connected.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Vérifiez donc dans les paramètres d’Hyper-V que vous ne vous êtes pas trompé d’adaptateur réseau lors de la configuration du réseau virtuel (cf &lt;a class="link" href="https://blog.zwindler.fr/2018/09/12/installer-minikube-sur-windows-10-et-hyper-v-part-1/" &gt;l’article précédent&lt;/a&gt;) !&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/09/minikube04.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h3 id="unable-to-authenticate-attempted-methods-publickey-none"&gt;unable to authenticate, attempted methods [publickey none]
&lt;/h3&gt;&lt;p&gt;Ok, cette fois ci tout est censé être bon. Pourtant, à la fin, ça plante encore (désespoir).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Error dialing TCP: ssh: handshake failed: ssh: unable to authenticate, attempted methods [publickey none], no supported methods remain
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Là je ne suis pas sûr à 100% ni de la cause, ni du fix, mais a priori, c’était un problème lié au client/serveur OpenSSH fourni par Microsoft, qui serait pourri. L’installation d’une autre version via Chocolatey semble avoir résolu le problème.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/minikube/issues/2329" target="_blank" rel="noopener"
&gt;github.com/kubernetes/minikube/issues/2329&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PS D:\&amp;gt; minikube ip
172.16.25.217
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;choco install openssh
Chocolatey v0.10.11
Installing the following packages:
openssh
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Installer Minikube sur Windows 10 et Hyper-V – part 1</title><link>https://blog.zwindler.fr/2018/09/12/installer-minikube-sur-windows-10-et-hyper-v-part-1/</link><pubDate>Wed, 12 Sep 2018 11:45:26 +0000</pubDate><guid>https://blog.zwindler.fr/2018/09/12/installer-minikube-sur-windows-10-et-hyper-v-part-1/</guid><description>&lt;img src="https://blog.zwindler.fr/2018/09/minikube.webp" alt="Featured image of post Installer Minikube sur Windows 10 et Hyper-V – part 1" /&gt;&lt;h2 id="minikube-sur-hyper-v-cest-facile-"&gt;Minikube sur Hyper-V, c’est facile ?
&lt;/h2&gt;&lt;p&gt;Un bon moyen de commencer à bidouiller avec &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=kubernetes" &gt;&lt;strong&gt;Kubernetes&lt;/strong&gt;&lt;/a&gt;, c’est d’utiliser &lt;strong&gt;Minikube&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Pour ceux qui ne connaissent pas, il s’agit d’un script qui va récupérer une machine virtuelle préconfigurée avec tous les composants nécessaires à Kubernetes, et l’installer sur votre machine. Ce script est disponible sur Windows, Mac et Linux, et vous trouverez de nombreux tutos pour l’installer via le logiciel de virtualisation &lt;strong&gt;Virtual Box&lt;/strong&gt; (à installer préalablement, en prérequis donc).&lt;/p&gt;
&lt;p&gt;Mais admettons que vous ayez commencés à bidouiller avec Docker avec « Docker for Windows ». Quoi de plus normal de passer sur K8s (le petit nom de Kubernetes, plus court) après avoir joué avec Docker.&lt;/p&gt;
&lt;p&gt;Et paf ! vous n’arrivez pas à installer, à cause d’un obscur message qui vous parle de Virtual Box (alors que vous ne l’utilisez pas). On coince dès les prérequis, ça commence mal.&lt;/p&gt;
&lt;p&gt;Et oui&amp;hellip; « Docker for Windows » active Hyper-V&amp;hellip; et si Hyper-V est activé, impossible d’installer Virtual Box !&lt;/p&gt;
&lt;p&gt;Si la plupart des tutoriels mettent en avant Virtual Box justement (car c’est l’option par défaut), vous n’avez peut être pas envie de désinstaller Docker for Windows pour autant !&lt;/p&gt;
&lt;p&gt;Ou peut être que vous n’avez pas envie d’installer Virtual Box alors que votre Windows 10 vous fourni déjà « out of the box » un logiciel de virtualisation parfaitement valide (attention, je dis ça uniquement pour Windows 10, sur un PC &lt;strong&gt;client&lt;/strong&gt;&amp;hellip; Pour un serveur, c’est juste une grosse blague cette plateforme de virtu&amp;hellip;).&lt;/p&gt;
&lt;h2 id="on-va-quand-même-sen-sortir"&gt;On va quand même s’en sortir
&lt;/h2&gt;&lt;p&gt;En gros, on est censé dérouler simplement les prérequis : avoir VT-x/AMD-v d’activés dans le BIOS. Là je ne vais pas vous faire l’explication car ça dépend grandement de votre machine.&lt;/p&gt;
&lt;p&gt;Ensuite, on ajoute la fonctionnalité Hyper-V sur votre Windows 10. Pour se faire, on ouvre le menu des « fonctionnalités Windows ».&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/09/minikube01.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/09/minikube02.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Si ce n’est pas déjà fait cocher « Hyper-V », validez, et on vous demandera très probablement de redémarrer. Attention, à partir de là vous ne pourrez plus utiliser Virtual Box (c’est tout le but de cet article, mais bon) ou VMware player ou autre.&lt;/p&gt;
&lt;p&gt;Et enfin, pour éviter des conflits avec Docker pour Windows, on va créer un réseau virtuel dédié dans notre console Hyper-V. Lancer le gestionnaire Hyper-V :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/09/minikube03.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Sur le menu tout à droite, on créé un Commutateur virtuel dédié. Pour réaliser cette opération, on clique sur &lt;strong&gt;Gestionnaire de commutateur virtuel&lt;/strong&gt;, puis dans la fenêtre qui s’ouvre, en haut à gauche dans la liste des &lt;strong&gt;Commutateurs virtuels&lt;/strong&gt;, on clique sur &lt;strong&gt;Nouveau commutateur réseau virtuel&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/09/minikube04.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Dans les propriétés, on lui donne un petit nom (minikube par exemple) et on oublie pas de cocher « Réseau externe » (pour utiliser une des cartes physiques comme un bridge) et de cocher ensuite « Autoriser le système d’exploitation de gestion à partager cette carte réseau (surtout si c’est votre seule carte réseau !).&lt;/p&gt;
&lt;p&gt;Pour finir, on récupère Minikube &lt;a class="link" href="https://kubernetes.io/docs/tasks/tools/install-minikube/" target="_blank" rel="noopener"
&gt;ici&lt;/a&gt; et on lance la commande suivante depuis un Powershell :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;minikube start --vm-driver hyperv --hyperv-virtual-switch &amp;#34;minikube&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="option-1--jai-de-la-chance"&gt;Option 1 : « J’ai de la chance »
&lt;/h2&gt;&lt;p&gt;Si tout se passe bien, tant mieux pour vous !&lt;/p&gt;
&lt;p&gt;Vous avez de la chance, tout se passe bien et vous avez Minikube d’installé sur votre poste. C’est la fête, vous allez pouvoir déployer des containers à Gogo !&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PS D:\&amp;gt; minikube status
minikube: Running
cluster: Running
kubectl: Correctly Configured: pointing to minikube-vm at 172.16.25.173
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="protips--et-maintenant-"&gt;Protips : Et maintenant ?
&lt;/h2&gt;&lt;p&gt;Pour aller plus loin, vous pouvez commencer par jeter un oeil sur &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=kubernetes" &gt;mes autres articles qui parlent de Kubernetes&lt;/a&gt;, notamment le tutoriel pas à pas où j’explique comment &lt;a class="link" href="https://blog.zwindler.fr/2017/10/24/tutoriel-xwiki-ma-premier-appli-stateful-sur-kubernetes/" &gt;déployer une application complète et Statefull sur Kubernetes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mais voici quelques protips supplémentaires spécialement dédiées aux spécificités de minikube.&lt;/p&gt;
&lt;h3 id="les-ingress-"&gt;Les Ingress !
&lt;/h3&gt;&lt;p&gt;Pour le fun, on va certainement vouloir ajouter le support des Ingress (pas activés par défaut) :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PS D:\&amp;gt; minikube addons enable ingress
ingress was successfully enabled
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="accéder-au-dashboard"&gt;Accéder au dashboard
&lt;/h3&gt;&lt;p&gt;On peut accéder au Dashboard (l’interface web qui permet de contrôler k8s sans passer par &lt;em&gt;kubectl&lt;/em&gt; ou les API) n’est pas directement accessible avec un &lt;em&gt;kubectl proxy&lt;/em&gt; comme sur un Kubernetes standard.&lt;/p&gt;
&lt;p&gt;Elle est cependant bien disponible sans ajout supplémentaire, à l’aide de la commande suivante :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;minikube dashboard
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="se-loguer-sur-la-machine-virtuelle-k8s"&gt;Se loguer sur la machine virtuelle K8s
&lt;/h3&gt;&lt;p&gt;Si pour une raison ou pour une autre, vous voulez vous connecter en SSH sur la VM qui contient votre environnement Kubernetes, c’est possible ! Récupérez l’IP affectée à la VM (afficher avec un &lt;em&gt;minikube status&lt;/em&gt; ou un &lt;em&gt;kubectl config view&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Il existe un user « docker » avec pour mot de passe « tcuser » (mot de passe ultrasecure, s’il en est). A noter, ce compte à un accès &lt;strong&gt;sudo&lt;/strong&gt; à la machine en &lt;em&gt;NOPASSWD&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ca peut être utile par exemple pour vérifier que les Adminission Controllers sont bien actifs (on en aura besoin dans un prochain article)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ps -ef | grep api
kube-apiserver --admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota --requestheader-allowed-names=front-proxy-client --service-account-key-file=/var/lib/localkube/certs/sa.pub --tls-private-key-file=/var/lib/localkube/certs/apiserver.key --kubelet-client-key=/var/lib/localkube/certs/apiserver-kubelet-client.key --proxy-client-cert-file=/var/lib/localkube/certs/front-proxy-client.crt --requestheader-group-headers=X-Remote-Group --enable-bootstrap-token-auth=true --allow-privileged=true --requestheader-username-headers=X-Remote-User --requestheader-extra-headers-prefix=X-Remote-Extra- --client-ca-file=/var/lib/localkube/certs/ca.crt --proxy-client-key-file=/var/lib/localkube/certs/front-proxy-client.key --insecure-port=0 --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --advertise-address=172.16.25.173 --service-cluster-ip-range=10.96.0.0/12 --tls-cert-file=/var/lib/localkube/certs/apiserver.crt --kubelet-client-certificate=/var/lib/localkube/certs/apiserver-kubelet-client.crt --requestheader-client-ca-file=/var/lib/localkube/certs/front-proxy-ca.crt --secure-port=8443 --authorization-mode=Node,RBAC --etcd-servers=https://127.0.0.1:2379 --etcd-cafile=/var/lib/localkube/certs/etcd/ca.crt --etcd-certfile=/var/lib/localkube/certs/apiserver-etcd-client.crt --etcd-keyfile=/var/lib/localkube/certs/apiserver-etcd-client.key
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl api-versions | findstr &amp;#34;admissionregistration.k8s.io/v1beta1&amp;#34;
admissionregistration.k8s.io/v1beta1
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="option-2"&gt;Option 2
&lt;/h2&gt;&lt;p&gt;Rien ne marche !&lt;/p&gt;
&lt;p&gt;Et pour être parfaitement honnête, c’est ce qui m’est arrivé ! Du coup, je vous prépare un nouvel article avec toutes les astuces de troubleshooting. &lt;a class="link" href="https://blog.zwindler.fr/2018/10/02/minikube-sur-hyper-v-part-2-troubleshooting-de-linstallation/" &gt;La suite - dans le prochain épisode&lt;/a&gt;, donc ;-)&lt;/p&gt;
&lt;h2 id="sources"&gt;Sources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/docs/tasks/tools/install-minikube/" target="_blank" rel="noopener"
&gt;La documentation officielle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.microsoft.com/fr-fr/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v" target="_blank" rel="noopener"
&gt;La documentation « officielle » et minimaliste pour installer Minikube avec Hyper-V&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;l’article MSDN de Microsoft : &lt;a class="link" href="https://blogs.msdn.microsoft.com/wasimbloch/2017/01/23/setting-up-kubernetes-on-windows10-laptop-with-minikube/" target="_blank" rel="noopener"
&gt;Setting up Kubernetes on Windows10 Laptop with Minikube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://medium.com/@JockDaRock/minikube-on-windows-10-with-hyper-v-6ef0f4dc158c" target="_blank" rel="noopener"
&gt;un autre tutoriel pour installer Minikube avec Hyper-V mais qui ne donne pas beaucoup plus d’info que le billet de MSDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Installation xwiki 10.6.1 via un playbook Ansible</title><link>https://blog.zwindler.fr/2018/09/05/installation-xwiki-10-6-via-un-playbook-ansible/</link><pubDate>Wed, 05 Sep 2018 11:45:00 +0000</pubDate><guid>https://blog.zwindler.fr/2018/09/05/installation-xwiki-10-6-via-un-playbook-ansible/</guid><description>&lt;img src="https://blog.zwindler.fr/2018/09/xwiki_ansible.webp" alt="Featured image of post Installation xwiki 10.6.1 via un playbook Ansible" /&gt;&lt;h2 id="ansible--xwiki"&gt;Ansible + XWiki
&lt;/h2&gt;&lt;p&gt;Je sais ce que vous vous dites :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ça fait longtemps que zwindler n’a pas écrit un article sur Ansible ou XWiki !&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Non ? Vous ne vous dites pas ça ? Bon tant pis c’est pas grave. Aujourd’hui, je rédige ENFIN l’article pour parler d’un playbook que j’ai déjà rédigé il y a presque un an déjà (et mis à jour et déployé de nombreuses fois). C’est dire si j’ai du retard dans les articles du blog&amp;hellip;&lt;/p&gt;
&lt;h2 id="petit-rappel-des-épisodes-précédents"&gt;Petit rappel des épisodes précédents
&lt;/h2&gt;&lt;p&gt;J’ai déjà rédigé de manière extensive sur XWiki qui est un belle solution open source de gestion de la connaissance. Parmi les articles les plus susceptibles d’intéresser, il y a déjà :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.zwindler.fr/2016/09/15/installer-xwiki-8-2-1-avec-docker-compose-en-2-lignes-de-commandes/" &gt;Installer facilement XWiki en 2 lignes de commandes avec Docker compose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.zwindler.fr/2016/09/12/migration-mediawiki-vers-xwiki/" &gt;Tutoriel de migration d’un Mediawiki vers XWiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.zwindler.fr/2017/10/24/tutoriel-xwiki-ma-premier-appli-stateful-sur-kubernetes/" &gt;Déploiement d’une application Stateful dans Kubernetes par l’exemple (XWiki + PostgreSQL)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.zwindler.fr/2016/03/12/parametres-caches-de-xwiki-taille/" &gt;Résoudre les erreurs de type « Fichier trop gros » lors de l’import d’un fichier dans XWiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il y en a plein d’autre (&lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=xwiki" &gt;voir ici&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id="et-ansible-"&gt;Et Ansible ?
&lt;/h2&gt;&lt;p&gt;Et bien oui. Je vous rabâche aussi les oreilles avec Ansible, l’Infrastructure as Code, et l’Idempotence. (Là encore, &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=ansible" &gt;il y en a plein&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Alors pourquoi pas un playbook Ansible pour automatiser l’installation de XWiki, si vous n’avez pas de cluster Kubernetes sous la main et que vous êtes un Gaulois réfractaire à Docker ?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/09/gaulois.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="ya-quoi-dans-ton-playbook-"&gt;Ya quoi dans ton playbook ?
&lt;/h2&gt;&lt;p&gt;Trêve de suspense, les sources sont disponibles sur &lt;a class="link" href="https://github.com/zwindler/ansible-deploy-xwiki-tomcat-postgresql" target="_blank" rel="noopener"
&gt;Github à cette adresse&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ce playbook a été testé pour des RHEL/CentOS 7, en particulier de la version 7.2 jusqu’à 7.4. Une installation de RHEL/CentOS en mode minimale, même sans environnement graphique, devrait être suffisante. Je l’ai faite tourner en production sur des environnements Desktop dans des VMs, mais aussi en Minimal sur un container LXC dans Proxmox VE sans aucun souci.&lt;/p&gt;
&lt;p&gt;L’installation n’utilise pas les serveurs web et de bases de données par « défaut » (MySQL), mais Tomcat 8 et PostgreSQL. Pour la version de Tomcat, c’est une version très particulière qu’il faut utiliser car des bugs ont étés introduits dans une version, puis RE-introduits quelques mois plus tard. Vous pouvez modifier la version par défaut qui est une variables de mon playbook (8.5.32) si elle ne vous convient pas. Les instructions d’installation se basent sur &lt;a class="link" href="https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationTomcat/" target="_blank" rel="noopener"
&gt;la documentation officielle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/09/xwiki_warning.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;- tomcat_version: 8.5.32
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Vous pouvez également modifier la version de XWiki directement dans le playbook (c’est une variable là aussi) :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;- xwiki_version: &amp;#34;10.6.1&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A noter, les vielles versions de XWiki n’étaient pas hébergées sur le même dépôt, qui a changé récemment, d’où les deux URLs dans le playbook.&lt;/p&gt;
&lt;h2 id="prérequis"&gt;Prérequis
&lt;/h2&gt;&lt;p&gt;On va utiliser git pour récupérer le playbook et ansible (version de l’OS, rien d’exotique).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;yum install ansible git
git clone https://github.com/zwindler/ansible-deploy-xwiki-tomcat-postgresql
cd ansible-deploy-xwiki-tomcat-postgresql
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="quand-est-ce-quon-installe-xwiki-"&gt;Quand est ce qu’on installe XWiki ?
&lt;/h2&gt;&lt;p&gt;Maintenant !&lt;/p&gt;
&lt;p&gt;Sur un poste qui dispose de git et Ansible :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ansible-playbook -l localhost ansible-deploy-xwiki-tomcat-postgresql.yml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Le playbook devrait vous prompter pour un mot de passe pour l’utilisateur de base de données PostgreSQL, n’hésitez pas à mettre quelque chose de complexe. Vous ne devriez pas en avoir besoin.&lt;/p&gt;
&lt;p&gt;Si vous avez une erreur qui vous dit que localhost est ignoré, vous pouvez l’ajouter à votre fichier d’inventaire global : /etc/ansible/hosts&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo vim /etc/ansible/hosts
[local]
localhost ansible_connection=local
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et Paf ! Vous avez un XWiki installé, disponible à l’adresse &lt;code&gt;http://@IP:8080/&lt;/code&gt;. Il n’y a plus qu’à le configurer :)&lt;/p&gt;</description></item><item><title>Utiliser kubectx/kubens pour changer facilement de context et de namespace dans Kubernetes</title><link>https://blog.zwindler.fr/2018/08/28/utiliser-kubectx-kubens-pour-changer-facilement-de-context-et-de-namespace-dans-kubernetes/</link><pubDate>Tue, 28 Aug 2018 11:45:26 +0000</pubDate><guid>https://blog.zwindler.fr/2018/08/28/utiliser-kubectx-kubens-pour-changer-facilement-de-context-et-de-namespace-dans-kubernetes/</guid><description>&lt;img src="https://blog.zwindler.fr/2017/06/kubernetes2.webp" alt="Featured image of post Utiliser kubectx/kubens pour changer facilement de context et de namespace dans Kubernetes" /&gt;&lt;h1 id="vous-avez-plusieurs-clusters-kubernetes-et-de-nombreux-namespaces"&gt;Vous avez plusieurs clusters Kubernetes et de nombreux namespaces
&lt;/h1&gt;&lt;p&gt;Si vous avez la main sur plusieurs clusters Kubernetes, vous utilisez très probablement la commande kubectl à tour de bras. Et le moins qu’on puisse dire, c’est que switcher d’un cluster à l’autre est parfois pénible, surtout si vous avez en plus de nombreux namespaces dans chacun d’entre eux.&lt;/p&gt;
&lt;p&gt;Pour ceux qui voudraient en savoir plus sur Kubernetes et qui voudraient monter un petit cluster rapidement, je vous renvoie sur mes &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=Kubernetes" &gt;autres articles sur le sujet&lt;/a&gt;; en particulier &lt;a class="link" href="https://blog.zwindler.fr/1017/11/05/installer-kubernetes-kubespray-ansible/" &gt;celui sur Kubespray&lt;/a&gt;, qui a l’avantage incommensurable d’utiliser Ansible pour déployer k8s ;-).&lt;/p&gt;
&lt;h1 id="avec-kubectl"&gt;Avec kubectl
&lt;/h1&gt;&lt;p&gt;Voilà ce qu’il faut faire si vous voulez naviguer de cluster en cluster et de namespace en namespace, simplement avec kubectl (en partant du principe que vos contexts sont déjà configurés).&lt;/p&gt;
&lt;p&gt;On commence par lister les contexts. Oui je ne connais pas par coeur leur nom alors j’ai besoin de regarder comment ils s’appellent et lequel est sélectionné en ce moment.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
k8s-par-prod k8s-par-prod k8s-par-prod-zwindler
k8s-dub-dev k8s-dub-dev k8s-dub-dev-zwindler
* k8s-par-test k8s-par-test k8s-par-test-zwindler
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ici, la petite étoile nous dit que c’est &lt;strong&gt;k8s-par-test&lt;/strong&gt; qui est sélectionné. Pas de bol, c’est en prod que je veux faire mes modifications.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl config use-context k8s-par-prod
Switched to context &amp;#34;k8s-par-prod&amp;#34;.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Si je ne veux pas que le context prod soit celui par défaut (pour éviter de supprimer par erreur des pods en &lt;strong&gt;prod&lt;/strong&gt; alors que je pense être en &lt;strong&gt;dev&lt;/strong&gt;), il est plus prudent de spécifier explicitement à chaque fois dans quel context je me trouve&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl --context k8s-par-prod get nodes
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Maintenant que j’ai sélectionné mon contexte, je veux lister des pods d’un namespace en particulier. Bon, le souci c’est que j’en ai beaucoup des namespaces et je ne me souviens pas toujours comment ils s’appellent. Rebelotte, je liste une nouvelle fois les objets disponibles :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl get ns
NAME STATUS AGE
kube-public Active 361d
kube-system Active 361d
[...]
zwindler Active 126d
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, je me souviens que mes pods sont dans le namespace « zwindler ». Comme pour le context, je peux maintenant soit configurer un namespace par defaut, soit le nommer explicitement :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl -n zwindler get pods
NAME READY STATUS RESTARTS AGE
ubuntu-1111111111-aaaaa 1/1 Running 0 31d
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A noter, si je veux spécifier le context explicitement aussi, ça commence à faire long comme lignes de commandes, juste pour un « get pods » :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl --context k8s-par-prod -n zwindler get pods
NAME READY STATUS RESTARTS AGE
ubuntu-1111111111-aaaaa 1/1 Running 0 31d
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="contourner-la-difficulté"&gt;Contourner la difficulté
&lt;/h2&gt;&lt;p&gt;Si je suis un peu bourrin, j’aurai pu afficher les pods de TOUS les namespaces avec l’option « &amp;ndash;all-namespaces ». C’est une bonne idée si on a pas beaucoup de containers et si on ne sait plus trop dans quel namespace est notre pod. Mais clairement, au delà de 50 pods, ça devient totalement illisible.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
toto ubuntu-1111111111-aaaaa 1/1 Running 0 4h
[... et c&amp;#39;est parti pour des centaines de lignes !!!]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pour se gagner du temps, il existe aussi des fichiers d’autocomplétion pour &lt;strong&gt;kubectl&lt;/strong&gt;. Vous n’avez plus qu’à appuyer sur la touche [tab] une fois que vous avez écris « kubectl &amp;ndash;context  » pour éviter de faire un get préalable et des copier coller le nom du contexte souhaité.&lt;/p&gt;
&lt;p&gt;Vous trouverez des infos sur l’autocomplétion de &lt;strong&gt;kubectl&lt;/strong&gt; sur le site officiel de Kubernetes : &lt;a class="link" href="https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion" target="_blank" rel="noopener"
&gt;kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;echo &amp;#34;source &amp;lt;(kubectl completion bash)&amp;#34; &amp;gt;&amp;gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Mais ça ne vous évite pas les lignes de commande à rallonge avec contexts et namespaces explicitement indiqués.&lt;/p&gt;
&lt;h2 id="un-petit-hack-simple-pour-se-simplifier-la-vie"&gt;Un petit hack simple pour se simplifier la vie
&lt;/h2&gt;&lt;p&gt;Si l’autocomplétion ne vous suffit pas, vous pouvez utiliser deux petits binaires très pratiques, disponibles sur le &lt;a class="link" href="https://github.com/ahmetb/kubectx" target="_blank" rel="noopener"
&gt;dépôt Github de ahmedb&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Vu sur Twitter (comme quoi des fois ça sert), ces deux petits binaires &lt;strong&gt;kubectx&lt;/strong&gt; et &lt;strong&gt;kubens&lt;/strong&gt; permettent de configurer respectivement le &lt;strong&gt;contexte&lt;/strong&gt; et le &lt;strong&gt;namespace&lt;/strong&gt; par défaut. Le projet fourni même l’autocomplétion pour les shells les plus utilisés.&lt;/p&gt;
&lt;h2 id="installation-rapide-de-kubectx-et-kubens"&gt;Installation rapide de kubectx et kubens
&lt;/h2&gt;&lt;p&gt;Ici, rien de bien compliqué. On copie le dépôt sur son poste et on link les binaires dans un dossier du PATH, et on colle l’autocomplétion dans notre shell :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo git clone https://github.com/ahmetb/kubectx /opt/kubectx
sudo ln -s /opt/kubectx/kubectx /usr/local/bin/kubectx
sudo ln -s /opt/kubectx/kubens /usr/local/bin/kubens
echo &amp;#34;source /opt/kubectx/completion/kubectx.bash&amp;#34; &amp;gt;&amp;gt; ~/.bashrc
echo &amp;#34;source /opt/kubectx/completion/kubens.bash&amp;#34; &amp;gt;&amp;gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Simple, non ?&lt;/p&gt;
&lt;h2 id="utilisation-de-kubectx-et-kubens"&gt;Utilisation de kubectx et kubens
&lt;/h2&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;kubectx [tab]
- k8s-par-prod k8s-dub-dev k8s-par-test
kubectx k8s-par-prod
Switched to context &amp;#34;k8s-par-prod&amp;#34;.
kubens
- default blip blup
kube-public kube-system blop [...]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pour le fun le développeur a simplifié la liste des objets et a ajouté un peu de couleur (jaune) pour indiquer quel context/namespace est sélectionné par défaut (plutôt qu’un tableau et une étoile). Peut être un peu gadget mais je ne dis pas non.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/08/kubectx01.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="et-cest-tout-"&gt;Et c’est tout ?
&lt;/h2&gt;&lt;p&gt;Et enfin, &lt;strong&gt;kubectx&lt;/strong&gt; ne sert pas qu’à sélectionner le context par défaut. On peut également réaliser la plupart des commandes sur les contexts avec :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectx --help
USAGE:
kubectx : list the contexts
kubectx : switch to context
kubectx - : switch to the previous context
kubectx = : rename context to
kubectx =. : rename current-context to
kubectx -d [] : delete context (&amp;#39;.&amp;#39; for current-context)
(this command won&amp;#39;t delete the user/cluster entry
that is used by the context)
kubectx -h,--help : show this message
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Alors certes, ça ne va pas révolutionner votre vie, mais ça peut vous faire gagner quelques secondes dans la journée. Et si vous êtes comme moi, vous n’êtes jamais contre quelques secondes de gagnées ;)&lt;/p&gt;</description></item><item><title>Sécuriser l’émission de vos certificats avec un CAA (Azure)</title><link>https://blog.zwindler.fr/2018/06/12/securiser-lemission-de-vos-certificats-azure-avec-un-caa/</link><pubDate>Tue, 12 Jun 2018 11:45:10 +0000</pubDate><guid>https://blog.zwindler.fr/2018/06/12/securiser-lemission-de-vos-certificats-azure-avec-un-caa/</guid><description>&lt;img src="https://blog.zwindler.fr/2018/06/azure.webp" alt="Featured image of post Sécuriser l’émission de vos certificats avec un CAA (Azure)" /&gt;&lt;h2 id="caa--azure-"&gt;CAA ? Azure ?!?
&lt;/h2&gt;&lt;p&gt;Et oui, je travaille sur Azure ! Je crois bien que c’est le premier article que je vais faire à ce sujet donc je commence par quelque chose de léger, créer un CAA.&lt;/p&gt;
&lt;p&gt;Au-delà de toute considération purement dogmatique, le cloud de Microsoft fait quand même partie des plus grands, avec une richesse fonctionnelle et une API aussi riche que ce qu’on trouve chez les autres. J’aurai l’occasion de faire d’autres articles sur Azure car j’utilise énormément les modules Ansible développés par les équipes de Microsoft (qui s’appuient sur l’API d’Azure).&lt;/p&gt;
&lt;h2 id="et-donc-le-caa-"&gt;Et donc, le CAA ?
&lt;/h2&gt;&lt;p&gt;Mais cet article parle de CAA. Pour ceux qui ne connaitraient pas, un CAA est un « nouveau » (2017) type d’enregistrement DNS :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;La CAA est une mesure de sécurité qui permet aux propriétaires d’un nom de domaine de préciser dans leur DNS (Domain Name System) les autorités de certification (AC) qui sont autorisées à émettre des certificats pour leur nom de domaine.&lt;/p&gt;
&lt;p&gt;Global Sign (lien mort, pas disponible sur Internet Archive)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Concrètement, si je possède un domaine avec un grand nombre de sites web signés, que je n’utilise qu’une ou deux (ou un nombre fini) autorités de certifications, je peux maintenant spécifier lesquelles (parmi la centaine des AC existantes) sont autorisées à émettre un certificat pour mon domaine. Cela permettra d’éviter que des personnes mal intentionnées génèrent un certificat pour une URL dans un de vos sous domaines.&lt;/p&gt;
&lt;h2 id="comment-ça-fonctionne-"&gt;Comment ça fonctionne ?
&lt;/h2&gt;&lt;p&gt;Il existe donc un nouveau type d’entrée dans votre DNS qui devrait ressembler à ça :&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;
Name
&lt;/th&gt;
&lt;th&gt;
Type
&lt;/th&gt;
&lt;th&gt;
Value
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan="2"&gt;
zwindler.fr.
&lt;/td&gt;
&lt;td rowspan="2"&gt;
CAA
&lt;/td&gt;
&lt;td rowspan="1"&gt;
0 issue « letsencrypt.org »
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan="1"&gt;
0 iodef « mailto:zwindler@zwindler.fr »
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Pour l’entrée zwindler.fr., j’ai donc un CAA qui dispose de 2 variables (issue et iodef) :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La première indiquant que seul letsencrypt.org peut générer des certificats pour mon domaine. On peut en avoir plusieurs si on a plusieurs autorités de certification.&lt;/li&gt;
&lt;li&gt;La seconde indiquant qu’il faut m’envoyer un email si jamais quelqu’un qui n’a pas les droits essaye de générer un certificat.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;A noter :&lt;/strong&gt; iodef n’est pas respecté par toutes les autorités de certifications, donc vous n’aurez potentiellement pas d&amp;rsquo;emails en cas de tentative de génération de certificat chez une AC non autorisé.&lt;/p&gt;
&lt;h2 id="ok-comment-je-créé-un-caa-"&gt;Ok, comment je créé un CAA ?
&lt;/h2&gt;&lt;p&gt;Normalement, c’est trivial. Il s’agit d’un enregistrement DNS comme un autre. Par exemple chez OVH, vous pouvez directement le créer depuis l’interface :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/06/caa01.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="et-sur-azure-"&gt;Et sur Azure ?
&lt;/h2&gt;&lt;p&gt;Il faut bien que ce soit rigolo. Dans le portail d’Azure, il n’est pas possible de créer (ni même de voir !!!) les champs de types CAA, pourtant disponibles depuis mi 2017.&lt;/p&gt;
&lt;p&gt;La seule solution est d’utiliser l’API REST, la CLI azure, ou Powershell :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.microsoft.com/en-us/cli/azure/network/dns/record-set/caa?view=azure-cli-latest" target="_blank" rel="noopener"
&gt;Page de documentation azure cli&lt;/a&gt; (record-set)&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.microsoft.com/fr-fr/azure/dns/dns-operations-recordsets" target="_blank" rel="noopener"
&gt;Gérer les enregistrements DNS avec Powershell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="avec-azure-cli"&gt;Avec Azure cli
&lt;/h2&gt;&lt;p&gt;Du coup je suis parti de la doc pour faire ça :&lt;/p&gt;
&lt;p&gt;En partant du principe que vous avez un compte sur Azure, que vous gérez les DNS de la zone &lt;strong&gt;zwindler.fr&lt;/strong&gt; depuis Azure DNS (dans un resource group appelé &lt;strong&gt;dns-rg&lt;/strong&gt;), voilà ce qu’il faut faire pour créer une protection pour le sous domaine *&lt;strong&gt;.test.zwindler.fr&lt;/strong&gt;.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;az network dns record-set caa add-record --resource-group dns-rg --zone-name zwindler.fr --record-set-name test --flags 0 --tag &amp;#34;issue&amp;#34; --value &amp;#34;letsencrypt.org&amp;#34;
az network dns record-set caa add-record --resource-group dns-rg --zone-name zwindler.fr --record-set-name test --flags 0 --tag &amp;#34;iodef&amp;#34; --value &amp;#34;zwindl3r@zwindler.fr&amp;#34;
az network dns record-set caa list --resource-group dns-rg --zone-name zwindler.fr
{
&amp;#34;caaRecords&amp;#34;: [
{
&amp;#34;flags&amp;#34;: 0,
&amp;#34;tag&amp;#34;: &amp;#34;iodef&amp;#34;,
&amp;#34;value&amp;#34;: &amp;#34;zwindl3r@zwindler.fr&amp;#34;
},
{
&amp;#34;flags&amp;#34;: 0,
&amp;#34;tag&amp;#34;: &amp;#34;issue&amp;#34;,
&amp;#34;value&amp;#34;: &amp;#34;letsencrypt.org&amp;#34;
}
],
&amp;#34;etag&amp;#34;: &amp;#34;aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa&amp;#34;,
&amp;#34;fqdn&amp;#34;: &amp;#34;test.zwindler.fr.&amp;#34;,
&amp;#34;id&amp;#34;: &amp;#34;/subscriptions/aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa/resourceGroups/dns-rg/providers/Microsoft.Network/dnszones/zwindler.fr/CAA/test&amp;#34;,
&amp;#34;metadata&amp;#34;: null,
&amp;#34;name&amp;#34;: &amp;#34;test&amp;#34;,
&amp;#34;resourceGroup&amp;#34;: &amp;#34;dns-rg&amp;#34;,
&amp;#34;ttl&amp;#34;: 3600,
&amp;#34;type&amp;#34;: &amp;#34;Microsoft.Network/dnszones/CAA&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="et-si-je-veux-le-domaine-entier-"&gt;Et si je veux le domaine entier ?
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Et là c’est la blague !&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Si vous créez un record-set « &lt;em&gt;test&lt;/em&gt;« , il va vous créer un CAA pour &lt;em&gt;test&lt;/em&gt;.zwindler.fr (voire le champ &lt;strong&gt;fqdn&lt;/strong&gt; dans la réponse du list). Vous n’avez pas la main sur le &lt;strong&gt;fqdn&lt;/strong&gt; directement (que ce soit en création ou en mise à jour), il est créé à partir du nom.&lt;/p&gt;
&lt;p&gt;Or, vous avez très probablement envie de protéger &lt;strong&gt;zwindler.fr&lt;/strong&gt;, pas seulement &lt;strong&gt;test.zwindler.fr&lt;/strong&gt;, car ça n’aurait pas vraiment de sens (on rappelle que le but de la manœuvre et d&amp;rsquo;empêcher des gens de générer des certificats pour des sous domaine de votre domaine) sinon.&lt;/p&gt;
&lt;p&gt;Créer une liste exhaustive de tous les sous domaines possibles me semble complexe ;-).&lt;/p&gt;
&lt;p&gt;L’astuce, que vous ne trouverez pas dans la documentation (en tout cas dans les pages que j’ai lues), est de créer un recordset avec comme nom « @ » (j’avais testé, vide, « * », « . », mais pas « @ »&amp;hellip;).&lt;/p&gt;
&lt;p&gt;Et là, un recordset sera créé pour l’ensemble de votre zone DNS (&lt;strong&gt;zwindler.fr&lt;/strong&gt; dans mon exemple).&lt;/p&gt;
&lt;p&gt;Magie-magie&amp;hellip;&lt;/p&gt;
&lt;h2 id="liens-utiles"&gt;Liens utiles
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.ssllabs.com/ssltest/" target="_blank" rel="noopener"
&gt;Un site pour tester son site en HTTPS (Qualys)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://sslmate.com/caa/" target="_blank" rel="noopener"
&gt;Un site pour générer les CAA records (SSLmate)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>