Sommaire
La direction financière ne demande pas un tableau de bord. Elle demande combien coûte l’application webshop sur le cluster vks-fret-01, et elle attend un chiffre qui tienne devant un comité. Le cluster tourne depuis dix-huit mois, la plateforme est refacturée en interne au workload domain wld-fret-prod en une ligne globale, et personne ne sait dire, sans reconstruire un tableur, ce que consomme webshop-db par rapport à webshop-web.
Cet article ne vend pas un tableau de bord : il vend la lecture d’un modèle de calcul. OpenCost n’ouvre aucune facture. Il interroge Prometheus, en tire des quantités de ressource moyennées sur une durée, et les multiplie par une fiche de prix. Tout l’enjeu est dans le second facteur — d’où vient ce prix, ce qu’il vaut, et ce qui se passe quand personne ne l’a choisi. Précision de méthode : aucun lab n’a été exécuté ici, aucune facture n’a été lue. Ce qui suit est un cadrage adossé à des pages de documentation, avec ses trous nommés à voix haute.
TL;DR
- La décision — la première étape n’est pas l’installation, c’est le choix de la source de prix. OpenCost applique par défaut, dans le cloud, « the on-demand list pricing » ; sur site, une fiche livrée dont le projet écrit lui-même la provenance :
"description": "Default prices based on GCP us-central1". - L’arbitrage qui coûte — la réconciliation avec votre facture remisée, les alertes, la gouvernance, la fédération multi-cluster et le support relèvent de Kubecost, publié par Apptio, an IBM Company. Sur une plateforme privée, cette réconciliation n’a même pas d’objet : il n’y a pas de facture amont à mettre en face.
- L’action de lundi matin — écrire une note de modèle d’une page, versionnée à côté du fichier de valeurs Helm, qui dit d’où vient chaque prix unitaire, à quelle date il a été posé, et quels réglages d’oisiveté et de résolution ont produit les chiffres publiés en interne.
Le contrat de chiffre de cet article
Cet article publie zéro montant, zéro pourcentage d’économie, zéro statistique de parc. Ce n’est pas une lacune de collecte, c’est une règle : un chiffre de coût a l’apparence d’un fait, il se recopie dans un tableur, puis dans une slide, puis dans un arbitrage budgétaire — et plus personne ne remonte à sa source.
Ce que l’article publie, en revanche : des versions et des états de mécanisme avec la page qui les porte, des noms de champs, de paramètres, d’endpoints et de ports, des valeurs par défaut de paramètres logiciels non monétaires, des dates de gouvernance, et des formules citées depuis la spécification plutôt que reformulées.
Ce qu’il refuse de chiffrer : tout prix unitaire de ressource, cloud public ou privé ; tout coût de namespace, d’application ou d’équipe ; tout écart, tout gain, tout ratio de gaspillage.
Un refus qui demande une justification
La page Installing On-Premises d’OpenCost publie une fiche de prix par défaut complète : une dizaine de clés monétaires avec leurs valeurs. Ces valeurs sont documentées, attribuables et datables — elles seraient donc citables. Cet article les nomme, cite leur description publiée, et ne reproduit pas leurs valeurs. Motif en une phrase : un nombre imprimé dans un article devient, chez le lecteur, la base de coût de son cluster privé — sans la ligne qui dit d’où il vient. Or cette ligne est justement la matière de l’article.
Ce qu’OpenCost calcule : une quantité, multipliée par un prix
La documentation d’accueil du projet publie sa définition : « OpenCost is a vendor-neutral open source project for measuring and allocating cloud infrastructure and container costs. » La FAQ du même site en publie une autre, qui ne recouvre pas tout à fait le même objet : « … for measuring and allocating Kubernetes and cloud infrastructure costs. » Les deux sont publiées ; on les cite avec leur page, on n’en fabrique pas une troisième.
Le projet est sous licence Apache 2.0 et gratuit — « No. OpenCost is open source (Apache 2.0) and free to use. » Côté gouvernance, la CNCF publie une maturité Incubating, un projet accepté le 2022-06-17 et passé Incubating le 2024-10-25. Il ne s’agit donc pas d’un « standard CNCF » : la CNCF ne publie pas de standard de mesure de coût.
Le point de mécanique qui fonde tout le reste tient en deux formes publiées par la spécification :
- coûts d’allocation de ressource = Amount × Duration × HourlyRate ;
- coûts d’usage = Amount × UnitRate.
Le chiffre affiché est donc le produit d’une mesure et d’une hypothèse. La mesure vient du cluster ; l’hypothèse vient d’ailleurs.
| Ressource | Quantité publiée | Prix publié | Coût publié |
|---|---|---|---|
| CPU | cores = avg_over_time(cpu) by (node) [cores] |
fiche fournisseur ou personnalisée [$/core-hr] |
total cost = cores * duration * price |
| RAM | ram bytes = avg_over_time(GB) by (node) [ram GBs] |
fiche fournisseur ou personnalisée [$/GB-hr] |
total cost = ram bytes * duration * price |
| GPU | « The greater of requested resources and used resources measured in cores » | fiche de prix | même forme quantité × durée × prix |
| Volume persistant | Disk Size = avg_over_time(GB) by (pv) [disk GBs] |
« typically a function of disk class, IOPS, backup size » | même forme |
| Réseau | ingress/egress « across zones, regions, or the wide internet », en octets ou gigaoctets | prix par octet | coût d’usage, pas d’allocation |
| Load balancer | octets entrants et nombre de forwarding rules | fiche de prix | usage et allocation |
Les formules portent des symboles de prix, jamais des valeurs. La durée publiée est duration = end running - start running [hrs].
Deux conséquences de lecture, rarement dites. D’abord, avg_over_time est une moyenne, pas un relevé : le chiffre d’un namespace est une intégrale approchée. Ensuite, le réseau et le load balancer ne suivent pas la même règle que le CPU — traiter « le coût d’un namespace » comme une somme homogène rate cette asymétrie.
La règle qui gouverne l’allocation est publiée telle quelle : « Workload Costs should be understood as max(request, usage) ». Côté Kubernetes, la page Resource Management for Pods and Containers publie la sémantique correspondante — le request sert au kube-scheduler pour placer le pod, et « it’s possible (and allowed) for a container to use more resource than its request for that resource specifies ». En clair : une charge qui réserve beaucoup et consomme peu porte le coût de sa réservation. C’est exactement ce que l’article suivant de la série ira déplacer.
Reste le résidu, et il porte un nom : Cluster Idle Cost = ( Cluster Asset Costs - Workload Costs ), avec Cluster Idle % = Idle Cost / Resource Allocation Costs. La spécification précise que les coûts d’usage n’en font pas partie — « they are always used, the corresponding resource never “sits idle.” » Trois paramètres d’API gouvernent son traitement, tous à false par défaut : includeIdle, shareIdle, idleByNode. Activer shareIdle augmente le coût affiché de tous les namespaces sans qu’un centime de dépense ait bougé. Ce n’est pas un réglage technique, c’est un arbitrage d’allocation — il se décide avec les équipes.
D’où vient le prix : trois chemins, dont un qu’on prend sans le savoir
| Chemin | Ce qu’il fournit | Ce qu’il suppose |
|---|---|---|
| Intégration de facturation du fournisseur | les coûts du fournisseur, exposés par /cloudCost |
un compte cloud, un export de facturation, des droits de lecture |
| Fiche de prix personnalisée | vos prix unitaires appliqués aux quantités échantillonnées | que quelqu’un ait calculé ces prix et sache dire d’où ils viennent |
| Valeurs par défaut | une fiche pré-remplie, d’origine GCP us-central1 |
rien — c’est ce qu’on obtient en ne choisissant pas |
La phrase publiée par la FAQ est sans ambiguïté : « OpenCost provides real-time monitoring of your Kubernetes cluster and provides the on-demand list pricing for the cloud resources in use by your cluster. » Tarif public, à la demande. Un lecteur sous contrat remisé, sous engagement, ou consommant de la capacité spot, regarde donc un chiffre qui n’est pas le sien tant qu’il n’a pas branché l’intégration de facturation de son fournisseur.
Sur site, c’est le même piège en pire : la fiche par défaut porte elle-même sa provenance, "description": "Default prices based on GCP us-central1". Dans le cloud, le prix par défaut est au moins le prix affiché de la ressource réellement employée ; sur un cluster VKS, c’est le prix affiché d’une autre plateforme, dans une autre région.
La page Configuration publie la raison d’être du deuxième chemin — « In some cases users may need to override the pricing provided by their cloud service provider. » — et l’application se fait par le fichier de valeurs Helm : « Custom pricing may be applied by updating your local OpenCost Helm values file. »
{
"provider": "custom",
"description": "REPLACE_WITH_PRICE_SHEET_PROVENANCE",
"CPU": "REPLACE_WITH_CPU_HOURLY_RATE",
"spotCPU": "REPLACE_WITH_SPOT_CPU_HOURLY_RATE",
"RAM": "REPLACE_WITH_RAM_GB_HOURLY_RATE",
"spotRAM": "REPLACE_WITH_SPOT_RAM_GB_HOURLY_RATE",
"GPU": "REPLACE_WITH_GPU_HOURLY_RATE",
"storage": "REPLACE_WITH_STORAGE_GB_HOURLY_RATE",
"zoneNetworkEgress": "REPLACE_WITH_ZONE_EGRESS_RATE",
"regionNetworkEgress": "REPLACE_WITH_REGION_EGRESS_RATE",
"internetNetworkEgress": "REPLACE_WITH_INTERNET_EGRESS_RATE"
}
Les noms de clés et le champ provider: "custom" sont publiés. Les REPLACE_WITH_* restent vides, et c’est volontaire : ils dépendent d’un relevé que seul l’exploitant peut faire, à sa date et sur sa région. La meilleure idée à retenir de la fiche livrée est ailleurs : le projet écrit lui-même sa provenance dans le champ description. Un exploitant qui y met sa source et sa date rend son modèle auditable par la personne suivante.
Deux trous à dire plutôt qu'à combler
Le chemin exact de la clé du fichier de valeurs Helm qui porte cette fiche n’a pas été obtenu en citation exacte lors de la campagne de vérification du 2026-08-16 : cet article ne publie donc aucun chemin de clé deviné, il renvoie à la page Installing On-Premises. De même, la page de releases du dépôt a rendu des dates incohérentes avec la date de campagne — cet article n’écrit pas « la version courante d’OpenCost est X ». La seule borne citable vient d’une page de documentation : « Kubernetes 1.28 is officially supported as of v1.105 ».
Dernier point de cadrage, et il change l’arbitrage pour un exploitant VCF : « Cloud Costs are not currently supported for on-prem, but you may configure OpenCost to view costs associated with other cloud service providers. » Sur vks-fret-01, le plan /cloudCost ne portera donc rien de la plateforme privée. Et il n’y a rien à réconcilier : il n’existe pas de facture amont. Or la réconciliation est précisément l’argument principal du produit commercial. Ce que le projet énumère lui-même comme relevant de Kubecost : « more accurate cost numbers for your cluster after reconciling the differences between your published bill with any negotiated discounts », puis « recommendations, governance, alerting, federated clusters, a SaaS platform, and support ». Kubecost est publié par Apptio, an IBM Company ; son palier Foundations est gratuit — « Unlimited clusters up to 250 cores », « 15-day metric retention », support communautaire — et aucun montant n’est affiché sur la page de tarification. Cette rétention de quinze jours borne l’analyse de tendance, pas la mesure : un besoin de comparaison trimestrielle sort du palier gratuit, ou reste dans Prometheus, dont la rétention est votre affaire.
Lire dans le bon ordre : les actifs avant l’allocation
Le prérequis publié tient en une phrase — « OpenCost requires Prometheus for scraping metrics and data storage » — et aucune version minimale de Prometheus n’est publiée. Ce n’est pas un oubli de collecte : la page de configuration Prometheus dédiée n’existe pas dans cet arbre de documentation, elle répond 404. On l’écrit tel quel plutôt que d’inventer une borne.
Deux planchers Kubernetes cohabitent chez le même projet : « Kubernetes 1.21+ and Kubernetes 1.28 is officially supported as of v1.105 » sur la page Setup, « OpenCost supports a Kubernetes environment above 1.8. » dans la FAQ. La règle de lecture, réutilisable bien au-delà d’OpenCost : quand deux pages d’un même projet publient deux bornes, on retient la plus restrictive et on nomme la page qui la porte. Ici 1.21+, page Setup — très en dessous du plancher de cette série, Kubernetes 1.35, cible 1.36. Ce n’est pas un procès du projet, c’est une méthode de citation.
L’installation se fait dans un namespace nommé opencost, l’UI est incluse par défaut, et l’accès local passe par un port-forward. Là encore, deux commandes sont publiées pour le même besoin, sur deux pages différentes — celle de la page Installation et celle de la page UI :
# page Installation — API sur 9003, UI sur 9090
kubectl port-forward --namespace opencost service/opencost 9003 9090
# page UI — même besoin, commande différente
kubectl port-forward --namespace opencost service/opencost 9090 9090
Vient ensuite l’argument central de cette section : on lit les actifs avant l’allocation. La ventilation n’a de sens que si on connaît d’abord le total qu’elle ventile. Un tableau de bord qui ouvre sur les namespaces met le lecteur devant un résultat sans son dénominateur.
# 1 — le total à ventiler : nœuds, disques, avec cpuCost, ramCost, totalCost
curl -G http://localhost:9003/assets -d window=7d
# 2 — la ventilation, exemple publié par la documentation
curl -G http://localhost:9003/allocation \
-d window=7d \
-d aggregate=namespace \
-d resolution=1m
# 3 — voir l'oisiveté et la répartir : deux réglages, deux résultats
curl -G http://localhost:9003/allocation \
-d window=1d \
-d shareIdle=true \
-d idleByNode=true
Le paramètre aggregate accepte cluster, node, namespace, controllerKind, controller, service, pod, container, label:LABEL_NAME et annotation:name. Le paramètre window accepte des mots (today, week, lastmonth), des durées (30m, 12h, 7d), des paires de dates RFC3339 et des timestamps Unix. Quant à resolution, sa description publiée est un aveu utile : « Smaller values (i.e. higher resolutions) will provide better accuracy, but worse performance […] Larger values will perform better, but at the expense of lower accuracy for short-running workloads. Default is 1m. » La même page porte une section intitulée « Theoretical error bounds ». Son tableau de valeurs n’a pas été obtenu en citation exacte lors de la vérification : cet article dit donc que le projet publie des bornes d’erreur, et n’en cite aucune valeur. Le fait suffit — un coût affiché à deux décimales sur un CronJob de trente secondes est une illusion de précision.
L’attribution par équipe passe par l’agrégation par étiquette, et elle suppose une convention antérieure au déploiement :
curl -G http://localhost:9003/allocation \
-d window=7d \
-d aggregate=label:REPLACE_WITH_TEAM_LABEL_KEY \
-d resolution=1m
Attention : l’API accepte cette agrégation, elle ne crée pas la donnée. Si trois Deployment sur quinze portent l’étiquette, la réponse arrivera quand même — et elle sera fausse au sens de la question posée. Aucune page chargée ne publie ce que devient une charge dépourvue de l’étiquette demandée : il n’y a pas lieu d’affirmer qu’elle atterrit dans un seau « non attribué ». La question se pose, elle se renvoie au relevé.
Un contrôle vaut d’être fait ailleurs qu’à travers OpenCost : vérifier que Prometheus détient bien l’historique de la fenêtre demandée. Une fenêtre plus longue que la rétention produit un chiffre silencieusement partiel.
# Reconstitution à partir des familles de métriques nommées par la spécification.
# Le nom exact des séries dépend de la pile en place — à valider sur votre plateforme.
count_over_time(
container_cpu_usage_seconds_total{namespace=~"webshop-.*"}[7d]
)
Sur VKS : ce que VCF Operations 9.1 expose, et ce qu’il ne publie pas
L’intuition « VCF ne dit rien du coût Kubernetes » est fausse depuis VCF 9.1. Les notes de version publient : « VCF Operations now delivers comprehensive costing capabilities across your entire Kubernetes ecosystem, including nodes, clusters, vSphere namespaces, projects, and organizations. » Et aussi : « VCF Operations now offers powerful tools to implement transparent, granular chargeback models specifically for VMware Kubernetes Service (VKS) nodes in addition to the traditional VM pricing. » Le Management Pack for Kubernetes livre par ailleurs un tableau de bord qui suit « the costs of the clusters, nodes, and namespaces in a single place ».
Côté origine du prix, la différence est structurelle : VCF Operations ne consulte aucun tarif, il distribue un coût saisi. Dix cost drivers sont publiés pour l’infrastructure vCenter — Server Hardware: Traditional, Server Hardware: Hyper-Converged, Storage, License, Applications, Maintenance, Labor, Network, Facilities, Additional Cost — et la mécanique tient en une phrase : « The total cost set by you is distributed across resources in the data center. » Le matériel s’amortit selon deux méthodes publiées, Straight Line et Max of Double or Straight, sur une période paramétrable de deux à cinq ans, avec une remise dont « The default discount % value is zero. »
| Axe | OpenCost | VCF Operations |
|---|---|---|
| Objet de coût le plus fin publié | jusqu’au conteneur, agrégeable par étiquette | nœud, cluster, vSphere namespace, projet, organisation |
| Origine du prix | fiche de prix appliquée aux quantités échantillonnées | coût total saisi, puis distribué |
| Méthode de calcul publiée | oui, dans la spécification | non trouvée sur les pages chargées |
| Facture amont à réconcilier | existe dans le cloud public | n’existe pas sur la plateforme privée |
Aucun des deux n’est « meilleur » : ils ne répondent pas à la même question. Et il faut assumer trois trous plutôt que les habiller. Un : aucune page chargée ne publie la méthode de calcul du costing Kubernetes de VCF Operations — l’article décrit ce qui est exposé, pas comment c’est obtenu. Deux : la granularité publiée s’arrête au nœud et au vSphere namespace, jamais au pod ni au conteneur. Trois : aucune page Broadcom chargée ne nomme OpenCost, Kubecost ou un outil FinOps Kubernetes tiers sur VKS — déployer OpenCost sur un cluster VKS est une reconstitution raisonnable, pas un chemin documenté par l’éditeur. À noter aussi : les pages de configuration du coût côté 9.1 — pricing cards, chargeback VCF Automation, cost drivers — ne nomment aucun objet Kubernetes ; seules les notes de version annoncent la capacité. On cite donc la capacité telle qu’annoncée, sans décrire une procédure de configuration qu’aucune page ne publie.
Reste la question ouverte, et elle se raconte comme telle. Il est mécaniquement possible de dériver un prix $/core-hr et $/GB-hr du modèle financier de VCF Operations et de le poser dans la fiche personnalisée d’OpenCost — mais aucune page ne publie cette dérivation ni ne l’autorise, et elle dépend du taux d’occupation de la plateforme. Ce sera le sujet du troisième article. Sur un cluster VKS, l’exploitant qui veut un chiffre au grain du conteneur doit fournir lui-même le prix unitaire. C’est précisément la ligne que cet article lui demande d’écrire.
Pièges & points de vigilance
Le piège n°1 : publier un chiffre avant d'avoir choisi son prix
Tant que le champ description de la fiche de prix n’a pas été réécrit avec une provenance réelle et une date, les sorties d’OpenCost sont des sorties de qualification, pas des chiffres publiables en interne. Un chiffre faux publié devant un comité ne se désinstalle pas — et le retrait technique, lui, tient en deux commandes : helm uninstall opencost puis kubectl delete namespace opencost.
- Le chiffre suit les réservations, pas la consommation.
max(request, usage). Une équipe qui optimise son code sans toucher à sesrequestsne verra aucun effet sur son coût affiché. - L’oisiveté partagée déplace le coût sans déplacer la dépense. Un showback publié sans dire quel réglage de
shareIdleet d’idleByNodel’a produit est incomparable d’un mois sur l’autre. Figer ces réglages, et les publier avec chaque chiffre. - Le fichier de valeurs se versionne comme un manifeste applicatif. Un changement de prix unitaire modifie rétroactivement la lecture de toutes les séries, sans laisser de trace ailleurs.
- Deux pages du même projet peuvent publier deux bornes. Bornes Kubernetes et listes d’intégrations de facturation divergent entre la page Configuration et la FAQ. On cite chaque liste avec sa page ; on ne construit pas une synthèse qui n’existe nulle part.
- Une fenêtre plus longue que la rétention Prometheus renvoie un résultat partiel, sans le dire. Le contrôle se fait côté Prometheus, pas côté OpenCost.
- Le rightsizing qui suit ne créera pas d’économie tout seul. Réduire une réservation libère de la capacité. L’économie n’existe que si un nœud est retiré, non acheté, ou repris par une autre charge.
Conclusion
La bonne sortie de ce chantier n’est pas une capture de graphe : c’est un document d’une page, versionné à côté du fichier de valeurs, qui répond à six questions. D’où vient chaque prix unitaire et à quelle date il a été posé. Quelle fenêtre et quelle resolution produisent les chiffres publiés en interne. L’oisiveté est-elle partagée, et selon laquelle des trois méthodes publiées — uniforme, proportionnelle, ou métrique personnalisée. Quelle clé d’étiquette porte l’attribution par équipe. Quels coûts sont hors de ce modèle, nommément. Et qui relit ce document, à quelle échéance.
Avant d’installer
Choisir la source de prix : intégration de facturation, fiche personnalisée, ou rien — et « rien » signifie des tarifs publics d’une région Google Cloud sur votre matériel privé.
Après l’installation
Lire les actifs avant l’allocation, figer fenêtre, résolution et traitement de l’oisiveté, et inscrire la provenance des prix dans le champ description.
Ce que ça ne fait pas
OpenCost ne réduit rien et ne réconcilie rien. Il rend un modèle lisible. La suite — savoir combien de ce coût est du vide réservé — est l’objet de l’article suivant.
Ce premier étage répond à la première question de la direction financière et s’arrête à une frontière nette : le chiffre produit est un produit, une quantité multipliée par un prix posé, et la quantité vaut max(request, usage). Autrement dit, sur les trois namespaces webshop-*, une part du coût affiché n’est pas de la consommation — c’est de la réservation. Combien ? Cet article ne le dit pas ; il dit où le lire, et avec quels réglages.
Lectures voisines sur le blog : Prometheus et Grafana sur VKS en production pour le prérequis d’observabilité, Premier cluster VKS sur VCF 9 pour le prérequis de plateforme, VCF 9.1 : Kubernetes en self-service pour le modèle de projets et d’organisations que le costing 9.1 vient chiffrer, et La nouvelle architecture VCF 9 expliquée aux architectes pour le modèle de plateforme.
Suite de la série : Rightsizing Kubernetes avec VPA et KRR.
Reçois le prochain par email
Les nouveaux articles et séries, envoyés à leur publication. Aucun autre courrier.



