Coûts CloudFinOpsGCPAWSTerraformIntermédiaire

Le guide 2026 d'optimisation des coûts Cloud

Jerry RajaonarivoMis à jour le 30 sept. 20269 min de lecture

Ce guide déroule une séquence d'audit des coûts cloud qui traite le coût comme un problème d'architecture plutôt qu'un problème de facturation : établir une base de coûts, redimensionner le calcul, s'engager sur des remises, hiérarchiser le stockage, nettoyer les ressources orphelines, et ancrer ces économies avec le GitOps.

1. Établir une base de coûts réellement fiable

Avant de toucher la moindre ressource, taguez tout et construisez une base répartie par :

  • Équipe / service : qui est responsable de la dépense
  • Environnement : production vs. staging vs. dev
  • Type de ressource : calcul, stockage, sortie réseau, services managés

Si votre export de facturation n'est pas interrogeable dans BigQuery (GCP) ou Athena/Cost Explorer (AWS) avec une granularité par tag, commencez par là. Vous ne pouvez pas optimiser ce que vous ne pouvez pas attribuer.

Sur GCP, l'export de facturation standard atterrit dans une table nommée d'après l'ID de votre compte de facturation. Interrogez le coût net. La colonne cost seule ignore les crédits (remises automatiques proportionnelles à l'utilisation, remises d'engagement basées sur les ressources, promotions, niveau gratuit), et surestime donc ce que vous payez. Je garde aussi la dépense sans label comme une ligne à part, parce que ce chiffre est généralement le premier constat de l'audit :

sql
-- GCP : coût net par équipe sur un mois de facturation, dépense sans label incluse
SELECT
  IFNULL((SELECT value FROM UNNEST(labels) WHERE key = 'team'), '(unlabeled)') AS team,
  ROUND(
    SUM(cost) + SUM(IFNULL((SELECT SUM(c.amount) FROM UNNEST(credits) c), 0)),
    2
  ) AS net_cost
FROM `my-billing-project.billing_export.gcp_billing_export_v1_XXXXXX_XXXXXX_XXXXXX`
WHERE invoice.month = '202608'
GROUP BY team
ORDER BY net_cost DESC

Sur AWS, l'équivalent le plus rapide est Cost Explorer en ligne de commande. Le tag team doit d'abord être activé comme tag de répartition des coûts dans la console Billing, et il ne s'applique qu'aux dépenses postérieures à son activation :

bash
aws ce get-cost-and-usage \
  --time-period Start=2026-08-01,End=2026-09-01 \
  --granularity MONTHLY \
  --metrics NetUnblendedCost \
  --group-by Type=TAG,Key=team \
  --query 'ResultsByTime[0].Groups[].[Keys[0], Metrics.NetUnblendedCost.Amount]' \
  --output table

Les lignes avec la clé team$ (valeur vide) représentent votre dépense non attribuée. Remplacez le group-by par Type=DIMENSION,Key=SERVICE pour obtenir la vue par service. Au-delà d'un instantané mensuel, mettez en place l'export Cost and Usage Report (CUR) et interrogez-le dans Athena.

2. Redimensionner le calcul, mais en vérifiant avec de vraies données d'utilisation

Le redimensionnement est le levier le plus puissant, et le plus risqué s'il est fait à l'aveugle. Le processus qui fonctionne :

  1. Récupérez 30 à 90 jours d'utilisation CPU, mémoire et réseau par instance/node pool.
  2. Signalez comme candidat au redimensionnement tout ce qui tourne nettement en dessous de son allocation (je commence par moins de 20 % de CPU moyen, et je vérifie la mémoire séparément).
  3. Recoupez avec les pics d'activité (batchs de fin de mois, trafic du Black Friday) avant de réduire quoi que ce soit.
  4. Déployez les changements via des politiques d'autoscaling définies dans Terraform, jamais par édition manuelle en console.

3. Vous engager sur ce que vous savez utiliser

Ne vous engagez qu'après le redimensionnement, sinon vous verrouillez une remise sur du gaspillage. Les Committed Use Discounts (GCP) ou Savings Plans (AWS) doivent couvrir le plancher stable observé sur toute la fenêtre de 30 à 90 jours, qui se situe sous la moyenne comme sous le pic. Tout ce qui dépasse ce plancher reste à la demande ou en autoscaling. Si la base bouge encore, commencez par une durée plus courte ou un engagement partiel. Les deux clouds affichent le taux d'utilisation des engagements. Vérifiez-le chaque mois, et n'augmentez l'engagement qu'une fois l'existant pleinement utilisé.

4. Hiérarchiser le stockage et réduire le gaspillage réseau

Côté stockage et réseau, les économies passent par la configuration plutôt que par des engagements, ce qui se prête bien à Terraform.

Les règles de cycle de vie déplacent automatiquement les données froides vers des classes moins chères. Sur GCS :

hcl
resource "google_storage_bucket" "app_logs" {
  name                        = "acme-app-logs"
  location                    = "EU"
  uniform_bucket_level_access = true
 
  lifecycle_rule {
    condition {
      age = 30
    }
    action {
      type          = "SetStorageClass"
      storage_class = "NEARLINE"
    }
  }
 
  lifecycle_rule {
    condition {
      age = 365
    }
    action {
      type = "Delete"
    }
  }
}

L'équivalent AWS est aws_s3_bucket_lifecycle_configuration avec des transitions vers STANDARD_IA ou une classe Glacier. Avant de hiérarchiser, regardez les durées minimales de stockage et les frais de récupération au Go des classes froides, car des données lues souvent peuvent finir par y coûter plus cher. Les très petits objets en profitent rarement, eux aussi.

Côté réseau, traquez le trafic inter-régions et inter-AZ. Les équipes oublient souvent d'auditer ce poste de dépense, et il grossit vite. Filtrez l'export de facturation sur les SKU de sortie réseau (GCP) ou les usage types DataTransfer (AWS) pour voir d'où il vient.

5. Éliminer les ressources « temporaires » jamais nettoyées

Chaque audit fait remonter des disques orphelins, des load balancers inactifs, des clusters de dev oubliés et des IP non rattachées. Je mets en place un balayage automatisé hebdomadaire sous forme de Cloud Function ou de Lambda gérée par Terraform. Il signale tout ce qui n'est pas tagué ou reste inactif au-delà d'un seuil, et ne supprime jamais rien automatiquement.

6. Ancrer ces économies avec le GitOps

Les économies qui ne survivent pas au trimestre suivant sont celles qui dépendent d'une personne pensant à vérifier un tableau de bord. Celles qui durent sont imposées par la politique :

  • Tout changement d'infrastructure passe par Terraform + revue de pull request (pas de clics en console).
  • Les alertes budgétaires et la détection d'anomalies sont définies en code.
  • Un contrôle CI bloque les hausses de coûts au-delà d'un plafond convenu.

Garde-fou 1 : un contrôle de coût sur chaque pull request

Infracost estime le delta de coût mensuel d'un changement Terraform et le publie en commentaire sur la PR. Ce workflow échoue en plus quand l'augmentation dépasse un seuil, sauf si un relecteur ajoute le label cost-approved. Faites du job un status check obligatoire dans la protection de branche pour que le plafond ne puisse pas être contourné :

yaml
# .github/workflows/infracost.yml
name: infracost
on:
  pull_request:
    paths: ["infra/**"]
    types: [opened, synchronize, reopened, labeled, unlabeled]
 
permissions:
  contents: read
  pull-requests: write
 
jobs:
  cost:
    runs-on: ubuntu-latest
    env:
      TF_ROOT: infra
      MAX_MONTHLY_INCREASE: "500" # USD par mois
    steps:
      - uses: infracost/actions/setup@v4
        with:
          api-key: ${{ secrets.INFRACOST_API_KEY }}
 
      - name: Checkout base branch
        uses: actions/checkout@v7
        with:
          ref: ${{ github.event.pull_request.base.ref }}
 
      - name: Estimate base branch cost
        run: |
          infracost breakdown --path="$TF_ROOT" \
            --format=json --out-file=/tmp/infracost-base.json
 
      - name: Checkout PR branch
        uses: actions/checkout@v7
 
      - name: Diff PR against base
        run: |
          infracost diff --path="$TF_ROOT" \
            --format=json \
            --compare-to=/tmp/infracost-base.json \
            --out-file=/tmp/infracost.json
 
      - name: Comment on the PR
        run: |
          infracost comment github --path=/tmp/infracost.json \
            --repo="$GITHUB_REPOSITORY" \
            --github-token="${{ github.token }}" \
            --pull-request="${{ github.event.pull_request.number }}" \
            --behavior=update
 
      - name: Enforce the monthly increase ceiling
        if: ${{ !contains(github.event.pull_request.labels.*.name, 'cost-approved') }}
        run: |
          delta=$(jq -r '.diffTotalMonthlyCost // "0"' /tmp/infracost.json)
          echo "Delta de coût mensuel : ${delta} USD"
          if awk -v d="$delta" -v max="$MAX_MONTHLY_INCREASE" 'BEGIN { exit !(d > max) }'; then
            echo "::error::L'augmentation mensuelle de ${delta} USD dépasse ${MAX_MONTHLY_INCREASE} USD. Ajoutez le label 'cost-approved' après revue."
            exit 1
          fi

Deux réserves s'imposent. Infracost chiffre les ressources à partir du code Terraform, donc les coûts liés à l'usage (sortie réseau, requêtes, volume de logs) sont estimés à zéro sauf si vous lui fournissez un fichier d'usage. Et les PR venant de forks n'ont pas accès aux secrets du dépôt, ce qui réserve ce workflow aux dépôts internes. Si vous préférez ne pas le maintenir, la GitHub App d'Infracost ou sa nouvelle action diff gèrent les commentaires avec moins de configuration. Le seuil se règle alors dans les garde-fous d'Infracost et non plus dans votre dépôt.

Garde-fou 2 : des alertes budgétaires dans Terraform

Le contrôle de PR ne voit que les changements faits dans le code. Les budgets couvrent la dépense qui dérive sans changement de code, par exemple une hausse du trafic, un job qui s'emballe ou un cluster de test oublié. Définissez-les à côté de l'infrastructure qu'ils surveillent :

hcl
# AWS : alerte à 80 % de la dépense réelle et quand la prévision dépasse 100 %
resource "aws_budgets_budget" "monthly_total" {
  name         = "monthly-total"
  budget_type  = "COST"
  limit_amount = "5000"
  limit_unit   = "USD"
  time_unit    = "MONTHLY"
 
  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 80
    threshold_type             = "PERCENTAGE"
    notification_type          = "ACTUAL"
    subscriber_email_addresses = ["finops@example.com"]
  }
 
  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 100
    threshold_type             = "PERCENTAGE"
    notification_type          = "FORECASTED"
    subscriber_email_addresses = ["finops@example.com"]
  }
}
 
# GCP : même principe, limité au projet de production
resource "google_billing_budget" "prod_monthly" {
  billing_account = var.billing_account_id
  display_name    = "prod-monthly"
 
  budget_filter {
    projects = ["projects/${var.prod_project_number}"]
  }
 
  amount {
    specified_amount {
      currency_code = "USD"
      units         = "5000"
    }
  }
 
  threshold_rules {
    threshold_percent = 0.8
  }
 
  threshold_rules {
    threshold_percent = 1.0
    spend_basis       = "FORECASTED_SPEND"
  }
 
  all_updates_rule {
    monitoring_notification_channels = [var.finops_notification_channel_id]
    disable_default_iam_recipients   = true
  }
}

Les budgets alertent, mais ne plafonnent pas la dépense. Envoyez les notifications dans un canal que quelqu'un lit, et traitez un budget dépassé comme n'importe quel incident, en retrouvant le changement responsable et en le corrigeant dans le code. Sur AWS, aws_ce_anomaly_monitor et aws_ce_anomaly_subscription ajoutent la détection d'anomalies de la même façon.

Le résultat

Dans les audits que j'ai menés, les économies les plus importantes, et celles qui durent, sont venues de l'attribution, du redimensionnement avant l'engagement et des garde-fous ci-dessus. Le montant économisé dépend fortement du gaspillage présent au départ. Mesurez-le donc par rapport à votre propre base de l'étape 1 plutôt qu'à un chiffre de l'industrie. La fiabilité tient parce que chaque changement suit le même processus de revue qu'un déploiement de fonctionnalité.

Si vous voulez cet audit appliqué à votre propre environnement, c'est l'objet de ma mission d'Audit des coûts Cloud. Vous repartez avec un rapport détaillé des coûts, une feuille de route d'économies priorisée et les pull requests Terraform pour la mettre en œuvre.

ALLER PLUS LOIN

Envie de faire tourner ça en production ?

Ce tutoriel couvre les concepts et l'architecture. Si vous voulez l'implémenter dans votre propre infrastructure, ou monter en compétence pour posséder ce sujet durablement, je propose du mentorat individuel construit autour de votre environnement réel, pas une formation générique.

Ce tutoriel

  • Concepts clés et architecture principale
  • Extraits de code illustratifs
  • Le raisonnement derrière chaque décision

Mentorat individuel

  • Des sessions de travail sur votre propre environnement
  • Des réponses directes aux cas particuliers que vous rencontrez
  • Un retour sur votre implémentation réelle
  • Un accompagnement continu pendant que vous la construisez
Me contacterRéponse sous 1 jour ouvré.

Tutoriels similaires