Le guide 2026 d'optimisation des coûts Cloud
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 :
-- 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 DESCSur 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 :
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 tableLes 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 :
- Récupérez 30 à 90 jours d'utilisation CPU, mémoire et réseau par instance/node pool.
- 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).
- Recoupez avec les pics d'activité (batchs de fin de mois, trafic du Black Friday) avant de réduire quoi que ce soit.
- 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 :
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é :
# .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
fiDeux 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 :
# 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.
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
Tutoriels similaires
FinOps Kubernetes sur EKS avec Karpenter
Remplacez les node groups statiques d'EKS par le provisioning just-in-time de Karpenter pour réduire le compute.
Provisionner un VPC AWS sécurisé avec Terraform
Un VPC AWS prêt pour la production en Terraform : sous-réseaux, NAT, tables de routage et valeurs par défaut plus sûres.
Réduire vos coûts Kubernetes sur GKE
Redimensionnez les requests avec le VPA, réglez le HPA, adoptez les node pools Spot et faites redescendre l'autoscaler.