Introduction
Le Langage de Configuration de HashiCorp (HCL), utilisé par Terraform, offre de nombreuses structures et capacités utiles qui se retrouvent dans d’autres langages de programmation. L’utilisation de boucles dans votre code d’infrastructure permet de réduire considérablement le code en double et d’accroître la lisibilité, ce qui permet un refactoring futur plus facile et une plus grande flexibilité. HCL fournit également quelques structures de données communes, telles que les listes et les cartes (appelées respectivement tableaux et dictionnaires dans d’autres langages), ainsi que des conditions pour le bifurcage du chemin d’exécution.
Une caractéristique unique de Terraform est la possibilité de spécifier manuellement les ressources en dépendance. Bien que le graphe d’exécution construit lors de l’exécution de votre code contienne déjà les liens détectés (ce qui est correct dans la plupart des cas), vous pourriez avoir besoin de forcer une relation de dépendance que Terraform n’a pas pu détecter.
Dans cet article, nous passerons en revue les structures de données que HCL fournit, ses fonctionnalités de boucles pour les ressources (les clés count
, for_each
et for
), les conditions pour traiter les valeurs connues et inconnues, et les relations de dépendance entre les ressources.
Prérequis
- Un token d’accès personnel de DigitalOcean que vous pouvez créer via le panneau de contrôle de DigitalOcean. Vous trouverez des instructions dans les documents produits DigitalOcean, Comment créer un token d’accès personnel.
- Terraform installé sur votre machine locale et un projet mis en place avec le fournisseur DigitalOcean. Complétez Steps 1 et Step 2 du tutoriel Comment utiliser Terraform avec DigitalOcean. Assurez-vous de nommer le dossier du projet
terraform-flexibilité
, plutôt queloadbalance
. Pendant Step 2, vous n’avez pas besoin d’inclure la variablepvt_key
et la ressource SSH clé lorsque vous configurez le fournisseur.
Note : Ce tutoriel a été testé spécifiquement avec Terraform 1.0.2
.
Types de données en HCL
Avant de découvrir plus sur les boucles et autres fonctionnalités de HCL qui rendent votre code plus flexible, nous allons d’abord passer sur les types de données disponibles et leur utilisation.
Le langage de configuration de Hashicorp supporte les types primitifs et complexes. Les types primitifs sont des chaînes de caractères, des nombres et des valeurs booléennes, qui sont les types basiques qui ne peuvent pas être dérivés d’autres. Les types complexes, en revanche, regroupent plusieurs valeurs dans une seule. Les deux types de valeurs complexes sont les types structuraux et les types de collection. Les types structuraux permettent de grouper des valeurs de différents types ensemble. L’exemple principal est les définitions de ressources que vous utilisez pour spécifier ce que votre infrastructure sera comme. En comparaison aux types structuraux, les types de collection également regroupent des valeurs, mais uniquement celles du même type. Les trois types de collections disponibles dans HCL dont nous sommes intéressés sont les listes, les cartes et les ensembles.
Les listes sont similaires à des tableaux dans d’autres langages de programmation. Elles contiennent un nombre connu d’éléments de même type, qui peuvent être accédés en utilisant la notation de tableau ([]
) par leur indice entier, commençant à 0. Voici un exemple de déclaration de variable de liste qui contient les noms des Droplet que vous déployerrez dans les étapes suivantes:
Pour le type
, vous avez spécifié qu’il s’agit d’une liste dont le type d’élément est une chaine de caractères, puis vous avez fourni sa valeur par défaut
. En HCL, les valeurs énumérées entre crochets signifient une liste.
Pour le type
, vous avez spécifié que c’est une liste dont le type d’élément est une chaîne de caractères, et vous avez fourni son valeur par défaut
. En HCL, les valeurs énumérées entre crochets signifient une liste.
Les cartes
Les cartes sont des collections de paires clé-valeur où chaque valeur est accédée en utilisant sa clé de type string
. Il y a deux façons de spécifier des cartes entre crochets : par l’utilisation de colones (:
) ou d’égalités (=
) pour spécifier les valeurs. Dans les deux cas, la valeur doit être enquêtée avec des guillemets. Quand vous utilisez des colones, la clé doit également être enquêtée.
La définition suivante de carte contenant des noms de déploiements pour différents environnements est écrite en utilisant l’égalité:
Si la clé commence par un nombre, vous devez utiliser le syntaxe de colonne:
Les ensemble
Les ensembles ne supportent pas l’ordre d’éléments, cela signifie que la traversée des ensembles n’est pas garantie à être identique chaque fois et qu’il n’est pas possible d’accéder en manière cible aux éléments. Ils contiennent des éléments uniques répétés exactement une fois, et spécifier le même élément plusieurs fois résultera en leur présence seule une fois dans l’ensemble.
Déclarer un ensemble est similaire à déclarer une liste, la seule différence étant le type du variable:
Après avoir appris sur les types de données structurées que HCL offre et examiné le syntaxe des listes, des cartes et des ensembles, que nous utiliserons tout au long de ce tutoriel, vous allez tester des méthodes flexibles pour déployer plusieurs instances de la même ressource dans Terraform.
Configurer le nombre de ressources en utilisant la clé « count »
Dans cette section, vous créerez plusieurs instances de même ressource en utilisant la clé « count ». La clé « count » est disponible sur tous les ressources et indique combien d’instances de la même ressource créer.
Vous verrez comment ça fonctionne en écrivant une ressource de Droplet, que vous stockeraz dans un fichier nommé droplets.tf
dans le répertoire du projet que vous avez créé comme préalable. Créez et ouvrez-le pour l’éditer en exécutant :
Ajoutez les lignes suivantes :
Ce code définit une ressource de Droplet appelée test_droplet
, qui tournera sur Ubuntu 20.04 avec 1 Go de RAM et un cœur de processeur.
Noticez que la valeur de count
est fixée à 3
, ce qui signifie que Terraform essayera de créer trois instances de la même ressource. Quand vous avez terminé, sauvegardez et fermez le fichier.
Vous pouvez planifier le projet pour voir quelles actions Terraform effectuerait en exécutant :
La sortie sera similaire à ceci :
Après avoir créé trois instances de test_droplet
avec le même nom web
dans Terraform, il est préférable de modifier la définition du Droplet pour que chaque instance ait un nom unique. Ouvrez droplets.tf
pour le modifier:
Modifiez la ligne indiquée:
Sauvegardez et fermez le fichier.
Terraform fournira les détails suivants concernant la création de trois instances de test_droplet
, toutes avec le même nom. Bien que cela soit possible, il n’est pas recommandé, donc modifiez la définition du Droplet pour que chaque instance ait un nom unique. Ouvrez droplets.tf
pour le modifier:Modifiez la ligne indiquée:
Ensuite, sauvegardez et fermez le fichier.
Les trois instances de test_droplet
seront maintenant créées avec leur index dans leur nom, ce qui les rendra plus faciles à suivre.
Vous avez maintenant compris comment créer plusieurs instances d’une ressource en utilisant la clé count
, ainsi que comment récupérer et utiliser l’indice d’instance pendant la provisionnement. Prochaine étape : apprendre comment extraire le nom du Droplet d’une liste.
Obtenir des noms de déploiement à partir d’une liste
Dans les situations où plusieurs instances du même ressource doivent avoir des noms personnalisés, vous pouvez dynamiquement les récupérer d’une variable de liste que vous avez définie. Pendant le reste du tutoriel, vous verrez plusieurs façons de déployer des déploiements de nuages en utilisant une liste de noms, ce qui promette de la flexibilité et de l’utilisation facile.
Vous devrez d’abord définir une liste contenant les noms de déploiement. Ouvrir un fichier appelé variables.tf
et le fermer pour le modifier :
Ajouter les lignes suivantes :
Sauvegardez et fermez le fichier. Cet exemple définit une liste appelée droplet_names
, contenant les chaînes first
, second
, third
, et fourth
.
Ouvrir droplets.tf
pour le modifier :
Modifier les lignes soulignées :
Pour améliorer la flexibilité, au lieu de spécifier manuellement un nombre constant d’éléments, vous passez la longueur de la liste droplet_names
au paramètre count
, qui retournera toujours le nombre d’éléments dans la liste. Pour le nom, vous récupérez l’élément de la liste situé à l’index count.index
, en utilisant la notation avec crochetes. Sauvegardez et fermez le fichier quand vous avez terminé.
Essayez à nouveau de planifier le projet. Vous recevrez une sortie similaire à celle-ci :
Ainsi, quatre instances de serveurs seront déployées successivement et nommées après les éléments de la liste droplet_names
.
Vous avez appris comment utiliser count
, ses fonctionnalités et sa syntaxe, et vous l’avez utilisé ensemble avec une liste pour modifier les instances de ressources. Vous allez maintenant voir ses défauts et comment les surmonter.
Comprendre les défauts du count
Maintenant que vous connaissez comment le compte est utilisé, examinons ses défauts lorsqu’il est utilisé pour modifier la liste sur laquelle il est appliqué.
Tentez d’effectuer le déploiement des serveurs dans la nuée :
Entrez oui
lorsque vous soyez demandé. La fin de votre sortie sera similaire à ceci :
OutputApply complete! Resources: 4 added, 0 changed, 0 destroyed.
Maintenant, créez une autre instance de serveur en augmentant la liste droplet_names
. Ouvrez variables.tf
pour le modifier :
Ajoutez un nouvel élément au début de la liste :
Quand vous avez terminé, sauvegardez et fermez le fichier.
Préparation du projet :
Vous recevrez un résultat comme celui-ci :
La sortie montre que Terraform renomme les quatre premiers « Droplets » et crée le cinquième appelé fourth
, car il considère les instances comme une liste ordonnée et identifie les éléments (Droplets) par leur numéro d’index dans la liste. C’est ainsi que Terraform initialement considère les quatre premiers Droplet :
Index Number | 0 | 1 | 2 | 3 |
---|---|---|---|---|
Droplet Name | first | second | third | fourth |
Lorsque le nouveau Droplet zero
est ajouté au début, sa représentation interne sous forme de table ressemble ainsi :
Index Number | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
Droplet Name | zero | first | second | third | fourth |
Les quatre premiers Droplets sont alors déplacés d’une place vers la droite. Terraform compare ensuite les deux états représentés dans des tables : à la position 0
, le Droplet était appelé first, et parce qu’il est différent dans la seconde table, il planifie une action d’update. Cela se continue jusqu’à la position 4
, qui n’a pas un élément comparable dans la première table, et au lieu de cela, une action de provisionnement de Droplet est planifiée.
Cela signifie que ajouter un nouvel élément à la liste n’importe où que ce soit, mais pas au bout, résultera en modifications de ressources qui ne sont pas nécessaires. Des actions similaires d’update seront planifiées si un élément de la liste droplet_names
était supprimé.
La principale faiblesse de l’utilisation de count
pour déployer un nombre dynamique de instances différentes du même type de ressource est le suivi des ressources incomplet. Pour un nombre constant et constant de instances identiques, count
est une solution simple qui fonctionne bien. Dans les cas où certains attributs sont tirés d’une variable, cependant, lorsque certains attributs sont fournis par une variable, le boucle for_each
que vous apprendrez plus tard dans cette séquence de tutoriels est une meilleure solution.
Référence à la Ressource Actuelle (self
)
Un autre inconvénient de count
est que référer à une instance arbitraire de ressource par son indice n’est pas possible dans certains cas.
L’exemple principal est les fournisseurs de provisions de temps de destruction, qui se exécutent quand la ressource est planifiée à être détruite. La raison est que l’instance demandée peut ne pas exister (elle est déjà détruite) ou créer une cyclicité mutuelle de dépendance. En tels cas, plutôt que référer à l’objet par la liste des instances, vous pouvez accéder uniquement à la ressource actuelle avec le mot-clé self
.
Pour montrer son utilisation, vous allez maintenant ajouter un fournisseur de localisation destructif à la définition de test_droplet
, qui affichera une message lorsque l’exécution sera effectuée. Ouvrez droplets.tf
pour le modifier :
Ajoutez les lignes suivantes soulignées :
Sauvegardez et fermez le fichier.
Le fournisseur local-exec
exécutera une commande sur la machine locale où Terraform est exécuté. Puisque le paramètre when
est défini sur destroy
, il se exécutera uniquement quand la ressource va être détruite. La commande qui est exécutée écoute une chaîne dans stdout
, qui remplace le nom de la ressource actuelle en utilisant self.name
.
Puisque vous créeront des Droplet de manière différente dans la section suivante, détruisez les Droplet actuellement déployés en exécutant la commande suivante :
Entrez oui
lorsqu’il vous sera demandé. Vous recevrez alors l’exécution du fournisseur local-exec
quatre fois :
En cette section, vous avez appris les défauts du constructeur count
. Vous allez maintenant apprendre le constructeur de boucle for_each
, qui surmonte ces limites et fonctionne avec plus large gamme de types de variables.
Utiliser un Boucle for_each
Dans cette section, vous considérez le constructeur de boucle for_each
, sa syntaxe, et comment cela contribue à la flexibilité lors de la définition de ressources avec plusieurs instances.
for_each
est un paramètre disponible sur chaque ressource, mais contrairement à count
, qui nécessite un nombre d’instances à créer, for_each
accepte un map ou un ensemble. Chaque élément de la collection fournie est parcouru une fois et une instance est créée pour lui. for_each
permet d’accéder à la clé et à la valeur sous la forme des attributs each.key
et each.value
respectivement. Lorsqu’un ensemble est fourni, la clé et la valeur seront les mêmes.
Comme il fournit l’élément courant dans l’objet each
, vous n’aurez pas à accéder manuellement à l’élément souhaité comme vous l’avez fait avec les listes. Dans le cas d’ensembles, cela n’est même pas possible, car ils n’ont pas de schéma d’ordre interne perceptible. Les listes peuvent également être passées en tant qu’arguments, mais elles doivent d’abord être converties en ensemble à l’aide de la fonction toset
.
L’avantage principal de l’utilisation de for_each
, en plus de la capacité à numéroter tous les trois types de données de collection, est que seuls les éléments touchés seront modifiés, créés ou supprimés. Si vous changez l’ordre des éléments d’entrée, aucune action ne sera planifiée, et si vous ajoutez, supprimez ou modifiez un élément de l’entrée, des actions appropriées seront planifiées uniquement pour cet élément.
Changeons le ressource Droplet de count
en for_each
et voyons comment ça marche en pratique. Ouvrez droplets.tf
pour l’édition en exécutant :
Modifiez les lignes surlignées :
Vous pouvez supprimer le fournisseur local-exec
. Quand vous aurez terminé, enregistrez et fermez le fichier.
La première ligne remplace count
et appelle for_each
, en passant la liste droplet_names
sous forme de ensemble à l’aide de la fonction toset
, qui convertit automatiquement l’entrée donnée. Pour le nom de Droplet, vous spécifiez each.value
, qui contient la valeur de l’élément actuel du ensemble des noms de Droplet.
Planifier le projet en exécutant :
La sortie détaillera les étapes que Terraform prendra :
En revanche, Terraform considère maintenant chaque instance individuellement et non pas comme éléments d’une liste ordonnée. Chaque instance est liée à un élément du jeu donné, comme indiqué par la chaîne d’élément affichée dans les crochets à côté de chaque ressource qui sera créée.
Appliquer le plan au cloud en exécutant :
Saisir yes
lors de l’invite. Lorsque cela sera terminé, vous retirerez un élément de la liste droplet_names
pour démontrer que les autres instances ne seront pas affectées. Ouvrez variables.tf
pour l’édition :
Modifiez la liste pour qu’elle soit comme ceci :
Enregistrez et fermez le fichier.
Planifiez à nouveau le projet, et vous recevrez la sortie suivante :
Cette fois, Terraform détruira uniquement l’instance supprimée (appelée zero
), et n’interférera pas avec les autres instances, ce qui est le comportement correct.
Dans cette étape, vous avez appris à propos de for_each
, comment l’utiliser et ses avantages par rapport à count
. Ensuite, vous apprendrez à propos de la boucle for
, sa syntaxe et son utilisation, et quand elle peut être utilisée pour automatiser certaines tâches.
Bouclage utilisant for
La boucle for
fonctionne sur des collections et crée une nouvelle collection en appliquant une transformation à chaque élément de l’entrée. Le type exact de la sortie dépendra de la présence de crochets ([]
) ou d’accolades ({}
) autour de la boucle, ce qui donne respectivement une liste ou une carte. En tant que tel, il est adapté pour interroger des ressources et former des sorties structurées pour un traitement ultérieur.
La syntaxe générale de la boucle for
est :
Comme dans d’autres langages de programmation, vous commencez par nommer la variable de boucle (element
) et spécifier la collection
à énumérer. Le corps du boucle est l’étape de transformation, et une clause optionnelle if
peut être utilisée pour filtrer la collection d’entrées.
Vous allez maintenant travailler sur quelques exemples en utilisant des sorties. Vous les stockeront dans un fichier nommé outputs.tf
. Créez-le pour le modifier en exécutant la commande suivante:
Ajoutez les lignes suivantes pour stocker dans un fichier les paires de noms de déploiements de noeuds et leurs adresses IP:
Ce code spécifie une sortie appelée ip_addresses
, et spécifie une boucle qui itère sur les instances de la ressource test_droplet
que vous avez personnalisé précédemment. Puisque la boucle est encadrée entre des crochets, son résultat sera une map. La étape de transformation pour les maps est similaire aux fonctions lambda dans d’autres langages de programmation, et ici elle crée une paire clé-valeur en combinant le nom de l’instance avec sa propriété IP privée.
Sauvez et fermez le fichier, puis rafraîchissez ensuite le statut de Terraform pour tenir compte de la nouvelle sortie en exécutant:
La commande refresh
de Terraform met à jour le statut local avec l’état réel de l’infrastructure dans le nuage.
Vérifiez alors le contenu des sorties:
Terraform a affiché le contenu de la sortie ip_addresses
, qui est une map construite par le boucle for
. (L’ordre des entrées peut être différent pour vous.) Le boucle fonctionnera parfaitement pour tout nombre d’entrées, ce qui signifie que vous pouvez ajouter un nouvel élément à la liste droplet_names
et le nouveau Droplet, qui serait créé sans aucune autre entrée manuelle, apparaîtrait également dans cette sortie automatiquement.
En encadrant le boucle for
entre crochets, vous pouvez faire en sorte que la sortie soit une liste. Par exemple, vous pourriez ne sortir que les adresses IP des Droplets, ce qui est utile pour des logiciels externes qui parsèment les données. Le code ressemblerait à ceci :
Dans ce cas, l’étape de transformation sélectionne l’attribut de l’adresse IP. Elle donnerait le sortie suivante :
Comme mentionné précédemment, vous pouvez également filtrer la collection d’entrées en utilisant la clause if
. Voici comment vous écrivez le boucle pour filtrer par la région fra1
:
En HCL, l’opérateur ==
vérifie l’égalité des valeurs des deux côtés, ici il vérifie si instance.region
est égal à fra1
. Si c’est le cas, le test est passé et l’instance
est transformée et ajoutée à la sortie, sinon elle est ignorée. La sortie de ce code serait la même que dans l’exemple précédent, car toutes les instances de Droplet sont dans la région fra1
, selon la définition du ressource test_droplet
. La condition if
est également utile lorsque vous voulez filtrer la collection d’entrées pour d’autres valeurs dans votre projet, comme la taille ou la distribution des Droplets.
Parce que vous devez créer des ressources différentes dans la section suivante, détruisez les ressources actuellement déployées en exécutant la commande suivante :
Entrez oui
lorsqu’il vous est demandé pour terminer le processus.
Nous avons expliqué le boucle for
, son syntaxe et des exemples d’utilisation dans les sorties. Vous apprendrez maintenant sur les conditionnels et comment ils peuvent être utilisés ensemble avec count
.
Direttive e condizionali
Nel precedente sezione hai visto come funziona la chiave count
e come funziona. Ora impararemo ad usare gli operatori condizionali ternari che puoi usare altrove nel tuo codice di Terraform e come funzionano insieme con count
.
La sintassi dell’operatore ternario è:
condizione
è un’espressione che calcola un valore booleano (true o false). Se la condizione è vera, allora l’espressione valuta valore_se_vero
. Al contrario, se la condizione è falsa, il risultato sarà valore_se_falso
.
L’uso principale degli operatori ternari è per abilitare o disabilitare la creazione singola di risorse secondo i contenuti della variabile passata al valore count
desiderato sulle risorse desiderate. Questo può essere fatto passando il risultato della comparazione (either 1
o 0
) alla chiave count
sulle risorse desiderate.
En cas d’utilisation de l’opérateur ternaire pour récupérer un seul élément d’une liste ou d’un ensemble, vous pouvez utiliser la fonction one
. Si la collection donnée est vide, elle renvoie null
. Sinon, elle renvoie l’élément unique dans la collection, sinon elle lance une erreur si il y en a plusieurs.
Ouvrez maintenant le fichier variables.tf
pour le modifier :
Ajoutez les lignes soulignées :
Ce code définit la variable create_droplet
de type bool
. Sauvegardez et fermez le fichier.
Pour ensuite modifier la déclaration du Droplet, ouvrez droplets.tf
pour le modifier en exécutant :
Modifiez votre fichier comme suit :
Pour count
, vous utilisez un opérateur ternaire pour retourner soit 1
si la variable create_droplet
est vraie, soit 0
si fausse, ce qui résultera en aucun Droplet ne étant pas fourni. Sauvegardez et fermez le fichier quand vous avez terminé.
Exécutez le plan d’exécution du projet avec la variable définie à false
en exécutant :
Vous recevrez les informations suivantes :
Parce que create_droplet
a été passé avec la valeur de false
, le nombre d’instances est 0
, et aucun Droplet n’est créé, donc aucune adresse IP n’est affichée.
Vous avez vu comment utiliser l’opérateur conditionnel ternaire en combinaison avec la clé count
pour activer un niveau supérieur de flexibilité dans le choix de déployer les ressources désirées. La suite, vous apprendrez à définir explicitement les dépendances de ressources pour vos ressources.
Définition Explicite de Dépendances de Ressources
Lors de la création du plan d’exécution de votre projet, Terraform détecte les chaînes de dépendances entre les ressources et les ordonne implicitement de manière à ce qu’elles soient construites dans l’ordre approprié. Dans la plupart des cas, Terraform est capable de détecter les relations en examinant toutes les expressions dans les ressources et en construisant un graphe.
Cependant, lorsqu’une ressource, afin d’être provisionnée, nécessite l’accès aux paramètres de contrôle déjà déployés par le fournisseur de cloud, il n’y a pas de signe clair pour Terraform qu’elles sont liées. En conséquence, Terraform ne saura pas qu’elles dépendent l’une de l’autre sur le plan de comportement. Dans de tels cas, la dépendance doit être spécifiée manuellement en utilisant l’argument depends_on
.
La clé depends_on
est disponible sur chaque ressource et utilisée pour spécifier les liens de dépendance cachés entre des ressources spécifiques. Les relations de dépendance cachées se forment quand une ressource dépend de la behavior d’une autre sans utiliser aucune de ses données dans sa déclaration, ce qui ferait de Terraform de les connecter d’une manière.
Voici un exemple de comment la depends_on
est spécifiée dans le code :
Il accepte une liste de références à d’autres ressources, et il ne accepte pas des expressions arbitraires.
depends_on
doit être utilisé avec prudence, et seulement lorsque toutes les autres options sont épuisées. Son utilisation signifie que ce que vous essayez de déclarer se trouve hors des limites du système automatique de détection de dépendances de Terraform; cela peut signifier que la ressource est explicitement dépendant de plus de ressources qu’elle n’en a pas besoin.
Vous avez maintenant appris sur le fait de spécifier explicitement des dépendences supplémentaires pour une ressource en utilisant la clé depends_on
. Et cela signifie que vous essayez de déclarer quelque chose qui se trouve hors des limites du système automatique de détection de dépendances de Terraform.
Conclusion
Dans cet article, nous avons expliqué les fonctionnalités de HCL qui améliorent la flexibilité et la scalabilité de votre code, telles que count
pour spécifier le nombre d’instances de ressources à déployer et for_each
comme façon avancée de boucler sur les types de données de collection et personnaliser les instances. Lorsqu’utilisées correctement, elles réduisent considérablement le coût opérationnel lié au gouvernement de l’infrastructure déployée.
Vous avez également appris sur les opérateurs conditionnels et ternaires, et comment ils peuvent être utilisés pour contrôler si une ressource sera déployée. Bien que le système automatique de détection de dépendances de Terraform soit assez capable, il peut arriver que vous deviez spécifier manuellement les dépendances des ressources en utilisant la clé depends_on
.
Cet tutoriel fait partie de la série Comment Gérer l’Infrastructure avec Terraform . La série couvre plusieurs sujets relatifs à Terraform, du premier install du logiciel jusqu’à la gestion de projets complexes.