Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
💥 Les 22 & 23 novembre : Accès 100% GRATUIT
à la Bibliothèque Numérique ENI. Je m'inscris !
  1. Livres et vidéos
  2. L’infrastructure as Code avec Terraform
  3. Intégrer Terraform dans une CI/CD
Extrait - L’infrastructure as Code avec Terraform Déployez votre infrastructure sur le Cloud
Extraits du livre
L’infrastructure as Code avec Terraform Déployez votre infrastructure sur le Cloud Revenir à la page d'achat du livre

Intégrer Terraform dans une CI/CD

Les principes de la CI/CD

CI/CD, pour Continuous Integration/Continous Deployment, est un ensemble de pratiques issues du monde du développement.

Le code est partagé dans un référentiel de code commun aux différents membres de l’équipe. Les développeurs travaillent localement sur leur poste. Ils archivent régulièrement leurs modifications de code sur le référentiel. Ils peuvent travailler en parallèle sur plusieurs fonctionnalités, qu’ils archivent sur des branches. Il existe plusieurs implémentations de ces types de référentiels. Le plus utilisé est Git, avec les services GitHub et GitLab.

Lorsqu’un changement est apporté au référentiel de code, un pipeline de CI/CD est déclenché. Un pipeline est l’ensemble des étapes, décrites sous la forme d’un script, qui conduisent à la construction d’un logiciel et à son déploiement.

La partie CI du pipeline consiste en la récupération des dépendances du code, son analyse syntaxique, sa compilation, et l’exécution des tests. La partie CD du pipeline consiste souvent en l’exécution du déploiement sur des environnements dédiés.

Le principe est d’obtenir une boucle de feedback rapide pour les développeurs, d’automatiser les opérations...

Configurer les providers et backend

Les providers Terraform doivent pouvoir être configurés en non interactif pour que terraform init s’exécute correctement. Au-delà du provider, lors du terraform init, le backend est également configuré et interrogé.

Les provider et backend font souvent usage de clés d’API ou de configuration de compte de service pour pouvoir se connecter aux services associés.

Il s’agit alors d’aller étudier la documentation de chaque provider ou backend utilisé pour trouver le meilleur moyen de le configurer.

Dans tous les cas, il ne sera pas souhaitable que des clés d’API ou comptes de service soient archivés avec le reste du code dans des référentiels Git. Le moyen le plus simple est d’utiliser des variables d’environnement qui seront injectées par les pipelines d’intégration continue.

Les sections suivantes illustrent la configuration des provider et backend AWS, GCP, Azure. La configuration d’autres providers, OVH et Scaleway entre autres, est illustrée dans les exemples de code disponible sur GitHub (https://github.com/eni-terraform-samples/) et sur GitLab (https://gitlab.com/eni-terraform-samples/).

1. Configurer le provider AWS et le S3

Le provider AWS peut être configuré directement avec le bloc provider dédié, et avec un backend S3 associé :

provider "aws" { 
  region = "eu-west-1" 
  access_key = "795edc12-5950-4dc4-9887-200c9ced1292" 
  secret_key = "c126b092-4528-4275-ac3d-8da32edd3579" ...

Positionner les variables

Les commandes Terraform, en particulier les commandes terraform plan et terraform apply ont la particularité d’être interactives, en demandant la saisie de variables ou la validation de l’application du plan. Ce n’est pas le cas pour les commandes terraform init ou terraform validate qui ne font qu’afficher les résultats de leur exécution.

Hors, dans un pipeline de CI, la saisie interactive est impossible, à cause de l’exécution scriptée des commandes. Il faut donc donner l’ensemble des variables à Terraform pour son exécution.

Pour illustrer cette section, trois variables sont utilisées avec la déclaration suivante :

variable "environment" { 
  type = string 
} 
variable "instance_count" { 
  type = number 
  default = 2 
} 
variable "instance_type" { 
  type = string 
  default = "M" 
} 

Quatre manières de positionner les variables sont disponibles lors de l’exécution d’un terraform plan, terraform apply ou terraform destroy.

1. Paramètres de ligne de commande

La première consiste à passer l’ensemble des variables de manière unitaire avec le paramètre -var. La commande résultante pour...

Exporter le plan d’exécution et le transmettre à terraform apply

Lors de l’exécution d’un workflow Terraform, plusieurs minutes peuvent se passer entre l’exécution du terraform plan et du terraform apply. Pendant ce temps, des changements peuvent avoir lieu sur les plateformes cloud.

La commande terraform plan possède un paramètre -out qui permet de préciser un fichier dans lequel sera écrit le plan d’exécution. Ce fichier binaire contient en particulier le numéro de version du state actuel, et le plan généré. La commande s’écrit alors terraform plan -out=tfplan. Le nom du fichier (ici tfplan) n’est pas contraint, par convention, utilisez le nom tfplan sans extension. Attention à ne pas utiliser une extension .tf ou .tfvars qui rentrerait en conflit avec le reste du code.

Attention, le fichier de plan d’exécution peut contenir des données sensibles comme des clés d’API, logins ou mot de passe. En effet, les valeurs des variables peuvent être conservées dans un state Terraform, ou dans un output. Les fichiers de plan doivent donc être gérés en conséquence, et ne pas être rendus publics.

La commande terraform apply accepte en argument un fichier de plan d’exécution. La commande s’écrit alors terraform apply...

Bonnes pratiques générales

Avant de passer à l’implémentation des pipelines pour les différents cas d’usage, certaines bonnes pratiques peuvent être listées.

Tout d’abord, il est recommandé d’archiver le fichier .terraform.lock. hcl. Ce fichier contient les versions précises des providers Terraform qui ont été installés pendant le développement du code sur le poste local du développeur. La présence de ce fichier assure que les pipelines de CI/CD utilisent strictement les mêmes versions de provider et de modules. Cela permet d’éviter les effets de bord qui sont liés à des montées de version non voulues.

Pour s’assurer de la présence du fichier .terraform.lock.hcl, la commande terraform init peut être complétée du paramètre -lockfile= readonly pour s’assurer que le fichier de lock est bien présent, et n’est pas écrit lors de l’initialisation.

Cela implique que la mise à jour des différents providers doive se faire sur un poste de développement. La modification du fichier terraform.tf qui contient les contraintes de version de providers est associée à l’exécution de la commande terraform init -upgrade. Cette commande a pour effet de mettre à jour le fichier .terraform.lock.hcl avec...

Déployer de l’infrastructure avec GitLab CI

L’écriture d’un pipeline GitLab CI se fait dans le fichier .gitlab-ci.yml à déposer à la racine du code, dans un projet GitLab.

Cette section ne porte pas sur les détails de la syntaxe de l’écriture d’un pipeline GitLab CI, mais bien uniquement sur l’écriture d’un pipeline adapté à l’exécution de Terraform, et au déploiement de modules dans le Package Registry de GitLab.

La documentation de GitLab CI contient tous les éléments nécessaires à l’écriture d’un pipeline : https://docs.gitlab.com/ee/ci/.

1. L’écriture du pipeline

À titre d’exemple, le code Terraform exécuté dans le pipeline est le suivant :

variable "length" { 
  type = number 
} 
 
resource "random_pet" "dog" { 
  length = var.length 
} 
 
output "dog_name" { 
  value = random_pet.dog.id 
} 

Ce code génère un nom de chien aléatoire et l’enregistre dans un output.

L’écriture du pipeline consiste en trois stages, nommés selon le workflow Terraform,  ’validate’, ’plan’ et ’apply’. L’en-tête de la configuration du pipeline contient la déclaration des trois étapes et la déclaration de l’image Docker utilisée pour exécuter chacun des jobs, et son entrypoint. La directive before_script permet de déclarer un script qui est exécuté avant chaque job.

stages: 
  - validate 
  - plan 
  - apply 
 
default: 
  image: 
    name: hashicorp/terraform 
    entrypoint: 
    - "sh" 
 
before_script: 
  - terraform version 
  - terraform init 

Le premier stage contient les exécutions des commandes...

Publier un module avec GitLab CI

GitLab permet d’héberger des modules Terraform avec la fonctionnalité appelée Package Registry. Cette fonctionnalité se présente comme une alternative au registry public https://registry.terraform.io hébergé par HashiCorp.

La documentation de GitLab propose un guide complet, ainsi qu’un template de pipeline GitLab CI, concernant l’utilisation du Package Registry pour y publier et consommer des modules Terraform. Ce guide est disponible à cette adresse : https://docs.gitlab.com/ee/user/packages/terraform_module_registry/

Le pipeline proposé consiste en l’import d’un template :

include: 
  template: Terraform-Module.gitlab-ci.yml 

Ce pipeline contient trois jobs. Un premier job fmt vérifie le bon formatage du code à l’aide de terraform fmt. Un deuxième job nommé kics-iac-sast vérifie si le module ne présente pas de faille de sécurité connue. Enfin, un troisième job nommé deploy déploie le module Terraform dans le Package Registry. Ce dernier job ne s’exécute que pour les pipelines GitLab déclenchés par un tag Git, comme il est préconisé par HashiCorp pour le déploiement de modules sur GitHub.

Attention, pour que le déploiement s’exécute correctement, les tags Git utilisés...

Déployer de l’infrastructure avec Github Actions

L’écriture d’un workflow GitHub Actions se fait dans les fichiers déposés dans le répertoire .github/workflows à déposer à la racine du code, dans un projet GitHub.

Comme pour GitLab CI, cette section ne porte pas sur les détails de la syntaxe de l’écriture d’un workflow GitHub Actions, mais bien uniquement sur l’écriture d’un workflow adapté à l’exécution de Terraform, et au déploiement de modules.

La documentation de GitHub Actions contient tous les éléments nécessaires à l’écriture d’un pipeline : https://docs.github.com/en/actions/using-workflows

1. L’écriture du workflow

À titre d’exemple, le code Terraform exécuté dans le workflow est le même que celui utilisé dans l’exemple pour GitLab CI :

variable "length" { 
  type = number 
  default = 1 
} 
 
resource "random_pet" "dog" { 
  length = var.length 
} 
 
output "dog_name" { 
  value = random_pet.dog.id 
} 

L’écriture du workflow consiste en un job, qui exécutera dans l’ordre les steps qui suivent le workflow Terraform : init, fmt, ’validate’, ’plan’ et ’apply’. Contrairement à GitLab CI, il n’est pas possible de forcer une validation manuelle sur l’une des étapes du workflow. Cependant, il est possible de limiter l’exécution d’une step à une branche en particulier. L’intégralité des steps sera exécutée...

Conclusion

Ce chapitre a présenté l’utilisation d’outils de CI (Continuous Integration) et de CD (Continuous Deployment) pour automatiser tout ou une partie du workflow Terraform.

Les exemples autour de GitLab CI et GitHub Actions vous permettront de démarrer sur ces deux plateformes. Si votre plateforme de CI/CD est différente, vous réussirez à adapter ces principes !

Le chapitre suivant est un peu spécial. Il présente la certification Terraform Associate, son contenu et son déroulement, ainsi que mes conseils de préparation pour le jour J ! Passer la certification est un bon exercice et vous permettra de valider les connaissances acquises dans cet ouvrage !