Infrastructure as Code avec Terraform

Infrastructure as Code avec Terraform

Pourquoi l'Infrastructure as Code ?

L'Infrastructure as Code (IaC) est le pilier fondamental du DevOps moderne. Au lieu de configurer manuellement des serveurs via des interfaces graphiques, on décrit l'infrastructure dans des fichiers de configuration versionnés.

Les avantages clés

  • Reproductibilité : un même fichier produit toujours la même infrastructure
  • Versionnement : chaque changement est tracé dans Git
  • Revue de code : les changements d'infra passent par des pull requests
  • Automatisation : déploiement en un seul terraform apply
  • Documentation vivante : le code est la documentation

Terraform : les fondamentaux avancés

Providers et resources

Terraform utilise des providers pour interagir avec les APIs cloud. Chaque provider expose des resources et des data sources.

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

  backend "s3" {
    bucket = "mon-terraform-state"
    key    = "prod/infrastructure.tfstate"
    region = "eu-west-3"
  }
}

provider "aws" {
  region = var.aws_region
}

Modules réutilisables

Un module Terraform encapsule un ensemble de resources dans un composant réutilisable :

module "vpc" {
  source = "./modules/vpc"

  cidr_block         = "10.0.0.0/16"
  availability_zones = ["eu-west-3a", "eu-west-3b", "eu-west-3c"]
  environment        = var.environment

  tags = local.common_tags
}

module "eks_cluster" {
  source = "./modules/eks"

  cluster_name    = "prod-cluster"
  vpc_id          = module.vpc.vpc_id
  subnet_ids      = module.vpc.private_subnet_ids
  node_count      = 3
  instance_type   = "t3.xlarge"

  depends_on = [module.vpc]
}

State management et workspaces

Le state est le fichier qui maintient la correspondance entre votre code et les ressources réelles. En équipe, il doit être stocké dans un backend distant.

# Utilisation des workspaces pour gérer plusieurs environnements
# terraform workspace new staging
# terraform workspace new production

resource "aws_instance" "app" {
  count         = terraform.workspace == "production" ? 3 : 1
  ami           = data.aws_ami.ubuntu.id
  instance_type = terraform.workspace == "production" ? "t3.xlarge" : "t3.medium"

  tags = {
    Environment = terraform.workspace
  }
}

Patterns avancés

Boucles et expressions dynamiques

variable "services" {
  type = map(object({
    port     = number
    replicas = number
    cpu      = string
    memory   = string
  }))

  default = {
    api = { port = 3000, replicas = 3, cpu = "500m", memory = "512Mi" }
    web = { port = 4200, replicas = 2, cpu = "250m", memory = "256Mi" }
    worker = { port = 0, replicas = 1, cpu = "1000m", memory = "1Gi" }
  }
}

resource "kubernetes_deployment" "service" {
  for_each = var.services

  metadata {
    name = each.key
    labels = {
      app = each.key
    }
  }

  spec {
    replicas = each.value.replicas

    selector {
      match_labels = {
        app = each.key
      }
    }

    template {
      spec {
        container {
          name  = each.key
          image = "${var.registry}/${each.key}:${var.image_tag}"

          resources {
            requests = {
              cpu    = each.value.cpu
              memory = each.value.memory
            }
          }
        }
      }
    }
  }
}

Gestion des secrets avec Vault

data "vault_generic_secret" "db_credentials" {
  path = "secret/data/production/database"
}

resource "aws_db_instance" "main" {
  engine         = "postgres"
  engine_version = "15.4"
  instance_class = "db.r6g.xlarge"
  username       = data.vault_generic_secret.db_credentials.data["username"]
  password       = data.vault_generic_secret.db_credentials.data["password"]

  storage_encrypted = true
  multi_az          = true

  backup_retention_period = 30
  deletion_protection     = true
}

Bonnes pratiques

  1. Toujours utiliser un backend distant pour le state (S3, GCS, Azure Blob)
  2. Verrouiller les versions des providers et modules
  3. Séparer les environnements avec des workspaces ou des dossiers distincts
  4. Utiliser terraform plan systématiquement avant apply
  5. Ne jamais stocker de secrets en clair dans les fichiers .tf
  6. Structurer en modules pour réutiliser et tester l'infrastructure
  7. Intégrer Terraform dans le CI/CD avec des plans automatiques sur les PR