Terraform Intermédiaire

Maîtriser les Modules Terraform et les États pour Produire en Confiance

Dépassez les scripts basiques pour construire une infrastructure scalable et maintenable avec Terraform. Apprenez à structurer vos projets avec des modules réutilisables et gérer les états comme des professionnels DevOps.

Preparetoi.academy 30 min

Architecture Modulaire : Construire pour la Réutilisabilité

Définition
Un module Terraform est un ensemble de fichiers de configuration regroupés dans un répertoire qui encapsule une ou plusieurs ressources. C'est l'unité fondamentale de réutilisabilité et d'abstraction en Terraform, permettant de créer des composants infrastructure standardisés et versionables.

Explication détaillée
Les modules représentent un changement de paradigme par rapport aux configurations plates. Ils permettent de transformer du code Terraform en composants réutilisables, similaires à des fonctions ou des classes en programmation traditionnelle. Chaque module expose des variables d'entrée (inputs) et produit des valeurs de sortie (outputs), créant une interface claire. Cette approche facilite la collaboration d'équipes, réduit la duplication de code et permet de maintenir une cohérence infrastructure. Les modules peuvent être organisés localement, stockés dans des registres privés ou publics (Terraform Registry), créant ainsi un écosystème d'infrastructure réutilisable au niveau organisationnel.

# Structure recommandée pour un module
# modules/vpc/main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

resource "aws_vpc" "main" {
  cidr_block           = var.cidr_block
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name        = var.vpc_name
    Environment = var.environment
    ManagedBy   = "Terraform"
  }
}

resource "aws_subnet" "private" {
  count             = length(var.private_subnets)
  vpc_id            = aws_vpc.main.id
  cidr_block        = var.private_subnets[count.index]
  availability_zone = data.aws_availability_zones.available.names[count.index % length(data.aws_availability_zones.available.names)]

  tags = {
    Name = "${var.vpc_name}-private-${count.index + 1}"
  }
}

# modules/vpc/variables.tf
variable "cidr_block" {
  description = "CIDR block pour le VPC"
  type        = string
  validation {
    condition     = can(cidrhost(var.cidr_block, 0))
    error_message = "Le CIDR block doit être valide."
  }
}

variable "vpc_name" {
  description = "Nom du VPC"
  type        = string
}

variable "private_subnets" {
  description = "Liste des CIDR blocks pour les subnets privés"
  type        = list(string)
}

variable "environment" {
  description = "Environnement de déploiement"
  type        = string
  default     = "production"
}

# modules/vpc/outputs.tf
output "vpc_id" {
  value       = aws_vpc.main.id
  description = "ID du VPC créé"
}

output "private_subnet_ids" {
  value       = aws_subnet.private[*].id
  description = "Liste des IDs des subnets privés"
}

# main.tf (root module)
module "vpc" {
  source = "./modules/vpc"

  cidr_block     = "10.0.0.0/16"
  vpc_name       = "production-vpc"
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  environment    = "production"
}

output "vpc_details" {
  value = {
    vpc_id  = module.vpc.vpc_id
    subnets = module.vpc.private_subnet_ids
  }
}
Aspect Approche Plate Approche Modulaire
Réutilisabilité Copie-coller du code Import du module
Maintenance Modifications multiples Modification centralisée
Testabilité Difficile à isoler Facile à tester
Versioning Complexe Natif avec registres
Collaboration Risque de conflits Interfaces claires
Documentation À faire manuellement Automatisable

Astuce professionnelle
Utilisez des conventions de nommage strictes pour vos modules : terraform-<provider>-<ressource-principale>. Par exemple, terraform-aws-vpc-multi-az. Cela facilite la recherche dans les registres publics et crée une cohérence organisationnelle. Documentez toujours vos modules avec un README.md complet incluant les exemples d'utilisation.

⚠️ Attention
Ne créez pas de modules trop génériques qui essaient de couvrir tous les cas d'usage possibles. Cela rend le code complexe et difficile à maintenir. Préférez des modules spécialisés et composables. Évitez aussi de hardcoder des valeurs sensibles ; utilisez toujours des variables avec validation.


Gestion des États : Fondation de la Cohérence Infrastructure

Définition
L'état Terraform est un fichier (généralement terraform.tfstate) qui enregistre l'inventaire exact des ressources gérées et leurs attributs actuels. C'est une cartographie bidirectionnelle entre votre configuration déclarative et les ressources réelles dans le cloud, essentielle pour que Terraform comprenne les changements à appliquer.

Explication détaillée
Terraform fonctionne selon le principe d'état : avant toute action, il consulte l'état pour connaître l'infrastructure existante, la compare avec la configuration souhaitée, puis calcule les opérations nécessaires. Sans cet état, Terraform ne pourrait pas distinguer une ressource créée manuellement d'une créée par Terraform, ni déterminer quels changements appliquer. En environnement professionnel, l'état doit être stocké à distance (backend distant) plutôt que localement, permettant à plusieurs membres d'équipe d'accéder à la même source de vérité. Le verrouillage d'état évite les modifications simultanées concurrentes qui corrompraient l'infrastructure.

# Configuration d'un backend S3 avec chiffrement et verrouillage
# terraform/backend.tf

terraform {
  backend "s3" {
    bucket            = "mon-organisation-terraform-state"
    key               = "production/terraform.tfstate"
    region            = "eu-west-1"
    encrypt           = true
    dynamodb_table    = "terraform-locks"
    workspace_key_prefix = "env"
  }
}

# Script d'initialisation sécurisée du backend
# scripts/init-backend.sh

#!/bin/bash
set -euo pipefail

BUCKET_NAME="mon-organisation-terraform-state"
REGION="eu-west-1"
DYNAMODB_TABLE="terraform-locks"

# Créer le bucket S3 avec versioning
aws s3api create-bucket \
  --bucket $BUCKET_NAME \
  --region $REGION \
  --create-bucket-configuration LocationConstraint=$REGION || true

# Activer le versioning
aws s3api put-bucket-versioning \
  --bucket $BUCKET_NAME \
  --versioning-configuration Status=Enabled

# Bloquer l'accès public
aws s3api put-public-access-block \
  --bucket $BUCKET_NAME \
  --public-access-block-configuration \
  "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"

# Activer le chiffrement côté serveur
aws s3api put-bucket-encryption \
  --bucket $BUCKET_NAME \
  --server-side-encryption-configuration '{
    "Rules": [{
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "AES256"
      }
    }]
  }'

# Créer la table DynamoDB pour les verrous
aws dynamodb create-table \
  --table-name $DYNAMODB_TABLE \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST \
  --region $REGION || true

# Exemple de commandes de gestion d'état
terraform state list
terraform state show aws_instance.web
terraform state rm aws_instance.deprecated
terraform state pull > state-backup.json

# Inspection sécurisée de l'état
# IMPORTANT : Ne pas commiter terraform.tfstate en Git !

# .gitignore
terraform.tfstate
terraform.tfstate.*
.terraform/
.terraform.lock.hcl
*.tfvars
!example.tfvars
Aspect État Local Backend Distant (S3) Backend avec Terraform Cloud
Accès en Équipe ❌ Impossible ✅ Oui (avec verrous) ✅ Oui (natif)
Chiffrement Manuel ✅ S3-side encryption ✅ Chiffré automatiquement
Versioning ❌ Non ✅ S3 versioning ✅ Historique complet
Audit ❌ Aucun ✅ Via CloudTrail ✅ Dashboard natif
Coût Gratuit ~ 1$/mois ~ 20$/mois
Simplicité ✅ Maximal Moyen ✅ Maximal

Astuce professionnelle
Implémentez un système de sauvegarde d'état automatisé. Chaque jour, extractez votre état avec terraform state pull et stockez-le dans un bucket S3 avec versioning. Cela vous permet de restaurer une version antérieure en cas de problème. Utilisez des tags Git pour marquer les versions stables de votre infrastructure.

⚠️ Attention
Jamais ne modifiez manuellement terraform.tfstate ou ne le committez dans Git. C'est un fichier hautement sensible contenant potentiellement des secrets. Si vous décelez une fuite, régénérez immédiatement les ressources sensibles. Utilisez toujours terraform state (non terraform state rm à la légère) pour les modifications d'état.


Sécurité et Gestion des Secrets : Protection de l'Infrastructure

Définition
La sécurité en Terraform comprend la protection des secrets (mots de passe, clés API, tokens), la validation des entrées, le chiffrement des données sensibles et l'audit des actions infrastructure. C'est l'ensemble des pratiques qui garantissent que votre infrastructure n'expose pas d'informations sensibles et respecte les principes du moindre privilège.

Explication détaillée
Les secrets dans Terraform constituent un défi majeur car ils doivent transiter par plusieurs couches : fichiers de configuration, variables, états, et logs. Une mauvaise gestion expose rapidement des credentials critiques. Les bonnes pratiques incluent l'utilisation de variables sensibles marquées avec sensitive = true, l'intégration avec des gestionnaires de secrets externes (AWS Secrets Manager, HashiCorp Vault), et l'exclusion systématique de fichiers contenant des secrets du contrôle de version. La validation des variables avec des validation blocks prévient les configurations dangereuses avant le déploiement.

# Exemple complet de gestion sécurisée des secrets
# terraform/variables.tf

variable "database_password" {
  description = "Mot de passe de la base de données"
  type        = string
  sensitive   = true
  
  validation {
    condition     = length(var.database_password) >= 16 && can(regex("[A-Z]", var.database_password)) && can(regex("[0-9]", var.database_password))
    error_message = "Le mot de passe doit contenir au minimum 16 caractères, une majuscule et un chiffre."
  }
}

variable "api_key" {
  description = "Clé API pour service externe"
  type        = string
  sensitive   = true
  default     = "" # Ne jamais mettre une vraie clé en défaut
}

variable "enable_encryption" {
  description = "Activer le chiffrement des données en transit et au repos"
  type        = bool
  default     = true
}

# terraform/main.tf - Récupération sécurisée des secrets via AWS Secrets Manager

data "aws_secretsmanager_secret" "db_credentials" {
  name = "prod/database/master-password"
}

data "aws_secretsmanager_secret_version" "db_credentials" {
  secret_id = data.aws_secretsmanager_secret.db_credentials.id
}

locals {
  db_credentials = jsondecode(data.aws_secretsmanager_secret_version.db_credentials.secret_string)
}

# Créer une ressource RDS avec le mot de passe du secret
resource "aws_db_instance" "main" {
  allocated_storage    = 100
  db_name              = "mydb"
  engine               = "mysql"
  engine_version       = "8.0"
  instance_class       = "db.t4g.medium"
  username             = "admin"
  password             = local.db_credentials.password
  skip_final_snapshot  = false
  storage_encrypted    = var.enable_encryption
  
  # Ne jamais exposer le mot de passe dans les outputs !
  depends_on = [data.aws_secretsmanager_secret_version.db_credentials]

  tags = {
    Name = "production-database"
  }
}

# Utiliser des fichiers .tfvars non committés pour les variables sensibles
# terraform.tfvars (à ajouter à .gitignore)
database_password = "GeneratedSecurePassword123!"
api_key           = "sk-1234567890abcdef"

# Ou utiliser des variables d'environnement
# export TF_VAR_database_password="..."
# export TF_VAR_api_key="..."

# Masquer les secrets dans les outputs
output "database_endpoint" {
  value       = aws_db_instance.main.endpoint
  description = "Endpoint de la base de données"
}

# Ne JAMAIS faire ceci :
# output "database_password" {
#   value = aws_db_instance.main.password
# }

# Utiliser des data sources pour récupérer les secrets
data "aws_ssm_parameter" "api_key" {
  name = "/prod/api/key"
}

# Stratégie avec Terraform Cloud / Enterprise
# Variables sensibles marquées comme "Sensitive" dans l'interface Terraform Cloud
# Elles sont chiffrées en transit et au repos, jamais affichées dans les logs
Méthode Sécurité Scalabilité Audit Complexité
Variables en dur 🔴 Critique ❌ Pauvre ❌ Aucun ✅ Simple
.tfvars local 🟡 Moyen ❌ Non 🟡 Git Moyen
Variables d'env 🟡 Moyen ✅ Bon 🟡 Partiel Moyen
AWS Secrets Manager 🟢 Excellent ✅ Excellent ✅ CloudTrail 🟠 Complexe
HashiCorp Vault 🟢 Excellent ✅ Excellent ✅ Audit natif 🔴 Complexe
Terraform Cloud 🟢 Excellent ✅ Excellent ✅ Natif ✅ Simple

Astuce professionnelle
Implémentez une couche d'abstraction avec un module secrets qui encapsule la logique de récupération des credentials. Cela centralise la gestion et facilite les migrations entre fournisseurs de secrets. Utilisez les commentaires # tfsec:ignore=aws123 judicieusement seulement après analyse de risque documentée.

⚠️ Attention
Ne jamais utiliser terraform show ou terraform output pour afficher les variables marquées sensitive = true en production. Vérifiez régulièrement vos fichiers .tfstate dans les buckets S3 pour détecter des fuites accidentelles. Configurez des règles CloudTrail pour auditer l'accès aux Secrets Manager.


Workflows et Collaboration : Orchestrer les Déploiements en Équipe

Définition
Un workflow Terraform professionnel est un ensemble de processus orchestrés (plan, validation, test, approbation, apply) exécutés dans un environnement contrôlé pour garantir la qualité, la sécurité et la traçabilité des changements infrastructure. C'est l'essence du GitOps appliqué à l'infrastructure.

Explication détaillée
Le workflow GitOps place Git comme source de vérité unique : chaque changement infrastructure passe par une merge request, subit une validation automatisée (linting, coût estimation, plan), est revu par les pairs, puis fusionné et déployé. Cette approche crée une traçabilité complète, permet de revenir à tout moment à une version antérieure, et distribue le contrôle d'accès selon les permissions Git. Des outils comme Terraform Cloud, GitLab CI/CD ou GitHub Actions automatisent ce pipeline. Le locking d'état prévient les déploiements concurrents qui pourraient corrompre l'infrastructure.

# Exemple de configuration GitLab CI/CD pour un workflow Terraform
# .gitlab-ci.yml

variables:
  TF_ROOT: ${CI_PROJECT_DIR}/terraform
  TF_VERSION: "1.6.0"
  AWS_DEFAULT_REGION: "eu-west-1"

stages:
  - validate
  - test
  - plan
  - cost-estimate
  - apply

# Bloc de configuration commune
.terraform_base:
  image: hashicorp/terraform:${TF_VERSION}
  before_script:
    - cd ${TF_ROOT}
    - terraform init
  cache:
    paths:
      - ${TF_ROOT}/.terraform/
    key: "${TF_VERSION}-${CI_COMMIT_REF_SLUG}"

# Stage 1 : Validation de la syntaxe et du format
terraform_validate:
  extends: .terraform_base
  stage: validate
  script:
    - terraform validate
    - terraform fmt -check -recursive .
  only:
    - merge_requests
    - main

# Stage 2 : Tests automatisés avec tfsec
terraform_security_scan:
  image: aquasec/tfsec-ci:latest
  stage: test
  script:
    - tfsec ${TF_ROOT} --format json --out tfsec-report.json || exit 0
  artifacts:
    reports:
      sast: tfsec-report.json
  only:
    - merge_requests
    - main

# Stage 3 : Planification des changements
terraform_plan:
  extends: .terraform_base
  stage: plan
  script:
    - terraform plan -out=plan.tfplan -json > plan.json
  artifacts:
    paths:
      - ${TF_ROOT}/plan.tfplan
      - ${TF_ROOT}/plan.json
    expire_in: 1 day
  only:
    - merge_requests
    - main

# Stage 4 : Estimation des coûts avec Infracost
terraform_cost_estimate:
  image: infracost/infracost:latest
  stage: cost-estimate
  script:
    - cd ${TF_ROOT}
    - infracost breakdown --path . --format table
  only:
    - merge_requests

# Stage 5 : Application automatique sur main uniquement
terraform_apply:
  extends: .terraform_base
  stage: apply
  script:
    - terraform apply plan.tfplan
  dependencies:
    - terraform_plan
  only:
    - main
  environment:
    name: production
    action: prepare

# Script de validation personnalisé
# scripts/validate.sh

#!/bin/bash
set -euo pipefail

echo "=== Validations Terraform ==="

# 1. Syntaxe
echo "[1/5] Vérification de la syntaxe..."
terraform validate

# 2. Formatage
echo "[2/5] Vérification du formatage..."
terraform fmt -check -recursive .

# 3. Détection des secrets
echo "[3/5] Scan de sécurité des secrets..."
git diff --cached | grep -E '(password|secret|key|token)' && echo "❌ Secrets détectés !" && exit 1 || echo "✅ Aucun secret détecté"

# 4. Analyse de coût
echo "[4/5] Analyse du coût estimé..."
terraform plan -json | jq '.resource_changes[] | select(.change.actions != ["no-op"]) | {address, actions}' || true

# 5. État verrouillé
echo "[5/5] Vérification du verrouillage..."
aws dynamodb scan --table-name terraform-locks --region eu-west-1

echo "✅ Toutes les validations sont passées !"
Élément Description Outil Recommandé Fréquence
Format Code Standardisation indentation/nommage terraform fmt À chaque commit
Validation Syntaxe Vérification config valides terraform validate Avant commit
Scan Sécurité Détection misconfigurations tfsec, checkov À chaque MR
Estimation Coût Prédiction impact budget infracost Avant apply
Analyse Plan Revue des changements tfplannery, infragrep À chaque apply
Documentation Génération auto doc variables terraform-docs À chaque release

Astuce professionnelle
Créez un template .gitlab-merge-request-template.md qui impose une checklist : "Plan Terraform généré ?", "Coûts estimés < seuil ?", "Tests de sécurité passés ?". Cela crée une discipline de revue et documente les décisions. Associez également un bot qui commente automatiquement les MR avec le résumé du terraform plan.

⚠️ Attention
Ne donnez jamais accès direct à terraform apply au-delà d'une poignée d'administrateurs. Utilisez des approbations multiples pour les changements critiques (bases de données, sécurité). Configurez un webhook pour notifier slack/Teams de chaque déploiement avec traçabilité complète.


Patterns Avancés et Optimisations Professionnelles

Définition
Les patterns avancés Terraform incluent les techniques de composition modulaire, les stratégies multi-environnement, le templating dynamique, et les optimisations de performance pour gérer des infrastructures complexes à large échelle. Ce sont les pratiques que les équipes DevOps matures utilisent quotidiennement.

Explication détaillée
À mesure que l'infrastructure grandit, les approches basiques deviennent insuffisantes. Les patterns avancés répondent aux défis réels : comment gérer dev/staging/prod avec DRY (Don't Repeat Yourself), comment composer des modules hétérogènes, comment valider les architectures avant déploiement, comment optimiser les temps de planification sur des milliers de ressources. La stratégie workspaces vs dossiers séparés impacte la gestion d'état et la collaboration. Les for_each et for expressions permettent de générer dynamiquement des ressources réduisant le copier-coller. Les locals organisent la logique complexe.

# Pattern avancé : Multi-environnement avec DRY
# Structure de dossiers

# terraform/
# ├── environments/
# │   ├── shared/        # Ressources communes (VPC, IAM)
# │   ├── dev/
# │   │   ├── terraform.tfvars
# │   │   └── main.tf
# │   ├── staging/
# │   └── production/
# ├── modules/
# │   ├── vpc/
# │   ├── eks/
# │   ├── rds/
# │   └── monitoring/
# └── globals.tf

# terraform/environments/production/main.tf
terraform {
  required_version = ">= 1.5"
  
  backend "s3" {
    bucket            = "company-tfstate"
    key               = "production/terraform.tfstate"
    region            = "eu-west-1"
    encrypt           = true
    dynamodb_table    = "terraform-locks"
  }

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region

  default_tags {
    tags = {
      Environment = var.environment
      Project     = var.project_name
      ManagedBy   = "Terraform"
      CostCenter  = var.cost_center
    }
  }
}

# Récupérer la configuration d'environnement
locals {
  env = yamldecode(file("${path.module}/config.yaml"))
}

# Créer des ressources EKS multi-cluster avec for_each
module "eks_clusters" {
  for_each = local.env.eks_clusters

  source = "../../modules/eks"

  cluster_name           = each.key
  cluster_version        = each.value.version
  instance_types         = each.value.instance_types
  desired_size           = each.value.desired_size
  max_size               = each.value.max_size
  min_size               = each.value.min_size
  enable_monitoring      = var.enable_monitoring
  
  depends_on = [module.vpc]
}

# Pattern : Composition dynamique avec locals
locals {
  # Configuration basée sur l'environnement
  instance_type_map = {
    dev         = "t3.micro"
    staging     = "t3.small"
    production  = "m5.large"
  }
  
  instance_type = local.instance_type_map[var.environment]
  
  # Étiquettes standardisées
  common_tags = {
    Environment = var.environment
    CreatedAt   = timestamp()
    CreatedBy   = "Terraform"
  }

  # Configuration réseau basée sur environnement
  network_config = {
    dev = {
      vpc_cidr              = "10.0.0.0/16"
      private_subnet_count  = 1
      public_subnet_count   = 1
      nat_gateway_count     = 0
      enable_vpc_flow_logs  = false
    }
    production = {
      vpc_cidr              = "10.0.0.0/16"
      private_subnet_count  = 3
      public_subnet_count   = 3
      nat_gateway_count     = 3
      enable_vpc_flow_logs  = true
    }
  }
}

# Générer dynamiquement les subnets privés
resource "aws_subnet" "private" {
  for_each = toset([
    for i in range(local.network_config[var.environment].private_subnet_count) : 
    "subnet-private-${i + 1}"
  ])

  vpc_id            = module.vpc.vpc_id
  cidr_block        = cidrsubnet(var.vpc_cidr, 4, index(keys(aws_subnet.private), each.key))
  availability_zone = data.aws_availability_zones.available.names[index(keys(aws_subnet.private), each.key) % length(data.aws_availability_zones.available.names)]

  tags = merge(
    local.common_tags,
    {
      Name = each.value
    }
  )
}

# terraform/environments/production/terraform.tfvars
aws_region           = "eu-west-1"
environment          = "production"
project_name         = "MyProject"
cost_center          = "ENGINEERING"
enable_monitoring    = true
instance_type        = "m5.large"
vpc_cidr             = "10.0.0.0/16"
enable_backup        = true
backup_retention_days = 30

# terraform/environments/production/config.yaml
eks_clusters:
  primary:
    version: "1.28"
    instance_types: ["t3.medium", "t3.large"]
    desired_size: 5
    max_size: 10
    min_size: 3
  secondary:
    version: "1.28"
    instance_types: ["m5.large"]
    desired_size: 3
    max_size: 6
    min_size: 2

# Pattern : Validation d'architecture avec tflint
# .tflint.hcl
plugin "aws" {
  enabled = true
  version = "0.26.0"
  source  = "github.com/terraform-linters/tflint-ruleset-aws"

  deep_check = true
}

rule "aws_instance_invalid_type" {
  enabled = true
}

rule "terraform_required_version" {
  enabled = true
}

rule "terraform_required_providers" {
  enabled = true
}

# terraform/scripts/comprehensive-check.sh
#!/bin/bash
set -euo pipefail

echo "=== Vérifications Terraform Complètes ==="

# 1. Linting
echo "[1/4] TFLint..."
tflint --recursive --format compact

# 2. Sécurité avec Checkov
echo "[2/4] Checkov..."
checkov -d . --framework terraform --compact

# 3. Coût
echo "[3/4] Infracost..."
infracost breakdown --path . --format table

# 4. Documentation
echo "[4/4] Terraform Docs..."
terraform-docs markdown table . > README.md

echo "✅ Tous les checks sont passés !"
Pattern Cas d'Usage Avantages Inconvénients
Workspaces Dev/staging/prod État séparé, même backend État fragile, facile confusion
Dossiers Multi-environnement États séparés, isolation Code dupliqué potentiel
for_each Ressources multiples similaires DRY, dynamique Indexation fragile
data sources Références cross-stack Découplage, flexibilité Dépendances implicites
Composition modules Configurations complexes Réutilisabilité Overhead cognitif
YAML config Environment-driven Séparation données/code Plus d'outils

Astuce professionnelle
Créez un module terraform-aws-environment

Un guide complet pour maîtriser le support informatique à tous les niveaux
Support IT Moderne

Développez des compétences concrètes en Cloud, cybersécurité, IA et automatisation avec une approche claire et orientée terrain.

Découvrir le livre →
Dans Infrastructure as Code
Voir tout →
Accédez à des centaines d'examens QCM — Découvrir les offres Premium