Tutoriel pour découvrir Terraform, un outil qui permet de gérer son infrastructure par le code (Infrastructure as Code)

Aurélie Vache

Ce tutoriel permet de découvrir Terraform, un outil qui permet de gérer son infrastructure par le code (Infrastructure as Code).

Pour réagir à cet article, un espace de dialogue vous est proposé sur le forum Commentez .

- Titre : Tutoriel pour découvrir Terraform, un outil qui permet de gérer son infrastructure par le code (Infrastructure as Code)

- Auteur : Aurélie Vache

- Parution : 11 mars 2019

- Licence : Copyright ® 2019 Aurélie Vache. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Qu'est-ce que Terraform ?

- II. Concepts

- II-A. HCL

- II-B. Fournisseur (Provider)

- II-C. Variables

- II-D. Modules

- II-E. Outputs

- II-F. Sources de données (Data Sources)

- II-G. Source de données externe (External Data Source)

- II-G-1. Création du script

- II-G-2. Définition de l'external data source

- II-G-3. Définition de la ressource souhaitée

- II-H. Etat (State)

- III. CLI

- III-A. Init

- III-B. Plan

- III-C. Apply

- III-D. Providers

- III-E. Destroy

- III-F. Console

- III-G. Get

- III-H. Graph

- IV. Mise en pratique

- IV-A. Installation

- IV-B. Initialisation du projet - Création d'un répertoire

- IV-C. Création d'une ressource

- IV-D. Prérequis

- IV-E. Initialiser Terraform

- IV-F. Plan

- IV-G. On applique le plan

- V. Astuces et Outils

- V-A. Pratiques != Bonnes pratiques

- V-B. jq

- V-B-1. Installation

- V-B-2. Utilisation

- V-C. Terraforming

- V-D. Gitignore

- V-E. Module registry

- V-F. Terraform CLI Cheat Sheet

- VI. Comparaison avec des outils équivalent

- VI-A. Terraform

- VI-B. CloudFormation

- VII. Avantages / Inconvénients

- VII-A. Avantages

- VII-B. Inconvénients

- VIII. Conclusion

- IX. Remerciements

I - Qu'est-ce que Terraform ?

Terraform est un outil créé en 2014 par HashiCorp, la société qui a créé d'autres outils que vous connaissez sûrement : Consul, Vagrant, Vault, Atlas, Packer et Nomad.

C'est un outil open source, écrit en Go, avec une communauté active de plus de 1200 contributeurs, plus de 15 000 stars sur Github, et qui repose sur une architecture basée sur les plugins.

Terraform (TF) est un outil qui permet de construire, modifier et versionner une infrastructure.

Contrairement à ce que l'on peut lire sur Internet, la technologie n'est pas « plateforme agnostique », mais elle permet d'utiliser plusieurs providers dans un même template de configuration. Il existe en effet des plugins pour des providers de Cloud, des services d'hébergement, des SCM… Nous le verrons un peu plus tard dans cet article.

Que fait l'outil ?

- Il assure la création et la cohérence d'infrastructure.

- Il permet d'appliquer des modifications incrémentales.

- On peut détruire des ressources si besoin.

- On peut prévisualiser les modifications avant de les appliquer.

Concrètement, Terraform permet de créer automatiquement son infrastructure, comme des machines virtuelles, des lambdas Amazon Web Services (AWS)… le tout, simplement, en trois étapes :

1. Write : écriture de la définition de ses ressources dans des fichiers au format *.tf ;

2. Plan : un plan des ressources à créer/modifier & supprimer est affiché, avant tout changement ;

3. Create : l'infrastructure voulue est mise en place, et reproductible dans tous les environnements souhaités.

L'exemple ci-dessous montre que, en quelques lignes de code, on va pouvoir déployer/créer un bucket S3 sur AWS :

1. resource "aws_s3_bucket" "com-developpez-terraform" {

2. bucket = "mon-bucket-aws-s3-pour-developpez-com"

3. acl    = "private"

5. tags {

6. Contact = "Aurelie Vache"

7. }

8. }

Résultat sur AWS :

II - Concepts

Dans cette section, nous allons présenter les principaux concepts qui composent Terraform.

II-A - HCL

Les fichiers de configuration s'écrivent en HCL (HashiCorp Configuration Language). Le principe est d'écrire des ressources.

Les ressources peuvent être écrites en JSON également, mais il est recommandé de les écrire en HCL.

Lire un fichier de configuration HCL est plutôt simple et intuitif.

C'est un langage dit « human readable ». Ce qu'il faut savoir, c'est que Terraform scanne tous les fichiers se terminant par .tf dans le répertoire courant : il ne va pas scanner les répertoires enfants par contre.

II-B - Fournisseur (Provider)

Un fournisseur (provider) est responsable du cycle de vie/du CRUD (create, read, update, delete) d'une ressource : sa création, sa lecture, sa mise à jour et sa suppression.

Plus de 125 fournisseurs (providers) sont actuellement supportés :

- AWS, GCP, Azure, OpenStack… ;

- Heroku, OVH, 1&1… ;

- Consul, Chef, Vault… ;

- Docker, Kubernetes … ;

- GitLab, BitBucket, GitHub… ;

- MySQL, PostgreSQL… ;

- mais encore RabbitMQ, DNSimple, CloudFlare…

La liste complète des fournisseurs (providers) est disponible sur le site de Terraform : https://www.terraform.io/docs/providers/index.html.

Vous ne trouvez pas le fournisseur de vos rêves ? Pas de soucis, vous pouvez écrire votre propre plugin et participer à l'élaboration de nouvelles fonctionnalités de Terraform. Si vous ne codez pas encore en Go, ce sera l'occasion de vous y mettre ;-).

Pour configurer un fournisseur, si nous voulons par exemple déployer une infrastructure Amazon Web Services (AWS), il suffit de créer une ressource fournisseur « aws » dans un fichier se terminant par .tf :

root.tf

provider "aws" {
region = "eu-central-1"
}

Bonne pratique : ne pas mettre les informations de connexion directement dans la ressource fournisseur « aws » mais plutôt modifier vos variables d'environnement :

export AWS_ACCESS_KEY=YOUR_ACCESS_KEY
export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY
export AWS_DEFAULT_REGION=eu-central-1

Ou bien vous pouvez les mettre dans un fichier .aws/credentials :

[default]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEY

Attention, il va de soi que vous devrez prendre les tokens d'un utilisateur qui aura les droits/la bonne policy pour créer les services que vous voulez.

II-C - Variables

Afin de faire du code propre et qui se réutilise, il est recommandé d'initialiser des variables et de les utiliser dans les autres fichiers .tf.

Définissez vos variables dans un fichier variables.tf, par exemple :

1. variable "default-aws-region" {

2. default = "eu-central-1"

3. }

5. variable "aws_account_id" {

6. default = "123456789123"

7. }

9. variable "tags-tool" {

10. default = "Terraform"

11. }

13. variable "tags-contact" {

14. default = "Aurelie Vache"

15. }

17. variable "aws_s3_folder" {

18. default = "s3"

19. }

21. variable "aws_s3_bucket_terraform" {

22. default = "com.developpez.terraform"

23. }

Appelez-les dans vos ressources :

aws_s3.tf

1. resource "aws_s3_bucket" "com-developpez-terraform" {

2. bucket = "${var.aws_s3_bucket_terraform}"

3. acl    = "private"

5. tags {

6. Tool    = "${var.tags-tool}"

7. Contact = "${var.tags-contact}"

8. }

9. }

II-D - Modules

Les modules sont utilisés pour créer des composants réutilisables, améliorer l'organisation et traiter les éléments de l'infrastructure comme une boite noire.

C'est un groupe de ressources qui prennent en entrée des paramètres et retournent en sortie des outputs.

Dans le même fichier, root.tf, dans lequel vous avez défini votre fournisseur, vous pouvez ensuite définir vos modules :

1. module "lambda" {

2. source            = "./lambda/"

3. toto              = "${var.aws_s3_bucket_toto_lambda_key}"

4. titi              = "${var.aws_s3_bucket_titi_key}"

5. tutu              = "${var.aws_s3_bucket_tutu_key}"

6. }

II-E - Outputs

Les modules peuvent produire des outputs que l'on pourra utiliser dans d'autres ressources.

lambda/outputs.tf

output "authorizer_uri" {
value = "${aws_lambda_function.lambda_toto.invoke_arn}"
}

aws_api_gw.tf

1. resource "aws_api_gateway_authorizer" "custom_authorizer" {

2. name                             = "CustomAuthorizer"

3. rest_api_id                      = "${aws_api_gateway_rest_api.toto_api.id}"

4. authorizer_uri                   = "${module.lambda.authorizer_uri}"

5. identity_validation_expression   = "Bearer .*"

6. authorizer_result_ttl_in_seconds = "30"

7. }

II-F - Sources de données (Data Sources)

Les sources de données (Data Sources) servent à récupérer une donnée/ressource existante dans votre infrastructure.

Utiliser une source de données est une bonne pratique. En effet, il est bon de privilégier son utilisation plutôt que de coder en dur des subnet_id, account_id ou autre donnée qui peut être récupérée !

data.tf

1. # VPC

2. data "aws_subnet" "subnet_id_1" {

3. filter {

4. name = "tag:Name"

5. values = ["mysubnet-for-developpez"]

6. }

7. }

Et ensuite vous pouvez appeler cette source de données simplement dans vos fichiers .tf comme ceci :

root.tf

1. module "developpez" {

2. source = "developpez"

3. subnet_id_1 = "${data.aws_subnet.subnet_id_1.id}"

4. }

II-G - Source de données externe (External Data Source)

Comme nous l'avons vu, il est possible de récupérer une source de données grâce à un système de filtre. C'est super… mais, et oui il y a un mais… malheureusement ce filtrage n'est pas possible avec tous les types de ressources.

Chez AWS il existe deux types de répartition de charge (load balancer) : classique et réseau (network). Imaginons que nous souhaitions récupérer une répartition de charge de type réseau, chez AWS, pour pouvoir créer une AWS Route 53 Record (entrée dans un nom de domaine). Nous ne pouvons appliquer un filtre sur ce type de ressources, nous allons donc devoir trouver une parade pour récupérer notre fameuse répartition de charge de type réseau.

La solution est de réaliser les actions suivantes.

1. Créer un script qui récupère la ressource.

2. Utiliser le résultat de ce script dans une source de données Terraform avec un external provider.

3. Utiliser cette donnée spéciale dans une ressource que vous voulez créer.

II-G-1 - Création du script

my_module/scripts/get_elb.sh

#!/bin/bash
set -e
kubectl get svc mygateway -n istio-system -o json | jq .status.loadBalancer.ingress[0]

Ce script retourne un objet JSON contenant une gateway Kubernetes (Istio) (côté infrastructure il s'agit d'un AWS Load Balancer).

1. $ ./my_module/scripts/get_elb.sh

2. {

3. "hostname": "a123456789gsfgfsgfsg12134gsgsg78-123456789dfdsf45545fdsf.elb.eu-central-1.amazonaws.com"

4. }

II-G-2 - Définition de l'external data source

my_module/data.tf

data "external" "elb" {
program= ["bash", "${path.module}/scripts/get_elb.sh"]
}

II-G-3 - Définition de la ressource souhaitée

my_module/aws_r53.tf

1. resource "aws_route53_record" "mymodule_CNAME" {

2. zone_id="${data.aws_route53_zone.my_zone.zone_id}"

3. name="${var.domain_name}"

4. type="CNAME"

5. records= ["${data.external.elb.result.hostname}"]

6. ttl="${var.route53_ttl}"

7. }

II-H - Etat (State)

Un état (state) est un snapshot de votre infrastructure depuis la dernière fois que vous avez exécuté la commande terraform apply.

Terraform utilise un stockage local pour créer les plans et effectuer les changements sur votre infrastructure, mais il est possible de stocker cet état dans une solution cloud.

Pour configurer le stockage de cet état de manière distante, il suffit de définir un backend.

backend.tf

1. # Backend configuration is loaded early so we can't use variables

3. terraform {

4. backend "s3" {

5. region  = "eu-central-1"

6. bucket  = "com.developpez.terraform"

7. key     = "state.tfstate"

8. encrypt = true

9. }

10. }

III - CLI

Terraform a une CLI (Command-Line Interface) facile à utiliser et composée de plusieurs commandes : nous allons en voir quelques-unes, pas toutes, uniquement celles que j'utilise le plus au quotidien.

III-A - Init

terraform init

La commande init va initialiser votre répertoire de travail qui contient vos fichiers de configuration au format .tf.

C'est la première commande à exécuter pour une nouvelle configuration, ou après avoir fait un checkout d'une configuration existante, depuis votre dépôt git par exemple.

La commande init va :

- télécharger et installer les fournisseurs (providers) ;

- initialiser le backend (si défini) ;

- télécharger et installer les modules (si définis).

III-B - Plan

terraform plan

La commande plan permet de créer un plan d'exécution. Terraform va déterminer quelles actions il doit entreprendre afin d'avoir les ressources listées dans les fichiers de configuration par rapport à ce qui est actuellement en place sur l'environnement/le fournisseur cible.

Cette commande n'effectue concrètement rien sur votre infrastructure.

Bonne pratique : afin de sauver le plan, vous pouvez spécifier un fichier de sortie.

terraform plan -out developpez.out

III-C - Apply

terraform apply developpez.out

La commande apply, comme son nom l'indique, permet d'appliquer les changements à effectuer sur l'infrastructure. C'est cette commande qui va créer nos ressources.

Attention : depuis la version 0.11 de Terraform, sorti le 16 novembre 2018, lorsque vous utilisez Terraform dans un environnement interactif, en local par exemple, mais pas en CI/CD, il est recommandé de ne plus passer par un plan d'exécution mais de directement utiliser la commande apply et de répondre Yes si vous souhaitez appliquer ce plan.

III-D - Providers

Après application de la définition de vos ressources, vous pouvez vérifier les fournisseurs (providers) utilisés par Terraform dans vos projet et modules.

1. $ terraform providers

2. .

3. ├── provider.aws ~> 1.54.0

4. └── module.my_module

5. ├── provider.aws (inherited)

6. └── provider.external

III-E - Destroy

terraform destroy

La commande destroy permet de supprimer TOUTES les ressources.

Un plan de suppression peut être généré au préalable :

terraform plan -destroy

III-F - Console

Grâce à la commande console, vous pouvez connaître la valeur d'une ressource Terraform. Cette commande est pratique pour faire du débogage, avant de créer un plan ou de l'appliquer.

$ echo "aws_iam_user.developpez.arn" | terraform console
arn:aws:iam::123456789123:user/developpez

III-G - Get

terraform get

Cette commande get est utile si, par le passé, vous avez déjà fait un terraform init puis ajouté un module. Il faut préciser maintenant à Terraform qu'il faut récupérer le module ou bien le mettre à jour. Si vous ne le faites pas, lors d'un terraform plan, Terraform vous demandera de le faire.

III-H - Graph

terraform graph | dot -Tpng > graph.png`

La CLI graph permet de dessiner un graphique de dépendances visuel des ressources Terraform en fonction des fichiers de configuration.

Au bout d'un certain nombre de ressources dans un répertoire, Terraform n'arrive plus à générer ce graphique. J'espère que ce problème sera corrigé dans les futures versions.

IV - Mise en pratique

Comme les concepts et les principales commandes de Terraform ont été présentés, passons à la pratique !

IV-A - Installation

Commençons tout d'abord par installer Terraform.

curl -O https://releases.hashicorp.com/terraform/0.11.10/terraform_0.11.10_linux_amd64.zip
sudo unzip terraform_0.11.10_linux_amd64.zip -d /usr/local/bin/
rm terraform_0.11.10_linux_amd64.zip

0.11.10 étant la dernière version de Terraform, stable, à ce jour.

Ces commandes vont extraire un binaire dans /usr/local/bin/, qui est déjà dans la variable d'environnement PATH.

Vous pouvez également installer Terraform grâce à l'outil tfenv, un Terraform version manager. La première chose à faire est de télécharger le binaire de tfenv et de le mettre dans la variable d'environnement PATH.

1. $ git clone https://github.com/Zordrak/tfenv.git

2. ~/.tfenv

3. $ echo 'export PATH="$HOME/.tfenv/bin:$PATH"'

4. >> $HOME/bashrc

Ensuite, vous pouvez simplement installer Terraform ou le mettre à jour en précisant la version désirée.

tfenv install 0.11.10

Afin de vérifier que Terraform est correctement installé, veuillez vérifier la version courante de l'outil.

$ terraform --version
Terraform v0.11.10

Pour information la commande terraform -version fonctionne également.

IV-B - Initialisation du projet - Création d'un répertoire

mkdir developpez/

IV-C - Création d'une ressource

1. $ vi aws_s3.tf

2. ############### AWS S3 ###############

3. resource "aws_s3_bucket" "com-developpez-terraform" {

4. bucket = "${var.aws_s3_bucket_terraform}"

5. acl = "private"

6. tags {

7. Tool = "${var.tags-tool}"

8. Contact = "${var.tags-contact}"

9. }

10. }

IV-D - Prérequis

Pour indiquer à Terraform sur quel compte AWS vous souhaitez déployer l'infrastructure souhaitée, vous devez définir des variables d'environnement AWS au préalable, par exemple dans un fichier .aws/credentials ou avec des variables d'environnement.

export AWS_ACCESS_KEY_ID="an_aws_access_key"
export AWS_SECRET_ACCESS_KEY="a_aws_secret_key"
export AWS_DEFAULT_REGION="a-region"

IV-E - Initialiser Terraform

1. $ terraform init

2. [0m[1mDownloading modules...[0m

3. [0m[1mInitializing the backend...[0m

4. [0m[1mInitializing provider plugins...[0m

5. The following providers do not have any version constraints in configuration,

6. so the latest version was installed.

7. To prevent automatic upgrades to new major versions that may contain breaking

8. changes, it is recommended to add version = "..." constraints to the

9. corresponding provider blocks in configuration, with the constraint strings

10. suggested below.

11. * provider.aws: version = "~> 1.3"

IV-F - Plan

1. $ terraform plan -out crf.out

2. Refreshing Terraform state in-memory prior to plan...

3. The refreshed state will be used to calculate this plan, but will not be

4. persisted to local or remote state storage.

5. aws_s3_bucket.com-developpez-terraform: Refreshing state... (ID: com.developpez.terraform)

6. ...

7. Plan: 1 to add, 0 to change, 0 to destroy.

IV-G - On applique le plan

$ terraform apply plan.out
...
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

V - Astuces et Outils

V-A - Pratiques != Bonnes pratiques

Si vous vous êtes déjà renseignés sur Terraform avant de consulter ce tutoriel, vous avez sans doute vu que la pratique d'organisation du code que l'on voit sur le net est que toutes les ressources Terraform sont écrites dans un fichier main.tf qui contient un peu de tout : la définition des ressources à créer, la définition du remote state, de la version du/des providers à utiliser…

Personnellement je ne recommande pas du tout cette approche. Je pense qu'il ne faut pas confondre les pratiques et les bonnes pratiques.

Faire du Terraform c'est faire de l'infrastructure as Code et donc c'est faire/écrire du code. Il s'agit donc de coder proprement. Afin que le code puisse être maintenable, s'il y a une bonne pratique à connaître, c’est qu'il vaut mieux bien organiser son code, et ce cas s'applique également pour de l'IaC et donc nos fichiers Terraform.

Au revoir l'énorme fichier main.tf contenant des torchons, des serviettes et des chaussettes (ou plutôt du GCP, Azure, AWS, Kubernetes, Vault….) et bonjour une organisation de fichier .tf qui consiste à séparer par fichier, par type de ressources, et à utiliser des modules.

Exemple :

1. .

2. ├── backend.tf

3. ├── cfg

4. │   ├── s3.dev.tf

5. │   ├── s3.prerprod.tf

6. │   └── s3.prod.tf

7. ├── mymodule1

8. │   ├── aws_acm.tf

9. │   ├── aws_api_gateway.tf

10. │   ├── aws_cloudwatch.tf

11. │   ├── aws_iam.tf

12. │   ├── aws_kinesis.tf

13. │   ├── aws_lambda.tf

14. │   ├── aws_r53.tf

15. │   ├── aws_s3.tf

16. │   ├── data.tf

17. │   ├── output.tf

18. │   ├── resources

19. │   │   └── swagger.json

20. │   └── variables.tf

21. ├── data.tf

22. ├── mymodule2

23. │   ├── aws_els.tf

24. │   ├── output.tf

25. │   └── variables.tf

26. ├── root.tf

27. ├── scripts

28. │   ├── migrateMapping.sh

29. │   └── resources

30. │       └── myproject.json

31. └── variables.tf

V-B - jq

jq est un command-line JSON processor léger. Combiné avec les output de Terraform, cela peut être très puissant.

V-B-1 - Installation

sudo apt install jq

V-B-2 - Utilisation

Nous allons récupérer uniquement le point d'accès (Endpoint) d'un elasticsearch.

$ terraform output -json | jq '.elastic_endpoint.value'
"vpc-toto-12fgf1235f4d1235get123.eu-central-1.es.amazonaws.com"

V-C - Terraforming

Afin de nous faciliter la vie, il y a quelques petits outils intéressants à connaître et à utiliser. Si vous avez une infrastructure AWS existante et que vous devez la dupliquer dans plusieurs autres comptes, Terraforming (https://github.com/dtan4/terraforming) est fait pour vous. C'est un outil écrit en Ruby qui permet d'extraire des ressources AWS existantes et de générer un fichier Terraform correspondant.

Pour l'installer, voici la marche à suivre :

sudo apt install ruby
gem install terraforming

Pour extraire un type de ressources, c'est très simple. Par exemple, si l'on veut extraire des buckets s3 :

terraforming s3 > aws_s3.tf

Comme vous pouvez le constater, si vous testez cette commande sur un compte AWS qui contient des buckets s3, cette dernière n'extrait que les buckets, elle n'extrait pas les objets : les zip, jar et divers fichiers contenus dans vos buckets.

Il vous faudra du coup écrire les ressources aws_s3_object comme ceci :

1. resource "aws_s3_bucket_object" "authorizer_keystore" {

2. bucket = "${var.aws_s3_bucket_authorizer}"

3. key    = "${var.aws_s3_bucket_authorizer_keystore_key}"

4. source = "${var.aws_s3_folder}/${var.aws_s3_bucket_authorizer_keystore_key}"

5. etag   = "${md5(file("${var.aws_s3_folder}/${var.aws_s3_bucket_authorizer_keystore_key}"))}"

7. tags {

8. Tool    = "${var.tags-tool}"

9. Contact = "${var.tags-contact}"

10. }

11. }

Attention, Terraforming ne prend pas en compte toutes les ressources AWS, notamment les API Gateway. De ce fait, même si vous souhaitez dupliquer une API GW existante, il vous faudra vous les écrire à la mimine.

V-D - Gitignore

.gitignore

1. #  Local .terraform directories

2. **/.terraform/*

4. # .tfstate files

5. *.tfstate

6. *.tfstate.*

8. # .tfvars files

9. *.tfvars

11. # .out files

12. *.out

V-E - Module registry

Plutôt que de créer vos propres modules, une autre bonne pratique est de consulter avant sur le module registry s'il n’en existe pas déjà un répondant à vos besoins.

V-F - Terraform CLI Cheat Sheet

En tant que développeur et DevOps, on aime bien avoir des petits guides qui nous résument tout ce qu'il y a à savoir sur une technologie. N'en ayant pas trouvé d'existant concernant Terraform, j'ai décidé de créer ma propre Cheat SHeet que j'ai mise sur Github afin de la partager avec tout le monde : github.com/scraly/terraform-cheat-sheet

VI - Comparaison avec des outils équivalent

Terraform n'est pas le seul à pouvoir faire de l'Infrastructure as Code. Lorsque l'on parle de AWS il y a également CloudFormation qui existe.

Voici un petit tableau qui compare les deux technologies.

VI-A - Terraform

- Support de presque tous les services AWS et d'autres (cloud) providers.

- Open source.

- Pas de rolling update pour les ASG (Auto Scaling Group).

- HCL/JSON.

- State management.

- Support de Vault.

VI-B - CloudFormation

- Support de presque tous les services AWS (uniquement ce cloud provider).

- Service géré et « offert par AWS ».

- Le rolling update d'EC2 par un ASG est supporté.

- JSON / YAML (depuis 2016).

- Pas de State management.

Il n'y a pas de meilleure technologie, chacune à ses avantages et ses inconvénients. CloudFormation couvre un peu plus de ressources AWS pour le moment que Terraform, mais ne prend pas en compte d'autres fournisseurs.

À noter qu'il est possible de charger du CloudFormation (CF) dans du Terraform, si par exemple vous avez déjà votre stack écrite en CF.

1. # Setup of an CloudformationStack with terraform

2. resource "aws_cloudformation_stack" "my_stack" {

3. depends_on = [

4. "aws_s3_bucket_object.lambda_code",

5. "aws_s3_bucket_object.authorizer"

6. ]

7. name = "${var.cf_stack_name}"

8. template_url = "https://${aws_s3_bucket.deployment_bucket.bucket_domain_name}/cf_logic.json"

9. provider = "aws.region"

11. parameters {

12. LambdaCodeAuthorizer = "${basename(var.authorizer_lambda_jar)}",

13. S3CodeBucket = "${aws_s3_bucket.deployment_bucket.id}",

14. ...

15. }

17. tags {

18. Tool    = "${var.tags-tool}"

19. Contact = "${var.tags-contact}"

20. }

21. }

VII - Avantages / Inconvénients

Terraform n'est pas une baguette magique : cette technologie a des inconvénients, comme toutes les technologies. Il s'agit notamment d'un outil assez jeune, et en constante évolution, donc il y a des bogues et toutes les ressources de tous les providers ne sont pas encore prises en compte.

On peut dresser une petite liste de « Pros » et de « Cons ».

VII-A - Avantages

- Permet de définir de l'Infrastructure as Code (IaC).

- Syntaxe concise et lisible.

- Réutilisation de : variables, inputs, outputs, modules.

- Commande plan.

- Multi cloud support.

- Développement très actif.

VII-B - Inconvénients

- Outil jeune (comporte des bogues).

- Pas de rollback possible.

- Assez verbeux.

- Pauvre gestion des secrets (à combiner avec Vault par exemple !).

J'ajouterai que les messages d'erreurs ne sont pas super explicites :

1. * module.lambda.aws_lambda_function.lambda_toto: 1 error(s) occurred:

3. * module.lambda.aws_lambda_function.lambda_toto: aws_lambda_function.lambda_toto: InvalidSignatureException: Signature expired: 20171218T075729Z is now earlier than 20171218T080647Z (20171218T081147Z - 5 min.)

4. status code: 403, request id: 17c82bc7-e3cb-11e7-8a7e-6b18fbf66fae

VIII - Conclusion

Ma conclusion personnelle est que Terraform est un des outils qui permettent de faire de l'Infrastructure as Code et de passer du ClickOps au DevOps.

Mais faire du Terraform en local ce n'est pas la vraie vie, donc nous pourrons voir dans un prochain épisode comment automatiser la création de ressources écrites en Terraform dans une chaîne d'intégration continue et de déploiement continu avec notre fidèle compagnon : Jenkins.

Nous verrons également comment manipuler les worskspaces pour faire du Terraform dans un contexte multienvironnement en ne définissant les ressources qu'une seule fois.

Nous pourrons également voir qu'il n'existe pas que CloudFormation ou Terraform, pour gérer des ressources sur AWS, donc nous ferons un comparatif avec les Opérateurs Kubernetes AWS et nous verrons comment se fait la mise en pratique.

IX - Remerciements

Cet article a été publié avec l'aimable autorisation de Aurélie Vache.

Nous tenons à remercier naute pour sa relecture orthographique attentive de cet article puis Winjerome et Mickael Baron pour la mise au gabarit.