Le cloud a résolu le problème du provisioning matériel. En quelques clics, tu lances des dizaines de serveurs, des bases de données managées, des clusters Kubernetes. Mais cette facilité a un prix — littéralement. Sans discipline, les factures cloud explosent et personne ne sait exactement qui consomme quoi, ni pourquoi.
Le FinOps (Financial Operations) est la discipline qui réconcilie vélocité technique et maîtrise financière. Ce n’est pas “dépenser moins” — c’est dépenser mieux, en donnant à chaque équipe la visibilité et la responsabilité de ses coûts. Dans ce cours, on installe les deux outils clés de l’écosystème : Kubecost pour la visibilité en temps réel sur Kubernetes, et Infracost pour anticiper les coûts avant même de déployer.
Le framework FinOps — Les fondations
Le FinOps, formalisé par la FinOps Foundation, repose sur un cycle itératif en trois phases : Inform (qui dépense combien ?), Optimize (comment réduire sans casser ?) et Operate (comment gouverner dans la durée ?).
Les six principes fondateurs sont clairs : les équipes Engineering, Finance et Business collaborent ensemble ; chaque équipe est responsable de ses coûts ; un groupe centralisé (Cloud Center of Excellence) pilote la stratégie ; les rapports sont accessibles en temps réel ; les décisions sont guidées par la valeur business, pas par le coût brut ; et le modèle variable du cloud est un avantage, pas un problème.
🔥 Cas réel : Une scale-up SaaS européenne de 80 ingénieurs a découvert, après audit FinOps, que 40% de sa facture AWS provenait d’environnements de développement allumés 24/7 — week-ends et nuits inclus. En implémentant un simple scheduling on/off (cron Kubernetes + Lambda), elle a économisé 180k€/an sans toucher à la production.
Les erreurs classiques qui gonflent la facture :
- Environnements de dev allumés 24/7 alors que personne ne travaille la nuit ni le week-end
- Instances oversized — ce
m5.4xlargequi tourne à 5% de CPU - Volumes EBS orphelins — l’instance est supprimée, le disque reste et facture
- Snapshots accumulés — 3 ans de snapshots quotidiens que personne n’utilise
- NAT Gateway — le service le plus cher que personne ne surveille
⚠️ Attention : Le NAT Gateway AWS coûte ~0.045$/GB de données traitées. Un cluster Kubernetes qui tire beaucoup d’images Docker ou qui communique avec des APIs externes peut facilement générer 500-1000$/mois de NAT Gateway seul. Vérifie cette ligne en premier dans ta facture.
Kubecost — Visibilité des coûts Kubernetes
Kubecost est l’outil de référence pour comprendre combien coûte chaque namespace, deployment, pod et même container dans ton cluster Kubernetes. Il combine les métriques Prometheus avec les prix réels de ton cloud provider pour produire une allocation de coûts précise.
L’installation se fait via Helm. Kubecost déploie son propre Prometheus (ou se branche sur un existant), un backend d’analyse de coûts (cost-model) et une interface web :
# Installation Kubecost via Helm
helm repo add kubecost https://kubecost.github.io/cost-analyzer/
helm repo update
helm install kubecost kubecost/cost-analyzer \
--namespace kubecost \
--create-namespace \
--set kubecostToken="ton-token" \
--set prometheus.server.persistentVolume.size=32Gi \
--set persistentVolume.size=32Gi
Pour une configuration production, il faut connecter Kubecost à l’API de facturation de ton cloud provider (AWS Cost and Usage Report, GCP BigQuery, Azure Cost Management). Cela permet de réconcilier les coûts estimés avec les coûts réels facturés, et d’intégrer les remises (Reserved Instances, Savings Plans) :
# values.yaml — Configuration Kubecost avancée
kubecostProductConfigs:
clusterName: "production-eu-west-1"
currencyCode: "EUR"
athenaProjectID: "123456789012"
athenaBucketName: "s3://kubecost-cur-reports"
athenaRegion: "eu-west-1"
athenaDatabase: "athenacurcfn_kubecost"
athenaTable: "kubecost_cur"
alertConfigs:
enabled: true
alerts:
- type: budget
threshold: 500 # Alerte si namespace > 500€/jour
window: daily
aggregation: namespace
filter: '*'
- type: efficiency
threshold: 0.8 # Alerte si efficacité < 80%
window: weekly
aggregation: cluster
L’API Kubecost est extrêmement puissante pour automatiser la détection d’anomalies et alimenter des dashboards custom :
# Coûts par namespace sur les 7 derniers jours
curl -s "http://kubecost:9090/model/allocation?window=7d&aggregate=namespace" \
| jq '.data[0] | to_entries[] |
{namespace: .key, cost: .value.totalCost} | select(.cost > 1)'
# Recommandations de right-sizing automatiques
curl -s "http://kubecost:9090/model/savings/requestSizing?window=72h" \
| jq '.[0:5] | .[] | {
container: .containerName,
namespace: .namespace,
currentCPU: .currentRequest.cpu,
recommendedCPU: .recommendedRequest.cpu,
monthlySavings: .monthlySavings
}'
💡 Tip DevOps : Pour que l’allocation de coûts fonctionne correctement, chaque Deployment doit porter des labels FinOps standardisés (cost-center, team, environment, product). Sans ça, Kubecost ne peut pas dire “l’équipe checkout dépense X€/mois” — et le FinOps perd tout son intérêt.
Infracost — Le coût avant le déploiement
Infracost prend l’approche shift-left : il estime le coût d’un changement Terraform avant qu’il soit appliqué. Intégré dans la CI/CD, il poste un commentaire sur chaque Pull Request avec l’impact financier du changement proposé.
Le principe : quand un développeur modifie un fichier Terraform pour ajouter une instance RDS db.r5.2xlarge, le reviewer voit immédiatement “+1 234$/mois” dans le commentaire de la PR. C’est un moment de décision : est-ce que cette instance vaut ce prix, ou est-ce qu’un db.r5.large suffirait ?
Voici l’intégration GitHub Actions complète :
# .github/workflows/infracost.yml
name: Infracost
on:
pull_request:
paths: ['terraform/**']
jobs:
infracost:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: infracost/actions/setup@v3
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}
- name: Checkout base branch
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.base.ref }}
path: base
- name: Generate baseline
run: infracost breakdown --path=base/terraform/production
--format=json --out-file=/tmp/infracost-base.json
- name: Generate diff
run: infracost diff --path=terraform/production
--compare-to=/tmp/infracost-base.json
--format=json --out-file=/tmp/infracost-diff.json
- name: Post comment
run: infracost comment github
--path=/tmp/infracost-diff.json
--repo=${{ github.repository }}
--pull-request=${{ github.event.pull_request.number }}
--github-token=${{ secrets.GITHUB_TOKEN }}
--behavior=update
- name: Check threshold
run: |
DIFF=$(jq '.diffTotalMonthlyCost | tonumber' /tmp/infracost-diff.json)
if (( $(echo "$DIFF > 500" | bc -l) )); then
echo "::error::Cost increase exceeds 500$/month"
exit 1
fi
Pour aller plus loin, Infracost supporte les policies OPA (Open Policy Agent) qui permettent de refuser automatiquement certains changements trop coûteux :
# policy.rego — Règles de coûts avec Open Policy Agent
package infracost
deny[msg] {
r := input.projects[_].breakdown.resources[_]
r.resourceType == "aws_instance"
r.monthlyCost > 500
msg := sprintf("Instance %s coûte %v$/mois (max: 500$)", [r.name, r.monthlyCost])
}
warn[msg] {
r := input.projects[_].breakdown.resources[_]
r.resourceType == "aws_nat_gateway"
msg := sprintf("NAT Gateway %s coûte %v$/mois — est-ce nécessaire ?", [r.name, r.monthlyCost])
}
🧠 À retenir : Infracost ne remplace pas le monitoring des coûts réels (Kubecost, AWS Cost Explorer). C’est un filet de sécurité en amont. Les deux sont complémentaires : Infracost prévient, Kubecost constate.
Right-sizing — Ne payer que ce qu’on utilise
Le right-sizing est souvent le quick win le plus rentable en FinOps. Le problème est universel : les développeurs demandent 4 CPU et 8 GiB de RAM “au cas où”, le service en utilise réellement 0.3 CPU et 1.2 GiB. À l’échelle de 200 pods, ce gaspillage de 85% représente des milliers d’euros par mois.
La première étape est de mesurer l’écart entre les requests déclarées et l’usage réel. En Kubernetes, les requêtes PromQL suivantes identifient les pods sur-provisionnés :
# Pods dont l'usage CPU est inférieur à 20% des requests (sur 24h)
# → Candidats immédiats au right-sizing
(
sum by (namespace, pod) (rate(container_cpu_usage_seconds_total[24h]))
/
sum by (namespace, pod) (kube_pod_container_resource_requests{resource="cpu"})
) < 0.2
Le Vertical Pod Autoscaler (VPA) automatise le right-sizing. En mode Off, il observe et recommande sans toucher à rien — c’est le mode idéal pour commencer. En mode Auto, il applique automatiquement les recommandations en recréant les pods :
# VPA en mode recommandation (safe pour démarrer)
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: payment-service-vpa
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: payment-service
updatePolicy:
updateMode: "Off" # Recommandations only, pas de restart
resourcePolicy:
containerPolicies:
- containerName: payment
minAllowed:
cpu: "100m"
memory: "128Mi"
maxAllowed:
cpu: "2"
memory: "4Gi"
⚠️ Attention : Ne passe jamais directement en mode Auto sur un service critique en production. Commence par Off pendant 2 semaines, valide les recommandations manuellement, puis passe en Auto sur les services non-critiques d’abord. Le VPA en mode Auto redémarre les pods pour appliquer les nouvelles requests — ça peut impacter la disponibilité si ton PodDisruptionBudget n’est pas correctement configuré.
Pour les instances cloud (EC2, Compute Engine), un script d’analyse identifie rapidement les machines sous-utilisées en interrogeant CloudWatch :
#!/usr/bin/env python3
"""Recommandation de right-sizing AWS EC2"""
import boto3
from datetime import datetime, timedelta
cw = boto3.client('cloudwatch')
ec2 = boto3.client('ec2')
def get_avg_cpu(instance_id, days=14):
resp = cw.get_metric_statistics(
Namespace='AWS/EC2', MetricName='CPUUtilization',
Dimensions=[{'Name': 'InstanceId', 'Value': instance_id}],
StartTime=datetime.utcnow() - timedelta(days=days),
EndTime=datetime.utcnow(), Period=3600,
Statistics=['Average', 'Maximum'])
if not resp['Datapoints']: return 0, 0
avg = sum(d['Average'] for d in resp['Datapoints']) / len(resp['Datapoints'])
return avg, max(d['Maximum'] for d in resp['Datapoints'])
instances = ec2.describe_instances(
Filters=[{'Name': 'instance-state-name', 'Values': ['running']}])
for r in instances['Reservations']:
for i in r['Instances']:
avg, mx = get_avg_cpu(i['InstanceId'])
action = "⬇️ DOWNSIZE" if avg < 10 else "✅ OK" if avg < 80 else "⬆️ UPSIZE"
print(f"{i['InstanceId']:<20} {i['InstanceType']:<15} {avg:.1f}% avg {action}")
🔥 Cas réel : Un e-commerce a appliqué les recommandations VPA sur ses 150 microservices en production. Résultat : les requests CPU totales sont passées de 480 vCPU à 185 vCPU, permettant de réduire le cluster de 60 à 25 nœuds. Économie : 12 000€/mois, soit 144k€/an — le salaire d’un ingénieur financé par du right-sizing.
Bonnes pratiques et pièges à éviter
Ce qui fonctionne :
- Rendre les coûts visibles à chaque équipe via un dashboard partagé (pas réservé au management)
- Intégrer Infracost dans les PR dès le premier jour — l’habitude se prend vite
- Commencer le VPA en mode
Offet valider manuellement avant d’automatiser - Planifier un “FinOps review” mensuel de 30 minutes par équipe
- Automatiser l’extinction des environnements de dev hors heures ouvrées
Ce qui échoue :
- Donner la responsabilité des coûts uniquement à l’équipe Ops (c’est l’affaire de tous)
- Optimiser sans baseline — tu ne sauras jamais combien tu as économisé
- Right-sizer trop agressivement et provoquer des OOMKills en production
- Ignorer les coûts réseau (NAT Gateway, data transfer inter-AZ)
- Acheter des Reserved Instances avant d’avoir stabilisé l’usage
💡 Tip DevOps : La règle des 80/20 s’applique au FinOps. 80% de tes économies viendront de 3 actions : éteindre les env de dev la nuit, right-sizer les 10 plus gros workloads, et acheter des Savings Plans sur les ressources stables. Ne te perds pas dans l’optimisation des centimes.
Résumé
Le FinOps structure la gestion des coûts cloud en trois phases (Inform, Optimize, Operate) portées par toute l’organisation, pas seulement les Ops. Kubecost fournit la visibilité temps réel sur les coûts Kubernetes avec allocation par namespace, équipe et label. Infracost décale le contrôle des coûts en amont en estimant l’impact financier de chaque PR Terraform. Le right-sizing, qu’il soit manuel (PromQL + analyse) ou automatisé (VPA), est systématiquement le quick win le plus rentable — 30 à 50% d’économies sur les workloads Kubernetes sont la norme, pas l’exception.
🧠 À retenir : Le FinOps n’est pas un projet ponctuel. C’est une pratique continue, un muscle que l’organisation renforce itération après itération. Les outils sont importants, mais la culture de responsabilité partagée des coûts l’est encore plus.
Prochain cours : On continue le volet financier avec les Spot Instances, les stratégies de tagging et les budgets cloud — les leviers opérationnels pour passer de la visibilité à l’action.
🖥️ Pratique sur ton propre serveur
Pour suivre Platform Engineering en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.
Contenu réservé aux abonnés
Ce chapitre fait partie de la formation complète. Abonne-toi pour débloquer tous les contenus.
Débloquer pour 29 CHF/moisLe chapitre 1 de chaque formation est gratuit.
Série pas encore débloquée
Termine la série prérequise d'abord pour accéder à ce contenu.
Aller à la série prérequiseSérie : Platform Engineering
5 / 6Sur cette page
Articles liés
Spot Instances, tagging et budgets cloud
Spot Instances pour réduire les coûts de 90%, stratégie de tagging, budgets et alertes, et quick wins pour des économies immédiates.
Zero Trust : ne fais confiance à personne
Comprends les principes du Zero Trust, pourquoi le modèle périmétrique est mort, l'architecture ZTA en détail et le modèle BeyondCorp de Google.
mTLS et Service Mesh en pratique
Implémente mTLS, déploie un Service Mesh (Istio/Linkerd), utilise Tailscale, et mets en place le Zero Trust progressivement sur Kubernetes.