arrow-left

Only this pageAll pages
gitbookPowered by GitBook
1 of 15

Français (French)

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Bienvenue

Ce document a pour but de décrire systématiquement les bonnes pratiques dans l’utilisation de Terraform et de fournir des recommandations par rapport aux problèmatiques fréquemment rencontrées.

Terraformarrow-up-right, un projet relativement nouveau (comme la plus part des outils Devops actuellement), a été lancé en 2014.

Terraform est un outil puissant (si ce n'est le plus puissant actuellement disponible) et le plus utilisé pour le gestion de l'infrastructure comme code. Il permet aux developpeurs de créer plusieurs codes dont le support et l'intégration seront faciles

Certaines informations décrit dans ce livre pourraient ne pas ressembler aux bonnes pratiques. J'en suis conscient, et pour aider les lecteurs à séparer ce qui établit comme bonnes pratiques et ce que je considère être d'autres méthodes équivalentes, j'utiliserai par moment des indications pour fournir un certain contexte et des icônes pour spécifier le niveau de maturité de chaque sous-section reliée aux bonnes pratiques

Ce livre a été commencé dans une ville de Madrid ensoleillée en 2018 et est disponible gratuitement ici https://www.terraform-best-practices.com/arrow-up-right

Quelques années plus tard il a été mis à jour grâce à plusieurs récentes bonnes pratiques disponibles avec Terraform 1.0. Éventuellement ce livre devrait contenir la plupart des bonnes pratiques et recommandations indiscutables pour les utilisateurs de Terraform.

hashtag
Sponsors

Please if you want to become a sponsor.

hashtag
Translations

Contactez-moi si vous voulez aider à traduire ce livre dans d'autres langues.

hashtag
Contributions

Je souhaite toujours obtenir des commentaires et mettre à jour ce livre au fur et à mesure que la communauté mûrit et que de nouvelles idées sont mises en œuvre et vérifiées au fil du temps. Si vous êtes intéressé par certains sujets, veuillez ouvrir un problème ou en indiquer un que vous souhaitez être traiter plus en détail. Si vous sentez que vous avez du contenu et que vous souhaitez y contribuer, rédigez un brouillon et soumettez un pull request (ne vous souciez pas d'écrire un bon texte à ce stade !)

hashtag
Authors

Ce livre est maintenu par Anton Babenko avec l'aide de différents contributeurs et traducteurs. Nicanor Foping l'a traduit en français.

hashtag
License

Ce travail est sous licence Apache 2. Voir LICENCE pour plus de détails.

Les auteurs et contributeurs de ce contenu ne peuvent garantir la validité des informations trouvées ici. Veuillez vous assurer que vous comprenez que les informations fournies ici sont fournies librement et qu'aucun type d'accord ou de contrat n'est créé entre vous et toute personne associée à ce contenu ou projet. Les auteurs et les contributeurs n'assument pas et déclinent par la présente toute responsabilité envers toute partie pour toute perte, dommage ou perturbation causé par des erreurs ou des omissions dans les informations contenues dans, associées ou liées à ce contenu, que ces erreurs ou omissions résultent de négligence, accident ou toute autre cause.

Copyright © 2018-2023 Anton Babenko.

— Terraform Compliance Simplified. Make your Terraform modules compliance-ready.

—

contact mearrow-up-right
العربية (Arabic)chevron-right
Bosanski (Bosnian)chevron-right
Português (Brazilian Portuguese)chevron-right
Englishchevron-right
ქართული (Georgian)chevron-right
Deutsch (German)chevron-right
ελληνικά (Greek)chevron-right
עברית (Hebrew)chevron-right
हिंदी (Hindi)chevron-right
Bahasa Indonesia (Indonesian)chevron-right
Italiano (Italian)chevron-right
日本語 (Japanese)chevron-right
ಕನ್ನಡ (Kannada)chevron-right
한국어 (Korean)chevron-right
Polski (Polish)chevron-right
Română (Romanian)chevron-right
简体中文 (Simplified Chinese)chevron-right
Español (Spanish)chevron-right
Türkçe (Turkish)chevron-right
Українська (Ukrainian)chevron-right
اردو (Urdu)chevron-right
arrow-up-right
Compliance.tfarrow-up-right

FAQ

FTP (Frequent Terraform Problems)

hashtag
Quels sont les outils que je devrais connaître et envisager d'utiliser?

  • Terragruntarrow-up-right - Outil d'orchestration

  • - Code linter

  • - Gestionnaire de versions

  • - Automation des demandes d'extraction (Pull Request)

  • - Collection de git hooks pour Terraform à utiliser avec

  • - Estimation des coûts du cloud pour Terraform dans les demandes de pull. Fonctionne aussi avec Terragrunt, Atlantis et pre-commit-terraform

hashtag
Quelles sont les solutions à l'enfer des dépendances avec les modules ?

Les versions des modules de ressources et d'infrastructure doivent être spécifiées. Les fournisseurs doivent être configurés en dehors des modules, mais uniquement en composition. La version des fournisseurs et de Terraform peut également être verrouillée.

Il n'y a pas d'outil maître de gestion des dépendances, mais il existe quelques astuces pour rendre l'enfer des dépendances moins problématique. Par exemple, peut être utilisé pour automatiser les mises à jour des dépendances. Dependabot crée des demandes d'extraction pour garder vos dépendances sécurisées et à jour. Dependabot prend en charge les configurations Terraform.

tflintarrow-up-right
tfenvarrow-up-right
Atlantisarrow-up-right
pre-commit-terraformarrow-up-right
pre-commit frameworkarrow-up-right
Infracostarrow-up-right
Dependabotarrow-up-right

Style de code

circle-info
  • Les exemples et les modules Terraform doivent contenir une documentation expliquant les fonctionnalités et comment les utiliser.

  • Tous les liens dans les fichiers README.md doivent être absolus pour que le site Web Terraform Registry les affiche correctement.

  • La documentation peut inclure des diagrammes créés avec et des plans créés avec .

  • Utilisez pour vous assurer que le code est valide, correctement formaté et automatiquement documenté avant qu'il ne soit transmis à git et examiné par des humains

hashtag
Documentation

hashtag
Documentation génèrée automatiquement

est un cadre de gestion et de maintenance des hooks de pré-commit multilingues. Écrit en Python, il est un outil puissant pour faire quelque chose automatiquement sur la machine d'un développeur avant que le code ne soit validé dans un référentiel git. Normalement, il est utilisé pour exécuter des linters et formater du code (voir ).

Avec les configurations Terraform pre-commit peut être utilisé pour formater et valider le code, ainsi que pour mettre à jour la documentation.

Vérifiez le pour vous familiariser avec lui, et les référentiels existants (par exemple, ) où cela est déjà utilisé.

hashtag
terraform-docs

est un outil qui génère la documentation des modules Terraform dans différents formats de sortie. Vous pouvez l'exécuter manuellement (sans crochets de pré-commit), ou utiliser pour obtenir la documentation mise à jour automatiquement.

@ToDo: Document module versions, release, GH actions

hashtag
Resources

  1. Blog posté par :

mermaidarrow-up-right
cloudcraft.coarrow-up-right
Terraform pre-commit hooksarrow-up-right
pre-commitarrow-up-right
supported hooksarrow-up-right
pre-commit-terraform repositoryarrow-up-right
terraform-aws-vpcarrow-up-right
terraform-docsarrow-up-right
pre-commit-terraform hooksarrow-up-right
pre-commit framework homepagearrow-up-right
Collection of git hooks for Terraform to be used with pre-commit frameworkarrow-up-right
Dean Wilsonarrow-up-right
pre-commit hooks and terraform - a safety net for your repositoriesarrow-up-right

Concepts clés

La documentation officielle de Terraform décrit tous les aspects de la configuration en détailarrow-up-right. Il faudrait la lire attentivement pour comprendre le reste de cette section

Cette section décrit les concepts clés qui seront utilisés dans le livre.

hashtag
Ressource

Une ressource est un objet commeaws_vpc, aws_db_instance, etc. Une ressource appartient à un fournisseur, accepte des arguments, génère des attributs et possède des cycles de vie. Une ressource peut être créée, récupérée, mise à jour et supprimée.

hashtag
Module de ressources

Un module de ressources est un ensemble de ressources connectées qui exécutent mutuellement l'action commune (par exemple, le module AWS VPC Terraform crée un VPC, des sous-réseaux, une passerelle NAT, etc.). Il dépend de la configuration du fournisseur, qui peut être définie dans celui-ci, ou dans des structures de niveau supérieur (par exemple, dans le module d'infrastructure).

hashtag
Module d'infrastructure

Un module d'infrastructure est un ensemble de modules de ressources, qui peuvent logiquement ne pas être connectés, mais dans la situation/projet/configuration actuels, ils ont le même objectif. Il définit la configuration des fournisseurs, qui est transmise aux modules de ressources en aval et aux ressources. Il est normalement limité au travail dans une entité par un séparateur logique (par exemple, AWS Region, Google Project).

Par exemple, le module utilise des modules de ressources comme et pour gérer l'infrastructure requise afin d'opérationneliser sur .

Un autre exemple est le module qui emploie plusieurs modules de ensemble afin de gérer l'infrastructure et utilisent les ressources Docker pour créer, pousser et déployer des images Docker. Tout en un ensemble.

hashtag
Composition

La composition est une collection de modules d'infrastructure, qui peuvent s'étendre sur plusieurs zones logiquement séparées (par exemple, des régions AWS, plusieurs comptes AWS). La composition est utilisée pour décrire l'infrastructure complète requise pour l'ensemble de l'organisation ou du projet.

Une composition est constituée de modules d'infrastructure, qui comprennent des modules de ressources implémentant des ressources individuelles.

hashtag
Source de données

La source de données effectue une opération en lecture seule et dépend de la configuration du fournisseur. Elle est utilisée dans un module de ressources et un module d'infrastructure.

La source de données terraform_remote_stateagit comme une colle (lien) pour les modules et les compositions de niveau supérieur.

La source de données permet à un programme externe d'agir en tant que source de données, exposant des données arbitraires à utiliser ailleurs dans la configuration Terraform. En voici un exemple à partir du module où le nom de fichier est obtenu en appelant un script Python externe.

La source de données envoie une requête HTTP GET à l'URL donnée et exporte des informations liées à la réponse. Ces dernières sont souvent utiles pour obtenir des informations à partir de points de terminaison où un fournisseur Terraform natif n'existe pas.

hashtag
État distant

Les modules et les compositions d'infrastructure doivent conserver leur dans un emplacement distant où il peut être récupéré par d'autres de manière contrôlable (par exemple, l'accès spécifique à l'ACL, la gestion des versions, la journalisation).

hashtag
Fournisseur, commission etc

Les fournisseurs, les commission (provisioner) et quelques autres termes sont très bien décrits dans la documentation officielle et il est inutile de le répéter ici. À mon avis, ils ont peu à voir avec l'écriture de bons modules Terraform.

hashtag
Pourquoi est ce si difficile?

Alors que les ressources individuelles sont comme des atomes dans l'infrastructure, les modules de ressources sont des molécules. Un module est la plus petite unité versionnable et partageable. Il a une liste exacte d'arguments, implémente une logique de base pour qu'une telle unité remplisse la fonction requise. Par exemple, le module crée des ressources aws_security_group etaws_security_group_rule en fonction de l'entrée. Ce module de ressources en lui-même peut être utilisé avec d'autres modules pour créer le module d'infrastructure.

L'accès aux données à travers les molécules (modules de ressources et modules d'infrastructure) est effectué à l'aide des sorties et des sources de données des modules.

L'accès entre les compositions est souvent effectué à l'aide de sources de données à distance. Il existe .

Lorsque vous mettez les concepts décrits ci-dessus dans des pseudo-relations, cela peut ressembler à ceci :

Ecrire des configurations Terraform

hashtag
Utilisez locals pour spécifier des dépendances explicites entre les ressources

Moyen utile d'indiquer à Terraform que certaines ressources doivent être supprimées au préalable lorsqu'il n'y a pas de dépendance directe dans les configurations Terraform.

Atélier

Il existe également un atelier pour les personnes qui souhaitent mettre en pratique certaines des choses décrites dans ce guide.

Le contenu est ici -

https://github.com/antonbabenko/terraform-best-practices-workshoparrow-up-right
terraform-aws-atlantisarrow-up-right
terraform-aws-vpcarrow-up-right
terraform-aws-security-grouparrow-up-right
Atlantisarrow-up-right
AWS Fargatearrow-up-right
terraform-aws-cloudqueryarrow-up-right
terraform-aws-modulesarrow-up-right
externe arrow-up-right
terraform-aws-lambdaarrow-up-right
http arrow-up-right
état Terraformarrow-up-right
terraform-aws-security-grouparrow-up-right
plusieurs façons de partager des données entre les configurationsarrow-up-right
Simple infrastructure composition
hashtag
Terraform 0.12 - Arguments réquis ou optionnels
  1. L'argument obligatoire index_documentdoit être défini, si var.website n'est pas une map vide.

  2. L'argument optionnel error_document peut être omis.

https://raw.githubusercontent.com/antonbabenko/terraform-best-practices/master/snippets/locals.tfarrow-up-right
main.tf
variable "website" {
  type    = map(string)
  default = {}
}

resource "aws_s3_bucket" "this" {
  # omitted...

  dynamic "website" {
    for_each = length(keys(var.website)) == 0 ? [] : [var.website]

    content {
      index_document = website.value.index_document
      error_document = lookup(website.value, "error_document", null)
    }
  }
}
composition-1 {
  infrastructure-module-1 {
    data-source-1 => d1

    resource-module-1 {
      data-source-2 => d2
      resource-1 (d1, d2)
      resource-2 (d2)
    }

    resource-module-2 {
      data-source-3 => d3
      resource-3 (d1, d3)
      resource-4 (d3)
    }
  }

}
terraform.tfvars
website = {
  index_document = "index.html"
}

Infrastructure de petite taille avec Terraform

Source: https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/small-terraformarrow-up-right

Cet exemple contient du code comme exemple de structuration des configurations Terraform pour une infrastructure de petite taille, où aucune dépendance externe n'est utilisée.

circle-check
  • Parfait pour commencer et refactoriser au fur et à mesure

  • Parfait pour les petits modules de ressources

  • Bon pour les petits modules d'infrastructure linéaires (par exemple, )

  • Bon pour un petit nombre de ressources (moins de 20-30)

circle-exclamation

Un fichier d'état unique pour toutes les ressources peut ralentir le processus de travail avec Terraform si le nombre de ressources augmente (envisagez d'utiliser un argument -target pour limiter le nombre de ressources)

Infrastructure de taille moyenne avec Terraform

Source:

Cet exemple contient du code comme exemple de structuration des configurations Terraform pour une infrastructure de taille moyenne qui utilise :

  • 2 comptes AWS

  • 2 environnements séparés (prod

terraform-aws-atlantisarrow-up-right
et
stage
qui ne partagent rien). Chaque environnement réside dans un compte AWS distinct
  • Chaque environnement utilise une version différente du module d'infrastructure standard (alb) provenant de Terraform Registryarrow-up-right

  • Chaque environnement utilise la même version d'un module interne modules/network puisqu'il provient d'un répertoire local.

  • circle-check
    • Parfait pour les projets où l'infrastructure est logiquement séparée (comptes AWS séparés)

    • Bon lorsqu'il n'est pas nécessaire de modifier les ressources partagées entre les comptes AWS (un environnement = un compte AWS = un fichier d'état)

    • Bon quand il n'y a pas besoin d'orchestration des changements entre les environnements

    • Bon lorsque les ressources d'infrastructure sont différentes par environnement à dessein et ne peuvent pas être généralisées (par exemple, certaines ressources sont absentes dans un environnement ou dans certaines régions)

    circle-exclamation

    Au fur et à mesure que le projet grandit, il sera plus difficile de maintenir ces environnements à jour les uns avec les autres. Il faudrait envisagez d'utiliser des modules d'infrastructure (prêts à l'emploi ou internes) pour les tâches répétables.

    hashtag

    https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/medium-terraformarrow-up-right

    Terraform

    Terragrunt

    Convention des noms

    hashtag
    Conventions générales

    circle-info

    Il ne devrait y avoir aucune raison de ne pas suivre au moins ces conventions :)

    circle-info

    Prenez notes que les ressources réelles dans le cloud ont souvent des restrictions dans les noms autorisés. Certaines ressources, par exemple, ne peuvent pas contenir de tirets, certaines doivent être en camel-case. Les conventions de ce livre font référence aux noms Terraform eux-mêmes.

    1. Utilisez _ (surligné) au lieu de - (tiret) partout (noms des ressources, noms des sources de données, noms des variables, sorties, etc.).

    2. Préférez les lettres minuscules et les chiffres (même si UTF-8 est pris en charge).

    hashtag
    Arguments de ressource et de source de données

    1. Ne répétez pas le type de ressource dans le nom de la ressource (ni partiellement, ni complètement) :

    circle-check
    triangle-exclamation
    triangle-exclamation
    1. Le nom de la ressource doit être ainsi donné s'il n'y a plus de nom descriptif et général disponible, ou si le module de ressources crée une seule ressource de ce type (par exemple, dans il y a une seule ressource de type aws_nat_gateway et plusieurs ressources de typeaws_route_table, donc aws_nat_gateway pourrait être nommé this etaws_route_table devrait avoir des noms plus descriptifs - comme private, public, database

    hashtag
    Exemples de code de ressource

    hashtag
    Utilisation de count / for_each

    circle-check
    triangle-exclamation

    hashtag
    Emplacement de tags

    circle-check
    triangle-exclamation

    hashtag
    Conditions dans count

    circle-check

    hashtag
    Variables

    1. Ne réinventez pas la roue dans les modules de ressources : utilisez le nom, la description et la valeur par défaut des variables telles que définies dans la section "Référence des arguments" pour la ressource avec laquelle vous travaillez.

    2. La prise en charge de la validation dans les variables est plutôt limitée (par exemple, impossible d'accéder à d'autres variables ou de faire des recherches). Planifiez en conséquence car dans de nombreux cas, cette fonctionnalité est inutile.

    3. Utilisez la forme plurielle dans un nom de variable lorsque type est list(...)

    hashtag
    Sorties

    Faire les sorties cohérentes et compréhensibles en dehors de son champ d'application (lorsqu'un utilisateur utilise un module, le type et l'attribut de la valeur renvoyée doivent être évidents).

    1. Le nom de la sortie doit décrire la propriété qu'il contient et être moins libre que vous ne le souhaiteriez normalement.

    2. Une bonne structure pour le nom de la sortie ressemble à {name}_{type}_{attribute} , où:

      1. {name} est le nom de la ressource ou de la source de données

    hashtag
    Exemples de Code de sortie (output)

    Renvoie au plus un ID de groupe de sécurité :

    circle-check

    Lorsque vous avez plusieurs ressources du même type, cela doit être omis dans le nom de la sortie:

    triangle-exclamation

    hashtag
    Utilisez un nom pluriel si la valeur retournée est une liste

    circle-check

    Références

    circle-info

    Il y a beaucoup de gens qui créent un excellent contenu et gèrent des projets open source pertinents pour la communauté Terraform, mais je ne peux pas penser à la meilleure structure pour obtenir ces liens répertoriés ici sans copier des listes comme .

    - Liste des personnes qui travaillent très activement avec Terraform et qui peuvent vous en dire beaucoup (si vous leur demandez).

    - Liste organisée de ressources sur Terraform de HashiCorp.

    Infrastructure de grande taille avec Terraform

    Source:

    Cet exemple contient du code comme exemple de structuration des configurations Terraform pour une infrastructure de grande taille qui utilise :

    • 2 comptes AWS

    • 2 régions

    2 environnements séparés (prod et stage qui ne partagent rien). Chaque environnement réside dans un compte AWS distinct et répartit les ressources entre 2 régions

  • Chaque environnement utilise une version différente du module d'infrastructure standard (alb) provenant de Terraform Registryarrow-up-right

  • Chaque environnement utilise la même version d'un module interne modules/network puisqu'il provient d'un répertoire local.

  • circle-info

    Dans un grand projet comme décrit ici, les avantages de l'utilisation de Terragrunt deviennent très visibles. Voir Code Structures examples with Terragrunt.

    circle-check
    • Parfait pour les projets où l'infrastructure est logiquement séparée (comptes AWS séparés)

    • Bon lorsqu'il n'est pas nécessaire de modifier les ressources partagées entre les comptes AWS (un environnement = un compte AWS = un fichier d'état)

    • Bon quand il n'y a pas besoin d'orchestration des changements entre les environnements

    • Bon lorsque les ressources d'infrastructure sont différentes par environnement à dessein et ne peuvent pas être généralisées (par exemple, certaines ressources sont absentes dans un environnement ou dans certaines régions)

    circle-exclamation

    Au fur et à mesure que le projet grandit, il sera plus difficile de maintenir ces environnements à jour les uns avec les autres. Il faudrait envisagez d'utiliser des modules d'infrastructure (prêts à l'emploi ou internes) pour les tâches répétables.

    hashtag

    https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/large-terraformarrow-up-right
    - "Your Weekly Dose of Terraform" chaine YouTube par Anton Babenko. Live avec des critiques, des interviews, des questions-réponses, du codage en direct et du hacking avec Terraform.

    https://weekly.tfarrow-up-right - Infolettre hebdomadaire avec Terraform. Diverses actualités dans le monde Terraform (projets, annonces, discussions) par Anton Babenko.

    awesome-terraformarrow-up-right
    https://twitter.com/antonbabenko/lists/terraform-expertsarrow-up-right
    https://github.com/shuaibiyy/awesome-terraformarrow-up-right
    http://bit.ly/terraform-youtubearrow-up-right
    ).
  • Toujours utilisez des noms au singulier.

  • Utiliser - à l'intérieur des valeurs des arguments et aux endroits où la valeur sera exposée à un humain (par exemple, à l'intérieur du nom DNS de l'instance RDS).

  • Inclure l'argument count / for_each à l'intérieur du bloc de ressource ou de source de données comme premier argument en haut et séparé par une nouvelle ligne après celui-ci.

  • Inclure l'argument tags,si pris en charge par ressource, comme dernier argument réel, suivi de depends_on etlifecycle, si necessaire. Tous ces éléments doivent être séparés par une seule ligne vide.

  • Lorsque vous utilisez des conditions dans un argumentcount / for_each, il est préférable d'employer les valeurs booléennes au lieu delength ou d'autres expressions.

  • ou
    map(...)
    .
  • Ordonner les clés dans un bloc variable comme ceci: description , type, default, validation.

  • Toujours inclure description sur toutes les variables même si vous pensez que c'est évident (vous en aurez besoin à l'avenir).

  • Préférez l'utilisation de types simples (number, string, list(...), map(...), any) plutôt qu'un type spécifique comme object() sauf si vous avez besoin d'avoir des contraintes strictes sur chaque clé.

  • Utilisez des types spécifiques comme map(map(string))si tous les éléments de la carte ont le même type (par exemple, string) ou peuvent être convertis en celui-ci (par exemple, le type de nombre peut être converti en string).

  • Utilisez type any pour désactiver la validation de type à partir d'une certaine profondeur ou lorsque plusieurs types doivent être pris en charge.

  • La Valeur {} est parfois un map mais quelques fois object. Utiliser tomap(...) pour créer une carte car il n'y a aucun moyen de créer un objet.

  • sans le préfixe du fournisseur.
    {name}
    pour
    aws_subnet
    est sous-réseau, pour
    aws_vpc
    ce sera
    vpc
    .
  • {type} est le type de ressource

  • {attribute} est l'attribut retourné par la sortie

  • Voir exemples.

  • Si la sortie renvoie une valeur avec des fonctions d'interpolation et plusieurs ressources, {name} et {type} il devrait être aussi générique que possible (this comme préfixe être omis). Voir exemple.

  • Si la valeur renvoyée est une liste, elle doit avoir un nom au pluriel. Voir exemple.

  • Incluez toujours une description pour toutes les sorties, même si vous pensez que c'est évident.

  • Évitez de définir un argument sensible à moins que vous ne contrôliez entièrement l'utilisation de cette sortie à tous les endroits de tous les modules

  • Préférez try() (disponible depuis Terraform 0.13) à element(concat(...)) (approche héritée pour la version antérieure à 0.13)

  • AWS VPC modulearrow-up-right
    `resource "aws_route_table" "public" {}`
    `resource "aws_route_table" "public_route_table" {}`
    `resource "aws_route_table" "public_aws_route_table" {}`
    main.tf
    resource "aws_route_table" "public" {
      count = 2
    
      vpc_id = "vpc-12345678"
      # ... remaining arguments omitted
    }
    
    resource "aws_route_table" "private" {
      for_each = toset(["one", "two"])
    
      vpc_id = "vpc-12345678"
      # ... remaining arguments omitted
    }
    main.tf
    resource "aws_route_table" "public" {
      vpc_id = "vpc-12345678"
      count  = 2
    
      # ... remaining arguments omitted
    }
    main.tf
    resource "aws_nat_gateway" "this" {
      count = 2
    
      allocation_id = "..."
      subnet_id     = "..."
    
      tags = {
        Name = "..."
      }
    
      depends_on = [aws_internet_gateway.this]
    
      lifecycle {
        create_before_destroy = true
      }
    }   
    main.tf
    resource "aws_nat_gateway" "this" {
      count = 2
    
      tags = "..."
    
      depends_on = [aws_internet_gateway.this]
    
      lifecycle {
        create_before_destroy = true
      }
    
      allocation_id = "..."
      subnet_id     = "..."
    }
    outputs.tf
    resource "aws_nat_gateway" "that" {    # Best
      count = var.create_public_subnets ? 1 : 0
    }
    
    resource "aws_nat_gateway" "this" {    # Good
      count = length(var.public_subnets) > 0 ? 1 : 0
    }
    outputs.tf
    output "security_group_id" {
      description = "The ID of the security group"
      value       = try(aws_security_group.this[0].id, aws_security_group.name_prefix[0].id, "")
    }
    outputs.tf
    output "this_security_group_id" {
      description = "The ID of the security group"
      value       = element(concat(coalescelist(aws_security_group.this.*.id, aws_security_group.web.*.id), [""]), 0)
    }
    outputs.tf
    output "rds_cluster_instance_endpoints" {
      description = "A list of all cluster instance endpoints"
      value       = aws_rds_cluster_instance.this.*.endpoint
    }

    Structure du code

    Les questions liées à la structure du code Terraform sont de loin les plus fréquentes dans la communauté. Tout le monde a également pensé à la meilleure structure de code pour le projet à un moment donné.

    hashtag
    Comment devrais-je structurer mes configurations Terraform?

    C'est l'une des questions pour lesquelles de nombreuses solutions existent, mais il est très difficile de donner des conseils universels, alors commençons par comprendre à quoi nous avons affaire.

    Quelle est la complexité de votre projet?

    • Nombre de ressources associées

    • Nombre de fournisseurs Terraform (voir la remarque ci-dessous sur les "fournisseurs logiques")

  • À quelle fréquence votre infrastructure change-t-elle ?

    • À partir d'une fois par mois/semaine/jour

    • À continuellement (à chaque fois qu'il y a un nouveau commit)

  • Quelles sont les initiateurs de changement de code? Laissez-vous le serveur CI mettre à jour le référentiel lorsqu'un nouvel artefact est créé ?

    • Seuls les développeurs peuvent pousser vers le référentiel d'infrastructure?

    • Tout le monde peut proposer un changement à n'importe quoi en ouvrant un PR (y compris les tâches automatisées exécutées sur le serveur CI)

  • Quelle plate-forme de déploiement ou service de déploiement utilisez-vous ?

    • AWS CodeDeploy, Kubernetes ou OpenShift nécessitent une approche légèrement différente

  • Comment les environnements sont-ils regroupés ?

    • Par environnement, région, projet

  • circle-info

    Les fournisseurs logiques fonctionnent entièrement dans la logique de Terraform et très souvent n'interagissent avec aucun autre service, nous pouvons donc considérer leur complexité comme O(1). Les fournisseurs logiques les plus courants incluent randomarrow-up-right, localarrow-up-right, terraformarrow-up-right, nullarrow-up-right, timearrow-up-right.

    hashtag
    Initiation à la structuration des configurations Terraform

    Mettre tout le code dans main.tf est une bonne idée lorsque vous débutez ou que vous écrivez un exemple de code. Dans tous les autres cas, il sera préférable d'avoir plusieurs fichiers répartis logiquement comme ceci :

    • main.tf - appelle les modules, les variables locals et les sources de données pour créer toutes les ressources

    • variables.tf - contient les variables qui seront utilisées dans main.tf

    • outputs.tf - contient les sorties des ressources créées dans main.tf

    • versions.tf - contient les exigences de version pour Terraform et les fournisseurs

    terraform.tfvars ne doit être utilisé nulle part sauf composition.

    hashtag
    Comment structurer les configurations Terraform?

    circle-info

    Veuillez vous assurer que vous comprenez les concepts clés - resource module, infrastructure module, et composition, tels qu'ils sont utilisés dans les exemples suivants.

    hashtag
    Recommandations courantes pour structurer le code

    • Il est plus facile et plus rapide de travailler avec un plus petit nombre de ressources

      • terraform plan etterraform apply effectuent tous deux des appels d'API cloud pour vérifier l'état des ressources

      • Si vous avez toute votre infrastructure dans une seule composition, cela peut prendre un certain temps

    • Le surface d'exposition est plus petit avec moins de ressources

      • Isoler les ressources non liées les unes des autres en les plaçant dans des compositions séparées réduit le risque en cas de problème

    • Démarrez votre projet en utilisant l'état distant car :

      • Votre ordinateur portable n'est pas une source fiable pour votre infrastructure

      • Gérer un fichier tfstate file dans un git est cauchemar

    • Adoptez une structure et une convention de cohérentes :

      • Comme tout code procédural, le code Terraform doit être écrit pour permettre d'abord aux gens de le lire. Sa cohérence aidera lorsque des changements se produiront dans une période de six mois

      • Il est possible de déplacer des ressources dans le fichier d'état Terraform, mais cela peut être plus difficile à faire si vous avez une structure et un nom incohérents

    • Gardez les modules de ressources aussi clairs que possible

    • Ne codez pas en dur les valeurs qui peuvent être transmises en tant que variables ou découvertes à l'aide de sources de données

    • Utilisez les sources de données et terraform_remote_state spécifiquement comme colle (liaison) entre les modules d'infrastructure au sein de la composition.

    Dans ce livre, des exemples de projets sont regroupés par complexité - des petites aux très grandes infrastructures. Cette séparation n'est pas stricte, vérifiez donc également les autres structures.

    hashtag
    Orchestration des modules d'infrastructure et compositions

    Avoir une petite infrastructure signifie qu'il y a un petit nombre de dépendances et peu de ressources. Au fur et à mesure que le projet se développe, la nécessité d'enchaîner l'exécution des configurations Terraform, de connecter différents modules d'infrastructure et de transmettre des valeurs au sein d'une composition devient évidente.

    On dénombre au moins 5 groupes distincts de solutions d'orchestration utilisées par les développeurs :

    1. Terraform uniquement. Très simple, les développeurs ne doivent connaître que Terraform pour faire le travail.

    2. Terragrunt. Un pur outil d'orchestration qui peut être utilisé pour orchestrer l'ensemble de l'infrastructure ainsi que pour gérer les dépendances. Terragrunt fonctionne nativement avec des modules d'infrastructure et des compositions, ce qui réduit la duplication de code.

    3. Scripts maison (personnel). Ils sont souvent utilisés comme point de départ vers l'orchestration et avant de découvrir Terragrunt.

    4. Ansible ou les outils d'automatisation généraux similaires. Généralement utilisé lorsque Terraform est adopté après Ansible, ou lorsque l'UI Ansible est activement utilisée.

    5. et autres solutions inspirées de Kubernetes. Parfois, il est logique d'utiliser l'écosystème Kubernetes et d'employer une fonction de boucle de réconciliation pour atteindre l'état souhaité de vos configurations Terraform. Voir la vidéo pour plus d'information.

    Avec cela en tête, ce livre passe en revue les deux premières structures de projet ci-dessus, Terraform uniquement ou Terragrunt.

    Voir des exemples de structure de code pour Terraform et Terragrunt dans le prochain chapitre.

    Plus tard, lorsque les couches d'infrastructure commenceront à se développer dans plusieurs directions (nombre de dépendances ou de ressources), il sera plus facile de garder les choses sous contrôle

    dénomination
    Crossplanearrow-up-right
    Crossplane vs Terraformarrow-up-right

    Exemples de structure de code

    hashtag
    Structures de code Terraform

    circle-info

    Ces exemples montrent un fournisseur AWS, mais la majorité des principes présentés dans les exemples peuvent être appliqués à d'autres fournisseurs de cloud public ainsi qu'à d'autres types de fournisseurs (DNS, DB, Monitoring, etc.)

    Type
    Description
    Préparation

    hashtag
    Structures de code Terragrunt

    Type
    Description
    Préparation

    Non

    petit

    Peu de ressources, pas de dépendances externes. Compte AWS unique. Région unique. Environnement unique

    Oui

    moyen

    Plusieurs comptes et environnements AWS, modules d'infrastructure prêts à l'emploi utilisant Terraform.

    Oui

    grand

    Plusieurs régions, besoin urgent de réduire le copier-coller, modules d'infrastructure personnalisés, utilisation intensive des compositions. Utilisation de Terraform.

    TeC(Travail en Cours)

    Très grand

    moyen

    Plusieurs comptes et environnements AWS, modules d'infrastructure prêts à l'emploi utilisant Terragrunt.

    No

    grand

    Plusieurs régions, besoin urgent de réduire le copier-coller, modules d'infrastructure personnalisés, utilisation intensive des compositions. Utilisation de Terragrunt.

    No

    très grand

    Plusieurs fournisseurs (AWS, GCP, Azure). Déploiements multi-cloud. Utilisation de Terragrunt.

    Non

    Plusieurs fournisseurs (AWS, GCP, Azure). Déploiements multi-cloud. Utilisation de Terraform.