Passer au contenu principal

Expertise (Terraform)

GitOps avec Terraform

Le GitOps applique les pratiques Git (branches, pull requests, review, merge) au cycle de vie de l'infrastructure. Toute modification passe par une MR, le plan est visible avant le merge, l'apply est automatique après validation. Le résultat : traçabilité complète, peer review systématique, rollback via revert.

Workflow GitOps basique

  1. Modifier le code HCL sur une branche feature
  2. Ouvrir une Merge Request : le pipeline CI lance un terraform plan et poste le résultat en commentaire
  3. Review humaine du plan
  4. Merge : le pipeline CI lance terraform apply automatiquement

GitLab CI : plan + apply

# .gitlab-ci.yml
variables:
  TF_ROOT: ${CI_PROJECT_DIR}
  TF_STATE_NAME: production

stages: [validate, plan, apply]

.terraform_base:
  image: hashicorp/terraform:1.14
  before_script:
    - terraform init
      -backend-config="bucket=${TF_STATE_BUCKET}"
      -backend-config="key=${TF_STATE_NAME}/terraform.tfstate"

validate:
  extends: .terraform_base
  stage: validate
  script:
    - terraform fmt -check -recursive
    - terraform validate
    - tfsec .

plan:
  extends: .terraform_base
  stage: plan
  script:
    - terraform plan -out=tfplan
    - terraform show -no-color tfplan > plan.txt
  artifacts:
    paths: [tfplan, plan.txt]
    expire_in: 1 week
  rules:
    - if: $CI_MERGE_REQUEST_ID

apply:
  extends: .terraform_base
  stage: apply
  script:
    - terraform apply tfplan
  dependencies: [plan]
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual    # approbation manuelle avant apply en prod

GitHub Actions

# .github/workflows/terraform.yml
name: Terraform
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  terraform:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      pull-requests: write

    steps:
      - uses: actions/checkout@v4

      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: 1.14.0

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::ACCOUNT:role/TerraformRole
          aws-region: eu-west-1

      - run: terraform init

      - name: Plan
        id: plan
        run: terraform plan -no-color -out=tfplan

      - name: Comment PR avec le plan
        uses: actions/github-script@v7
        if: github.event_name == 'pull_request'
        with:
          script: |
            const plan = require('fs').readFileSync('plan.txt', 'utf8')
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `\`\`\`terraform
${plan}
\`\`\``
            })

      - name: Apply
        if: github.ref == 'refs/heads/main'
        run: terraform apply tfplan

Atlantis : GitOps dédié pour Terraform

Atlantis est un serveur open-source spécialisé dans le GitOps Terraform. Il écoute les webhooks Git et gère automatiquement le cycle plan/apply depuis les commentaires de PR.

# Installation via Docker
docker run -p 4141:4141   -e AWS_ACCESS_KEY_ID   -e AWS_SECRET_ACCESS_KEY   -e ATLANTIS_GH_TOKEN   -e ATLANTIS_GH_WEBHOOK_SECRET   ghcr.io/runatlantis/atlantis server     --gh-user=monuser     --repo-allowlist=github.com/monorg/*

Dans une PR, les commentaires déclenchent Atlantis :

  • atlantis plan : lance un plan et poste le résultat
  • atlantis apply : applique le plan approuvé
  • atlantis unlock : libère le verrou si un apply a échoué
# atlantis.yaml — config par dépôt
version: 3
projects:
  - name: prod-vpc
    dir: environments/prod/vpc
    workspace: default
    autoplan:
      when_modified: ["**/*.tf", "../../modules/vpc/**/*.tf"]
  - name: prod-ec2
    dir: environments/prod/ec2
    depends_on: [prod-vpc]