Infrastructure as Code avec Terraform : de la gestion manuelle du cloud à la gestion automatisée du cloud

Gérez l'infrastructure cloud avec Terraform. Couvre la syntaxe HCL, les modules, la gestion des états, l'intégration CI/CD et les stratégies de déploiement multi-environnements.

E
ECOSIRE Research and Development Team
|16 mars 20267 min de lecture1.6k Mots|

Infrastructure as Code avec Terraform : de la gestion manuelle à la gestion automatisée du cloud

Les organisations utilisant l'Infrastructure as Code (IaC) fournissent des environnements 90 % plus rapidement et subissent 60 % moins de pannes liées à la configuration que celles qui gèrent l'infrastructure manuellement. Terraform est devenu l'outil IaC dominant, avec plus de 3 000 fournisseurs prenant en charge toutes les principales plates-formes cloud et services SaaS.

Ce guide couvre l'utilisation pratique de Terraform pour les applications Web, les systèmes ERP et les plates-formes de commerce électronique, de la première définition de ressources aux déploiements multi-environnements de production.

Points clés à retenir

  • Terraform rend les modifications d'infrastructure révisables, testables et réversibles grâce au contrôle de version
  • La gestion de l'état à distance évite les conflits lorsque plusieurs ingénieurs modifient l'infrastructure
  • Les modules encapsulent des modèles réutilisables, réduisant la configuration de centaines de lignes à quelques paramètres
  • L'intégration Terraform Cloud ou CI/CD applique la discipline de planification avant application pour des changements sûrs

Pourquoi Terraform pour les PME

Le problème de l'infrastructure manuelle

Sans IaC, vos connaissances en infrastructure résident dans :

  • Chemins de clics de la console AWS que personne n'a documentés
  • Des commandes SSH exécutées il y a des mois et dont personne ne se souvient
  • Fichiers de configuration édités directement sur les serveurs
  • Le modèle mental d'un ingénieur sur "le fonctionnement du réseau"

Avec Terraform, votre infrastructure réside dans Git. Chaque changement est une pull request. Chaque déploiement est reproductible. Chaque ingénieur peut comprendre la situation dans son ensemble.

Concepts de base

ConceptsDescriptif
FournisseurPlugin qui s'interface avec une plateforme cloud (AWS, GCP, Azure, Cloudflare)
RessourceUn seul composant d'infrastructure (instance EC2, base de données RDS, bucket S3)
Source de donnéesRéférence en lecture seule à l'infrastructure existante
VariablesParamètre d'entrée pour configuration réutilisable
SortieValeur exportée à partir d'une configuration Terraform
ÉtatEnregistrement de ce que Terraform gère et de ses attributs actuels
ModuleGroupe de ressources réutilisable avec une interface définie

Première configuration de Terraform

AWS VPC et EC2 pour une application Web

# providers.tf
terraform {
  required_version = ">= 1.7"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    bucket = "ecosire-terraform-state"
    key    = "production/terraform.tfstate"
    region = "us-east-1"
    encrypt = true
    dynamodb_table = "terraform-locks"
  }
}

provider "aws" {
  region = var.aws_region
}

# variables.tf
variable "aws_region" {
  type    = string
  default = "us-east-1"
}

variable "environment" {
  type    = string
  default = "production"
}

variable "instance_type" {
  type    = string
  default = "t3.large"
}

# main.tf
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name        = "${var.environment}-vpc"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

resource "aws_subnet" "public" {
  count             = 2
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.${count.index + 1}.0/24"
  availability_zone = data.aws_availability_zones.available.names[count.index]

  map_public_ip_on_launch = true

  tags = {
    Name = "${var.environment}-public-${count.index + 1}"
  }
}

resource "aws_instance" "app" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = var.instance_type
  subnet_id     = aws_subnet.public[0].id

  vpc_security_group_ids = [aws_security_group.app.id]
  key_name               = aws_key_pair.deploy.key_name

  root_block_device {
    volume_size = 50
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-app"
    Environment = var.environment
  }
}

resource "aws_db_instance" "postgres" {
  identifier     = "${var.environment}-db"
  engine         = "postgres"
  engine_version = "17"
  instance_class = "db.t3.medium"

  allocated_storage     = 50
  max_allocated_storage = 200
  storage_encrypted     = true

  db_name  = "ecosire"
  username = "app"
  password = var.db_password

  vpc_security_group_ids = [aws_security_group.db.id]
  db_subnet_group_name   = aws_db_subnet_group.main.name

  backup_retention_period = 7
  backup_window           = "03:00-04:00"
  maintenance_window      = "sun:04:00-sun:05:00"

  skip_final_snapshot = false
  final_snapshot_identifier = "${var.environment}-db-final"

  tags = {
    Environment = var.environment
  }
}

Modules pour une infrastructure réutilisable

Création d'un module d'application Web

# modules/web-app/main.tf
variable "name" {
  type = string
}

variable "environment" {
  type = string
}

variable "instance_type" {
  type    = string
  default = "t3.medium"
}

variable "vpc_id" {
  type = string
}

variable "subnet_ids" {
  type = list(string)
}

resource "aws_lb" "app" {
  name               = "${var.name}-${var.environment}-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = var.subnet_ids
}

resource "aws_lb_target_group" "app" {
  name     = "${var.name}-${var.environment}-tg"
  port     = 3000
  protocol = "HTTP"
  vpc_id   = var.vpc_id

  health_check {
    path                = "/health"
    healthy_threshold   = 2
    unhealthy_threshold = 3
    interval            = 30
  }
}

resource "aws_autoscaling_group" "app" {
  name                = "${var.name}-${var.environment}-asg"
  min_size            = 2
  max_size            = 10
  desired_capacity    = 2
  vpc_zone_identifier = var.subnet_ids
  target_group_arns   = [aws_lb_target_group.app.arn]

  launch_template {
    id      = aws_launch_template.app.id
    version = "$Latest"
  }

  tag {
    key                 = "Name"
    value               = "${var.name}-${var.environment}"
    propagate_at_launch = true
  }
}

output "alb_dns_name" {
  value = aws_lb.app.dns_name
}

Utilisation du module

# environments/production/main.tf
module "web" {
  source = "../../modules/web-app"

  name          = "ecosire-web"
  environment   = "production"
  instance_type = "t3.large"
  vpc_id        = module.network.vpc_id
  subnet_ids    = module.network.public_subnet_ids
}

module "api" {
  source = "../../modules/web-app"

  name          = "ecosire-api"
  environment   = "production"
  instance_type = "t3.large"
  vpc_id        = module.network.vpc_id
  subnet_ids    = module.network.public_subnet_ids
}

Gestion de l'état

État distant avec S3

# Bootstrap: create the state bucket and DynamoDB table manually or with a separate config
resource "aws_s3_bucket" "terraform_state" {
  bucket = "ecosire-terraform-state"

  lifecycle {
    prevent_destroy = true
  }
}

resource "aws_s3_bucket_versioning" "terraform_state" {
  bucket = aws_s3_bucket.terraform_state.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_dynamodb_table" "terraform_locks" {
  name         = "terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

Le verrouillage de l'état via DynamoDB empêche deux ingénieurs d'exécuter terraform apply simultanément, ce qui pourrait corrompre l'état.

Sécurité des fichiers d'état

Le fichier d'état Terraform contient des informations sensibles, notamment des mots de passe de base de données, des clés API et des ID de ressources. Protégez-le :

  • Chiffrement au repos : gestion des versions du bucket S3 + chiffrement côté serveur
  • Chiffrer en transit : HTTPS uniquement pour l'accès à l'état
  • Restreindre l'accès : politiques IAM limitant les personnes pouvant lire/écrire l'état
  • Ne jamais s'engager sur Git : les fichiers d'état ne doivent jamais être sous contrôle de version
  • Activer la gestion des versions : la gestion des versions S3 permet la récupération à partir d'un état corrompu

Intégration CI/CD

Pipeline Terraform d'actions GitHub

name: Terraform
on:
  pull_request:
    paths: ['infrastructure/**']
  push:
    branches: [main]
    paths: ['infrastructure/**']

jobs:
  plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3

      - name: Terraform Init
        run: terraform init
        working-directory: infrastructure/environments/production

      - name: Terraform Plan
        run: terraform plan -out=tfplan
        working-directory: infrastructure/environments/production

      - name: Comment PR with plan
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const plan = require('fs').readFileSync('infrastructure/environments/production/tfplan.txt', 'utf8');
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## Terraform Plan\n\`\`\`\n${plan}\n\`\`\``
            });

  apply:
    needs: plan
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3

      - name: Terraform Apply
        run: terraform apply -auto-approve
        working-directory: infrastructure/environments/production

Stratégie multi-environnements

EnvironnementObjectifTailles des instancesObjectif de coût
DéveloppementTest des fonctionnalitést3.micro / t3.petit<100$/mois
Mise en scèneValidation pré-productionProduction de miroirs (plus petits)~30% de la production
FabricationTrafic en directAdapté à la chargeOptimisé

Utilisez des espaces de travail Terraform ou des répertoires distincts par environnement :

infrastructure/
  modules/
    web-app/
    database/
    network/
  environments/
    development/
      main.tf
      terraform.tfvars
    staging/
      main.tf
      terraform.tfvars
    production/
      main.tf
      terraform.tfvars

Questions fréquemment posées

Terraform ou Pulumi --- que devons-nous choisir ?

Terraform si votre équipe comprend des ingénieurs d'exploitation qui préfèrent la configuration déclarative. Pulumi si votre équipe est composée de nombreux développeurs et préfère écrire une infrastructure en TypeScript ou Python. Terraform dispose d'un écosystème plus vaste et de plus de modules communautaires. Pulumi a une courbe d'apprentissage initiale plus raide mais est plus flexible pour la logique complexe.

Comment importer l'infrastructure existante dans Terraform ?

Utilisez terraform import pour placer les ressources existantes sous gestion Terraform. Par exemple : terraform import aws_instance.app i-1234567890abcdef0. Après l'importation, écrivez la configuration correspondante. Terraform 1.5+ prend en charge les blocs d'importation dans les fichiers de configuration pour les importations groupées.

Comment gérons-nous les secrets dans Terraform ?

Ne confiez jamais de secrets aux fichiers Terraform. Utilisez terraform.tfvars (exclu de Git), des variables d'environnement (TF_VAR_db_password) ou un gestionnaire de secrets (AWS Secrets Manager, HashiCorp Vault). Marquez les variables sensibles avec sensitive = true pour éviter qu'elles n'apparaissent dans la sortie du plan.

Quel est le coût de la gestion de Terraform ?

Terraform lui-même est gratuit et open source. Terraform Cloud propose un niveau gratuit pour un maximum de 5 utilisateurs avec état à distance et planification/application. Le coût principal est la courbe d'apprentissage (20 à 40 heures pour un ingénieur expérimenté) et la maintenance continue (2 à 4 heures par mois). Ceci est compensé par le temps gagné sur la gestion manuelle de l’infrastructure.


Ce qui vient ensuite

Terraform constitue la base d'une infrastructure automatisée. Combinez-le avec des pipelines CI/CD pour un déploiement automatisé, de la surveillance pour une visibilité opérationnelle et de la reprise après sinistre pour la résilience.

Contactez ECOSIRE pour obtenir des conseils en automatisation de l'infrastructure, ou explorez notre guide DevOps pour les petites entreprises pour obtenir la feuille de route complète.


Publié par ECOSIRE – aider les entreprises à automatiser l'infrastructure cloud.

E

Rédigé par

ECOSIRE Research and Development Team

Création de produits numériques de niveau entreprise chez ECOSIRE. Partage d'analyses sur les intégrations Odoo, l'automatisation e-commerce et les solutions d'entreprise propulsées par l'IA.

Discutez sur WhatsApp