Vous êtes sur la page 1sur 18

17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code


Publié le : 7 novembre 2021 | Mis à jour le : 10 octobre 2022

Dans le premier billet sur Terraform, j’avais simplement montré comment l’utiliser avec libvirt pour le prendre en main. Je vais commencer une série de billets
pour rentrer dans le vif du sujet. J’utiliserai comme exemple le fichier du précédent billet.

Table des matières


Terraform c’est quoi ?
Rappel sur l’Infrastructure As Code
HCL le langage de Terraform
Le workflow de Terraform
Le state de Terraform
Installer et configurer Terraform
La cli terraform
Le registre Terraform ou registry
Les fichiers de déclarations de configurations
Les providers
Les ressources ou resource
Les variables d’entrée
Les fichiers de variables
Les variables de sortie ou output
Les variables locals
Les data sources ou data
Les provisionneurs ou provisioner
https://blog.stephane-robert.info/post/introduction-terraform/ 1/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

Structure d’un projet Terraform


Plus loin
Mise en pratique

Terraform c’est quoi ?


Terraform, fais partie des meilleurs outils devops et en particulier de l’infrastructure-as-code. Mais pourquoi ?

Tout simplement parce qu’il est agnostique : Un logiciel est dit agnostique en termes de protocole lorsqu'il est indépendant des protocoles de
communication. En effet, Terraform est un outil indépendant à la plateforme visée. On peut aussi bien provisionner des machines dans le cloud (AWS, Azure,
GCP, …) que sur du onprem’s (VmWare, Libvirt, )

Rappel sur l’Infrastructure As Code


L’infrastructure as code (IaC) désigne le processus qui implique la mise à disposition d’environnements à l’aide d’un code contenant la configuration désirée
d’une infrastructure.

Couplé à un système de gestion de code, comme git, plus un gestionnaire de configuration, comme Ansible, et vous avez tout pour faire un parfait gitops. Vous
serez capable de reconstruire toute votre infrastructure à l’identique après une catastrophe, un changement de fournisseur, etc.

HCL le langage de Terraform

Dans le cas de Terraform, le langage utilisé pour définir l’infrastructure est connu sous le nom de HashiCorp Configuration Langage (HCL).

L’objectif principal de Terraform est de déclarer des ressources, qui représentent des objets d’infrastructure. Toutes les autres fonctionnalités de son langage
permettent de rendre la définition des ressources plus flexible et pratique.

Pour le moment nous allons nous concentrer sur la description du workflow de Terraform et l’écriture des fichiers de déclarations.

Le workflow de Terraform

https://blog.stephane-robert.info/post/introduction-terraform/ 2/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

Le workflow de Terraform reposent sur cinq étapes clés : Write, Init, Plan, Apply et Destroy et sur l’enregistrement du state:

Write: Vous commencez à écrire votre configuration.


Init: Vous initialisez votre configuration pour installer les dépendances nécessaires.
Plan: Vous auditez les changements et validez simplement si vous les acceptez.
Apply: Vous appliquez les changements à l’infrastructure réelle.
Destroy: Vous décommissionnez toute votre infrastructure.

Ensuite, vous modifiez votre code, vous rebouclez par plan, apply et ainsi de suite. La phase de destroy n’intervenant que lorsque vous n’avez plus besoin de
ces ressources.

Le state de Terraform
Terraform doit stocker l’état de votre configuration, car il va servir pour mapper les ressources réelles de votre configuration ainsi que ces métadonnées.

Par défaut cet état est stocké dans un fichier local nommé “terraform.tfstate”, mais il peut également être stocké à distance, mais pas dans votre repository git,
parce qu’il peut contenir des secrets.

Terraform utilise cet état pour créer des plans et apporter des modifications à votre infrastructure. Avant toute opération, Terraform effectue un rafraîchissement
pour mettre à jour l’état avec celle de l’infrastructure réelle.

Pour gérer ce state il est possible d’utiliser les workspace et les backends

Installer et configurer Terraform


Dans une fenêtre terminal tapez les commandes suivantes en fonction de votre distribution Linux.

Ubuntu/Debian:

Copy

https://blog.stephane-robert.info/post/introduction-terraform/ 3/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

sudo apt-get update && sudo apt-get install -y gnupg software-properties-common curl

curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -

sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"

sudo apt-get update && sudo apt-get install terraform

RHEL family: Centos, Oracle Linux, Alma Linux, Rocky Linux:

Copy

sudo yum install -y yum-utils

sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo

sudo yum -y install terraform

On lance la commande pour contrôler que tout fonctionne :

Copy

terraform --version

Terraform v1.0.10

La cli terraform
La CLI de Terraform permet entre autre de :

init : La commande init va initialiser le répertoire de travail et vérifier que les plugins utilisés sont correctement installés.
plan : La commande plan permet de créer un plan d’exécution. Terraform va indiquer quelles actions il doit effectuer pour arriver au résultat décrit dans
le fichier de configuration.
apply : L’infrastructure voulue est mise en place.
console : Cette commande permet de faire du débogage, avant de créer un plan ou de l’appliquer.
destroy : L’infrastructure est détruite

Copy

terraform init

terraform plan

terraform apply

terraform destroy

Le registre Terraform ou registry

https://blog.stephane-robert.info/post/introduction-terraform/ 4/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

Comme la plupart des langages de programmation Terraform encourage la réutilisation du code via des artefacts réutilisables. Pour les utilisateurs de
Terraform, la registry Terraform permet la distribution des modules Terraform, qui sont en fait des configurations réutilisables et de se fournir en providers.
Comme avec docker, vous pouvez créer une registry locale pour y stocker votre propre code.

Les fichiers de déclarations de configurations


Les fichiers Terraform porte l’extension .tf dont le principal se nomme main.tf. Comme la plupart des produits HashiCorp, Terraform utilise le langage
HCL.

Le langage de configuration HashiCorp (HCL) permet de décrire rapidement des ressources à l’aide de blocs, d’arguments et d’expressions.

Les blocs sont des conteneurs pour d’autres contenus et représentent généralement la configuration d’un type d’objet, comme une ressource, un provider,
… Les blocs ont un type de bloc, peuvent avoir zéro ou plusieurs étiquettes et avoir un corps qui contient un nombre quelconque d’arguments et de blocs
imbriqués.
Les arguments attribuent une valeur à un nom. Ils apparaissent dans les blocs.
Les expressions représentent une valeur, soit littéralement, soit en référençant et en combinant d’autres valeurs. Ils apparaissent en tant que valeurs
d’arguments ou dans d’autres expressions.

Pour vous aider à écrire du code rapidement et ce de manière sûr je vous conseille d’utiliser l’extension Visual Code. En plus elle est écrite par HashiCorp !

Les providers
Terraform s’appuie sur des plugins appelés « providers » pour interagir avec les fournisseurs de cloud, les fournisseurs SaaS et d’autres API. Les
configurations Terraform doivent déclarer les fournisseurs dont elles ont besoin pour que Terraform puisse les installer et les utiliser. De plus, certains
fournisseurs nécessitent une configuration (comme des URL de point de terminaison ou des régions cloud) avant de pouvoir être utilisés.

Copy

provider "libvirt" {

uri = "qemu:///system"

Ici nous utiliserons le fournisseur libvirt. Nous utiliserons ici une ressource de type volume du provider libvirt qui porte l’étiquette os_image.

Les providers sont distribués séparément de Terraform lui-même, mais ils sont installés automatiquement lors de l’initialisation de votre configuration.
Terraform détermine généralement automatiquement le fournisseur à utiliser en fonction des types de ressource. Pour les providers, comme celui de libvirt, vous
devez utiliser un bloc required_providers :

Copy

https://blog.stephane-robert.info/post/introduction-terraform/ 5/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

terraform {

required_providers {

libvirt = {

source = "dmacvicar/libvirt"

version = "0.6.14"

Les principaux providers d’infrastructure :

AWS
Google Cloud Platform
Azure
VmWare Vsphere

Les ressources ou resource


Les ressources sont les éléments les plus importants du langage Terraform. Une ressource est une entité d’un service (cloud ou pas). De multiples ressources
forment ainsi une infrastructure.

Chaque type de ressource est fournie par un provider, qui est en fait un plugin Terraform. Chaque ressource est associée à un type de ressource unique, qui
détermine le type d’objet d’infrastructure qu’elle manipule.

Copy

resource "libvirt_volume" "os_image" {

name = "${var.hostname}-os_image"

pool = "default"

source = "bionic-server-cloudimg-amd64.img"

format = "qcow2"

Les variables d’entrée

Les Input variables ou variables d'entrée pour nous français, sont définies en indiquant un nom, un type et une valeur par défaut (default = “valeur”). Le
type est optionnel, car Terraform les déduit automatiquement. On peut ajouter une description.

Copy

variable "nom" {

type = "string"

https://blog.stephane-robert.info/post/introduction-terraform/ 6/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

default = "valeur"

description = "Un texte de description."

validation {

condition = condition

error_message = "message d'erreur."

L’étiquette se trouvant après le mot-clé variable est le nom de celle-ci, il doit être unique parmi toutes les variables d’un même module. Ce nom est utilisé pour
lui affecter une valeur ou utiliser sa valeur dans la configuration.

Une variable ne peut pas se nommer : source, version, providers, count, for_each, lifecycle, depends_on ou encore locals.

Pour accéder à une variable dans les blocs, il suffit d’ajouter le préfixe var..

Copy

variable "hostname" {

type = string

default = "staticip"

resource "libvirt_volume" "os_image" {

name = "${var.hostname}-os_image"

pool = "default"

source = "bionic-server-cloudimg-amd64.img"

format = "qcow2"

Les types simples

Les chaines ou string

Le type string est une série de caractères Unicode représentant un texte.

Copy

variable "nom_variable" {

type = "string"

default = "bonjour"

Les nombres ou number

https://blog.stephane-robert.info/post/introduction-terraform/ 7/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

Le type number permet de spécifier une valeur numérique, qui peut être entière ou décimale (.)

Copy

variable "port" {

type = "number"

default = 80

Les booléens ou bool

Le type bool qui peut prendre les valeurs true ou false :

Copy

variable "delete_after" {

type = "bool"

default = true

Les types de variables complexes

Les listes ou list

Le type list est une séquence de valeurs :

Copy

variable "ma_liste" {

type = "list"

default = ["a", 15, true]

Pour accéder à un élément de la liste :

Copy

element = "$ {var.ma_liste [0]}"

Les maps ou map ou object

https://blog.stephane-robert.info/post/introduction-terraform/ 8/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

Le type map est une structure de données composée de couple clé/valeur.

Copy

variable "user1" {

type = "map"

default = {

name = "John"

age = 52

Pour accéder à une clé de la map, deux écritures possibles :

Copy

nom = "$ {var.user1[var.name]}"

nom = "$ {var.user1["name"]}"

Les fichiers de variables


Pour de nombreuses variables, il est préférable de les déclarer dans un fichier de définitions de variables. Un fichier se terminant par l’extension .tfvars.

Par contre, ici pas besoin de spécifier qu’il s’agit d’un bloc de type variable. On les spécifie directement sous la forme nom = valeur.

Copy

port = 80

zones = [

"us-east-1a",

"us-west-1c",

Les fichiers .tfvars doit être chargé explicitement lors de l’application du plan. Pour le charger automatiquement il suffit de l’appeler .auto.tfvars

Les variables de sortie ou output

Les variables de sortie permettent d’afficher les valeurs d’une variable à la sortie de l’application du plan, sauf si elle est déclarée sensitive.

Copy

output "ip" {

value = libvirt_domain.domain-ubuntu.*.network_interface.0.addresses

https://blog.stephane-robert.info/post/introduction-terraform/ 9/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

description = "The public IP address of the server instance."

sensitive = true

Les variables locals


Contrairement aux variables d’entrée, une variable locale n’est accessible que dans les expressions du module où elle a été déclarée. Les valeurs locales peuvent
être utiles pour éviter de répéter plusieurs fois les mêmes valeurs ou expressions dans une configuration, mais si elles sont trop utilisées, elles peuvent également
rendre la lecture d’une configuration difficile. On accède à une variable locale en la préfixant par local..

Copy

locals {

# Common tags to be assigned to all resources

common_tags = {

Service = local.service_name

Owner = local.owner

resource "aws_instance" "example" {

# ...

tags = local.common_tags

Les data sources ou data

Les sources de données appelées data permettent d’extraire ou de calculer des données qui seront ensuite utilisées ailleurs dans votre configuration Terraform.

Copy

data "google_compute_instance" "appserver" {

name = "primary-application-server"

zone = "us-central1-a"

Comme dis précédemment cela peut être aussi une donnée calculée, par exemple l’utilisation d’un template pour générer un fichier qui sera ensuite utilisé par
votre configuration :

Copy

https://blog.stephane-robert.info/post/introduction-terraform/ 10/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

data "template_file" "user_data" {

template = file("${path.module}/cloud_init.cfg")

vars = {

hostname = "${var.hostname}"

fqdn = "${var.hostname}.${var.domain}"

public_key = "${file("./id_rsa.pub")}"

Le contenu (en partie) du template ou on voit l’utilisation des variables ${variable :

Copy

hostname: ${hostname}

fqdn: ${fqdn}

manage_etc_hosts: true

...

C’est comme cela qu’on arrive à créer par exemple un inventaire Ansible qui sera ensuite utilisé par un provisionner local. Mais je préfère utiliser l’inventaire
Ansible du provider en question.

On peut aussi faire appel à des programmes externes ou external :

Copy

data "external" "cars_count" {

program = ["python", "${path.module}/get_cool_data.py"]

query = {

thing_to_count = "cars"

output "cars_count" {

value = "${data.external.cars_count.result.cars}"

Vous commencez à voir le potentiel qu’offre Terraform, il est infini. On peut ainsi récupérer des données d’un vault Terraform. doc

Filtrer les data sources avec filter

Les filtres permettent de faire le tri et de récupérer les informations nécessaires, utiles pour les données externes.

https://blog.stephane-robert.info/post/introduction-terraform/ 11/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

Copy

data "aws_ami" "example" {

executable_users = ["self"]

most_recent = true

name_regex = "^myami-\\d{3}"

owners = ["self"]

filter {

name = "name"

values = ["myami-*"]

filter {

name = "root-device-type"

values = ["ebs"]

filter {

name = "virtualization-type"

values = ["hvm"]

Ici, on récupère toutes les images ami disponibles pour ne garder que celles :

dont le nom contient ‘myami-*’


de root type ebs
de virtualisation-type hvm

La documentation de cette source de données

Utilisation des data dans votre configuration

Comme pour les variables il suffit d’ajouter le suffixe data devant le nom de celui :

Copy

resource "aws_instance" "app" {

ami = "${data.aws_ami.app_ami.id}"

instance_type = "t2.micro"

https://blog.stephane-robert.info/post/introduction-terraform/ 12/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

Les provisionneurs ou provisioner

Les provisioner sont utilisés pour lancer des actions sur la machine locale ou sur une machine distante afin de préparer des serveurs ou d’autres objets
d’infrastructure pour le service. Il existe des trois provisioner génériques : local_exec, remote_exec et file.

Il faut privilégier l’utilisation au maximum les provider plutôt que ces provisioner.

Le provisioner local_exec

Pour exécuter une action locale vous pouvez utiliser le provisioner local_exec :

Copy

resource "null_resource" "example2" {

provisioner "local-exec" {

command = "Get-Date > completed.txt"

interpreter = ["PowerShell", "-Command"]

Du powershell :)

Le provisioner remote_exec

Pour exécuter une action sur la ressource distante il faut utiliser le provisioner remote_exec :

Copy

resource "aws_instance" "web" {

# ...

provisioner "remote-exec" {

inline = [

"dnf -y install epel-release",

"dnf -y install htop",

Le provisioner file

https://blog.stephane-robert.info/post/introduction-terraform/ 13/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

Le provisioner file est utilisé pour copier des fichiers ou des répertoires de la machine exécutant Terraform vers la ressource nouvellement créée.

Copy

resource "aws_instance" "web" {

# ...

# Copies the myapp.conf file to /etc/myapp.conf

provisioner "file" {

source = "conf/myapp.conf"

destination = "/etc/myapp.conf"

Pour info : ce provisioner prend en charge les connexions de type ssh ou et winrm.

Modifier le comportement d’un provisioner

Par défaut, un provisioner s’exécute lorsque la ressource dans laquelle il est défini est créée. Attention seulement pendant la création et non la mise à jour !
Cependant, on peut modifier ce comportement avec les arguments when = destroy et on_failure = continue.

when = destroy permet de lancer un provisioner au moment du décommissionnement d’une ressource.

Copy

resource "aws_instance" "web" {

# ...

provisioner "local-exec" {

when = destroy

command = "echo 'Destroy-time provisioner'"

En cas d’échec d’un provisioner la ressource associé est déclarée comme vérolée. On peut bypasser ce comportement en utilisant on_failure = continue.

Copy

resource "aws_instance" "web" {

# ...

provisioner "local-exec" {

command = "echo The server's IP address is ${self.private_ip}"

on_failure = continue

https://blog.stephane-robert.info/post/introduction-terraform/ 14/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

Structure d’un projet Terraform


Pour un projet très simple, vous pouvez regrouper tout dans un seul fichier main.tf. Cependant, je vous conseille d’adopter une structure pour vous y retrouver
facilement dans tous vos projets, voici la structure que j’ai adoptée :

Copy

├── README.md

├── main.tf

├── variables.tf

├── outputs.tf

├── resources.tf

├── provider.tf

├── terraform.tfvars

├── modules/

│ ├── module1/

│ │ ├── README.md

│ │ ├── variables.tf

│ │ ├── main.tf

│ │ ├── outputs.tf

Le fichier main.tf qui est le fichier principal d’un projet terraform


Le fichier provider.tf pour y définir les fournisseurs
Le fichier variables.tf pour les variables principales
Le fichier terraform.tfvars pour les variables secrètes qui ne sera pas stocké dans votre repository git
Le fichier de variables *.auto.tfvars variables qui sont lues automatiquement
Le fichier outputs.tf pour y définir tout ce qui sera affiché
Les fichiers resources.tf pour un petit projet un simple fichier resources.tf suffira pour de plus prend vous pouvez en créer plusieurs avec des noms
explicites.
Les modules
Le fichier .gitignore dont voici le contenu :

Copy

# Local .terraform directories

**/.terraform/*

# .tfstate files

*.tfstate

https://blog.stephane-robert.info/post/introduction-terraform/ 15/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

*.tfstate.*

# Crash log files

crash.log

# Exclude all .tfvars files, which are likely to contain sentitive data, such as

# password, private keys, and other secrets. These should not be part of version

# control as they are data points which are potentially sensitive and subject

# to change depending on the environment.

*.tfvars

# Ignore override files as they are usually used to override resources locally and so

# are not checked in

override.tf

override.tf.json

*_override.tf

*_override.tf.json

# Include override files you do wish to add to version control using negated pattern

# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan

# example: *tfplan*

# Ignore CLI configuration files

.terraformrc

terraform.rc

L’ordre des blocs et des fichiers dans lesquels ils sont organisés ne sont généralement pas significatifs ; En effet Terraform utilise les relations implicites et
explicites entre les ressources pour déterminer dans quel ordre les opérations vont s’exécuter.

Plus loin
Vous pouvez poursuivre la lecture sur les billets suivants :

Les backends Terraform et les workspaces


Meta-arguments : créer des boucles et modifier le comportement des ressources

Mise en pratique
Je vous propose de suivre l’application dans plusieurs exemples :
https://blog.stephane-robert.info/post/introduction-terraform/ 16/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

En utilisant le provider libvirt:

Provisionning automatique
Resizing automatique des images

Google Cloud Platform

AWS depuis GITLAB

dans Mon Home Lab Devops

Installation de Nexus
Installation de Rundeck
Installation de PowerDNS
FlatCar Linux un os Immutable
Nixos Linux un os Immutable

Mots clés :
devops tutorials infra as code terraform

Si vous avez apprécié cet article de blog, vous pouvez m'encourager à produire plus de contenu en m'offrant un café sur  Ko-Fi. Vous pouvez aussi
passer votre prochaine commande sur amazon, sans que cela ne vous coûte plus cher, via  ce lien . Vous pouvez aussi partager le lien sur twitter ou
Linkedin via les boutons ci-dessous. Je vous remercie pour votre soutien.

Soutenez moi sur Ko-fi  Twitter  Linkedin

Autres Articles
Terraform - Utiliser le provider libvirt
Ansible - Les taches asynchrones
Docker - Optimiser la taille des images utilisant python
Ansible - Créer une machine de test Windows 2019 Server
Ansible 4.0 Les nouveautés
Ansible-console - une console Ansible interactive bien utile
Ansible - Les modules service et service_facts
Ansible - Ajouter, remplacer des lignes dans des fichiers
Ansible - Les principaux modules pour gérer les packages
Ansible - Comment utiliser les templates Jinja
https://blog.stephane-robert.info/post/introduction-terraform/ 17/18
17/11/2022 13:51 Apprendre et Maitriser Terraform l'outil d'Infrastructure As Code

https://blog.stephane-robert.info/post/introduction-terraform/ 18/18

Vous aimerez peut-être aussi