Fin 2019 on m’a demandé d’aider à la migration d’un serveur dédié vers une infrastructure managée AWS pour faciliter la scalabilité d’une plateforme médicale.
La société qui allait s’occuper de l’infogérance (nécessaire pour la certification HDS) ne maitraisant pas Terraform, j’ai utilisé la console AWS pour configurer les différents services. Les pipelines de déploiement, le cluster MongoDB, la configuration réseau… tout a été monté à la main. Les besoins de l’époque étant relativement basiques, ce n’était pas tellement un problème : j’ai pu répliquer intégralement l’infrastructure d’un environnement à l’autre en une grosse journée ou deux.
Mais le temps passant, les besoins changent, la complexité augmente et les risques aussi. Plusieurs acteurs intervenant pour modifier des configurations ou installer de nouveaux outils, le partage d’informations devient compliqué et des effets de bords peuvent apparaître. Risquant également de ne pas toujours être disponible (j’aimerais bien prendre des vacances de temps en temps, quand même 😊), que se passe-t-il s’il faut modifier un élément précis sans risque, ou dupliquer un pipeline pour un nouvel environnement ?
J’ai donc proposé spontanément à mon client de mettre en place des outils pour centraliser la configuration de son infrastructure entière, mais aussi permettre l’automatisation de celle-ci : un simple push sur un dépôt Git pourrait permettre de mettre à jour ce qui a besoin de l’être, sans même se connecter à la console AWS ou lancer un tunnel SSH.
Convaincu, la mission est validée, je me lance donc dans un projet… alors que je n’ai jamais touché à Terraform avant ! Tout juste ai-je joué avec Ansible. Le client me fait confiance malgré tout, c’est parti pour apprendre en pratiquant !
Cet article a vocation d’être une introduction à Terraform. D’autres articles sont prévus pour aborder des aspects plus poussés. Il s’agit ici de poser les bases pour créer des ressources simples avec une organisation de fichiers propre mais linéaire.
- Démarrage en douceur
- Organiser ses fichiers
- Définir un fournisseur
- Utiliser des variables
- Les Locales
- Importer des ressources existantes
- Créer des ressources dépendantes
- Faire sortir des infos
- Tout supprimer et partir en retraite
Démarrage en douceur
Pour faire simple je vous suggère de suivre les tutoriels Get Started officiels de Hashicorp (qui produit Terraform) : j’ai suivi celui pour AWS et ça aide à prendre l’outil en main et assimiler les commandes de base.
On y voit ainsi la syntaxe des fichiers .tf
(qui contiennent la configuration de notre infra) et .tfvars
(qui permettent d’injecter des variables via un fichier, en remplacement ou complément des variables d’environnement), les commandes terraform init
pour installer les dépendances, terraform plan
pour générer un plan d’exécution avant d’appliquer nos modifications et terraform apply
pour déployer une nouvelle version de l’infra.
Les tutoriels sont très bien faits et vous permettront de voir les bases de Terraform appliquées à votre fournisseur préféré.
Organiser ses fichiers
Pour commencer on peut tout mettre dans un même dossier, qui servira de racine à notre projet Terraform. On verra dans un prochain article comment organiser un projet plus complexe avec des modules.
Les fichiers .tf
seront chargés automatiquement, peu importe leur nom : les noms utilisés dans cet article ne sont qu’une convention ou des suggestions. Libre à vous d’en utiliser d’autres si besoin, tant que vous vous y retrouvez.
Les fichiers .tfvars
ne sont pas lus automatiquement, c’est à vous de les inclure lors de certaines commandes (plan
ou apply
par exemple).
Les fichiers .tfstate
sont générés par Terraform automatiquement : évitez d’y toucher, c’est un risque à perdre des données importantes.
Définir un fournisseur
Avant toute chose, dans un projet tout neuf, on indique à Terraform quel fournisseur utiliser :
Il s’agit ici d’indiquer à Terraform que l’on souhaite utiliser la version 1.0
ou plus de l’outil, avec le provider
aws
(version 3.27
ou version mineure supérieure).
En lançant terraform init
il sera alors installé et prêt à l’usage.
On définit ensuite des informations pour initialiser le provider : le profil AWS (défini dans la configuration de l’outil en ligne de commande d’AWS) à utiliser, la région dans laquelle on veut travailler par défaut… et quelques étiquettes (tags
) à appliquer par défaut aux ressources.
Utiliser des variables
Les plus attentifs ont pu remarquer la syntaxe var.xxxx
pour faire appel à une variable.
Définition
On commence donc par les définir :
Les blocs variable
permettent donc d’indiquer que l’on souhaite définir une nouvelle variable dont le nom est dans les guillemets qui suivent, avec une description
, un type
et une éventuelle valeur par défaut (default
).
On peut également y inclure un bloc validation
pour vérifier le format de la variable en question, par exemple sa longueur, les caractères contenus, ou une sous-chaîne… On indique alors une condition
ainsi qu’un message d’erreur (error_message
). Plus d’infos sur la validation de variables.
Injection
On peut alors créer un fichier test.tfvars
pour y définir les valeurs correspondantes spécifiques à cet environnement :
Pour utiliser ce fichier pensez à l’indiquer à Terraform : terraform plan -var-file="./test.tfvars"
ou terraform apply -var-file="./test.tfvars"
.
Les Locales
Un peu sur le même principe, le mot-clé local
permet de calculer une valeur et de l’utiliser comme une variable.
On peut par exemple calculer un préfixe pour les noms des ressources :
On peut alors l’utiliser directement, par exemple en important une paire de clés de chiffrement :
Il faut donc s’assurer d’avoir une clé tutoaws-tests
sur le compte AWS et d’avoir extrait la partie publique (qui commence par ssh-rsa
) pour la mettre dans une nouvelle variable :
Importer des ressources existantes
Que se passe-t-il si la ressource existe déjà ?
Si la clé SSH en question a déjà été créée par AWS, vous pouvez demander à Terraform de l’importer pour éviter qu’il ne tente d’en créer une nouvelle qui pourrait rentrer en conflit :
terraform import -var-file="./test.tfvars" aws_key_pair.main tutoaws-tests
Ici aws_key_pair.main
correspond à la ressource Terraform à importer, et tutoaws-tests
au nom de la clé sur la console AWS. Terraform saura maintenant que la clé existe déjà, vous évitant ainsi des erreurs à l’application de la configuration.
Créer des ressources dépendantes
Jusqu’ici rien de bien difficile, on a créé une simple clé de chiffrement. Et si on voulait créer plusieurs ressources… avec des dépendances entre elles ?
Eh bien on peut faire référence à un attribut d’une ressource comme on utiliserait une variable !
Prenons le cas d’une instance EC2 (un genre de VPS) qui doit faire partie d’un groupe de sécurité :
En n’oubliant pas de définir notre variable :
Faire sortir des infos
Une fois votre configuration appliquée, il peut être intéressant de récupérer des valeurs, notamment celles qui sont générées, pour pouvoir retrouver facilement certaines informations.
On peut alors utiliser un bloc output
:
On peut alors appliquer tout ça :
terraform apply -var-file="./test.tfvars"
Et voilà, vous êtes prêts à pratiquer l'infra-as-code ou IaC !
Tout supprimer et partir en retraite
Enfin… vous êtes pas obligés non plus, mais ça peut être pratique de supprimer toutes ses ressources si c’était juste pour tester, histoire de ne pas payer pour rien :
Cette commande détruit toutes les ressources gérées par Terraform, sans exception. Y compris celles qui ont juste été importées.
Elle ne touche (heureusement) pas aux autres, mais ça reste destructeur.
terraform destroy -var-file="./test.tfvars"