Le design du chargeback est décidé par une limite d'Azure Monitor, pas par une préférence comptable : une métrique custom autorise 10 clés de dimension, API Management en dépense déjà 5 pour ses valeurs par défaut, et les time series actives qu'une politique produit sont le produit des valeurs uniques de chaque dimension ajoutée. Trois dimensions à dix valeurs chacune font mille time series, contre un plafond de 50 000 time series actives par région et par subscription sur une fenêtre de douze heures. Mettez un ID utilisateur ou un ID de requête sur cette métrique et la télémétrie de la plateforme devient elle-même la panne. La partie 4 a terminé les trois chemins de requête. Cette partie répond à la question pour laquelle toute la série existe : quelle équipe a dépensé quoi, et comment la gateway empêche l'une d'elles de dépenser le quota de toutes les autres.

Deux credentials, deux rôles différents

API Management fournit deux mécanismes que l'on traite couramment comme des alternatives alors qu'ils sont complémentaires.

Une subscription key identifie un consommateur pour les besoins des products, des quotas et de l'analytique. Elle arrive dans l'en-tête Ocp-Apim-Subscription-Key, ou dans un paramètre de requête subscription-key qui n'est vérifié qu'en l'absence de l'en-tête, et les deux noms sont configurables par API. Les keys sont émises par paires, si bien qu'une application peut passer de la key A à la key B et régénérer A avec un minimum d'interruption.

Deux points sur les keys demandent d'être traités par le design plutôt qu'écartés par hypothèse. D'abord, API Management n'a aucun cycle de vie intégré pour les subscription keys : pas de date d'expiration, pas de rotation automatique. La rotation est un workflow à construire, avec Azure PowerShell ou les SDK, et si vous ne le construisez pas, les keys vivent pour toujours. Ensuite, la key est transmise au backend par défaut, où elle peut finir dans les logs de monitoring du backend et partout où ces logs sont expédiés. Un set-header à la fin de la section inbound qui la retire est un correctif de deux lignes pour un constat de credential dans les logs qui, sinon, est découvert par un auditeur.

Un JWT de Microsoft Entra ID répond à une autre question : cet appelant est-il autorisé en ce moment. Il expire nativement, il peut être révoqué de façon centralisée, et il porte des claims. Les applications en obtiennent un via le flow OAuth2 client credentials, et la gateway le valide avant que quoi que ce soit d'autre ne s'exécute :

<validate-jwt header-name="Authorization" require-scheme="Bearer"
              require-expiration-time="true" require-signed-tokens="true"
              clock-skew="60"
              output-token-variable-name="jwt"
              failed-validation-httpcode="401"
              failed-validation-error-message="Invalid or missing token.">
  <openid-config url="https://login.microsoftonline.com/{{tenant-id}}/v2.0/.well-known/openid-configuration" />
  <audiences>
    <audience>api://genai-gateway</audience>
  </audiences>
  <required-claims>
    <claim name="roles" match="any">
      <value>model.invoke</value>
    </claim>
  </required-claims>
</validate-jwt>

output-token-variable-name est la partie qui mérite sa place : le token validé atterrit dans une variable de politique, si bien que les politiques suivantes peuvent y lire un claim au lieu de faire confiance à un en-tête que l'appelant contrôle. Cela compte immédiatement, parce que la décision suivante est de savoir quelle valeur sert de clé au quota.

Le piège de l'accès anonyme

Cela vaut d'être dit clairement, parce que la configuration qui le produit a l'air inoffensive. Qu'une API puisse être appelée sans aucune subscription key dépend de deux réglages indépendants : si l'API elle-même exige une subscription, et si chaque product auquel elle est assignée en exige une. Si l'API n'exige pas de subscription, les appels sans key sont autorisés dans le contexte de l'API, même quand une key à portée product fonctionnerait aussi. La gateway fait exactement ce qu'on lui a dit ; personne ne lui a dit l'intention.

Pour une gateway devant une capacité de modèles payante, la règle est que chaque API exige une subscription et chaque product exige une subscription, et la politique validate-jwt s'exécute quoi qu'il arrive, si bien qu'un appel non authentifié échoue deux fois. Les portées des keys comptent aussi : une key à portée service ou toutes-APIs ouvre chaque API de l'instance, ce qui est juste pour l'outillage de l'équipe plateforme et faux pour un consommateur. Les consommateurs reçoivent des keys à portée product.

Le quota, et contre quoi le compter

La politique de limite de tokens de la partie 1 prend une counter-key, et ce choix est tout le modèle de tenancy. Prendre l'ID de subscription comme clé donne un compartiment par consommateur, exactement ce dont l'incident de la partie 1 avait besoin : le batch job marketing ne peut pas vider le quota de l'assistant client parce que ce sont des subscriptions différentes avec des compteurs différents.

<llm-token-limit counter-key="@(context.Subscription.Id)"
                 tokens-per-minute="{{tpm_tier}}"
                 estimate-prompt-tokens="true"
                 remaining-tokens-variable-name="remainingTokens"
                 remaining-tokens-header-name="x-remaining-tokens" />

Renvoyer l'allocation restante dans un en-tête de réponse vaut les deux attributs supplémentaires. Un client qui voit sa propre marge peut ralentir avant de recevoir un 429, et une conversation de support sur le throttling démarre d'un nombre que les deux côtés peuvent voir.

Les products deviennent les niveaux de service : un product interactif avec une limite par minute élevée et un quota journalier modeste, un product batch avec l'inverse, et un product sandbox avec des limites assez basses pour qu'une boucle emballée dans un notebook soit une nuisance plutôt qu'un incident. Un tenant est une application Entra ID plus une ou plusieurs subscriptions de product, provisionné par le Terraform de la couche 30-tenants de la partie 2, jamais par un ticket.

Le budget de dimensions

Voici la contrainte du chapeau, énoncée comme la règle de design qu'elle produit. Azure Monitor plafonne les métriques custom à 10 clés de dimension, et API Management en utilise 5 pour ses valeurs par défaut, dont Region, Service ID, Service Name et Service Type. Il reste donc au maximum 5 dimensions custom par politique. La limite la plus large est combinatoire : les time series actives égalent le produit des valeurs uniques de vos dimensions sur la période, donc trois dimensions à dix valeurs chacune en apportent mille, et le plafond régional est de 50 000 time series actives par subscription sur douze heures. Plusieurs instances API Management dans la même région contribuent au même total régional.

La conséquence est une séparation nette qui mérite d'être écrite dans la documentation de la plateforme elle-même :

  • Les métriques ne portent que des dimensions à faible cardinalité. Tenant, alias de modèle, environnement. Trois dimensions, des ensembles de valeurs bornés, des dashboards qui chargent vite et des alertes qui se déclenchent sur la bonne chose.
  • Les logs portent tout le reste. ID de requête, ID utilisateur s'il est capturé, tailles de prompt et de complétion, latence, quel backend a servi la requête. Application Insights et Log Analytics sont l'endroit où vit l'attribution par requête, et le job mensuel de chargeback les interroge.
<llm-emit-token-metric namespace="llm-metrics">
  <dimension name="Tenant"      value="@(context.Subscription.Name)" />
  <dimension name="ModelAlias"  value="@(context.Request.MatchedParameters.GetValueOrDefault("model","unknown"))" />
  <dimension name="Environment" value="{{env}}" />
</llm-emit-token-metric>

Trois dimensions, délibérément. La quatrième que quelqu'un demandera est l'ID utilisateur, et la réponse est non : sa place est dans l'enregistrement de log, où la cardinalité coûte du stockage plutôt que le budget de métriques d'une région entière.

Un chargeback qui survit à une discussion avec la finance

Le job mensuel est de l'ingénierie de données ordinaire, et sa crédibilité tient à l'explicitation de son exactitude plutôt qu'à sa précision. Les parties 3 et 4 ont établi trois classes, et le document de chargeback les nomme :

  • Synchrone non streamé : mesuré depuis le usage du modèle lui-même. Exact.
  • Synchrone streamé : tokens de prompt et de complétion estimés à la gateway, parce que le streaming force l'estimation quelle que soit la configuration de la politique. Approximatif, avec la dérive suivie comme sa propre métrique.
  • Batch : exact, à partir des comptes de requêtes du job lui-même et de l'usage par réponse dans le fichier de sortie, parce que le control plane l'a soumis.

Le job produit un chiffre par tenant et une ligne de réconciliation : la somme des dépenses attribuées face au coût réel de la ressource sur la période. Un résidu de quelques pourcents, stable de mois en mois, est le coût honnête de l'estimation. Un résidu qui grandit est un bug, le plus souvent un appelant qui a trouvé un chemin contournant la gateway. Publier le résidu plutôt que le cacher est ce qui rend le reste du chiffre crédible, et il sert en même temps de détecteur pour le chemin de contournement contre lequel la partie 1 mettait en garde.

Quand une équipe a besoin de sa propre gateway

Il arrive que les exigences d'un consommateur ne tiennent pas dans une infrastructure partagée : un workload réglementé qui a besoin de sa propre isolation réseau, ou une équipe qui doit gérer ses propres APIs sans toucher à celles des autres. Les workspaces d'API Management existent pour cela, et le choix se fait entre la gateway managée par défaut du service, disponible dans les niveaux v2 sans coût de gateway supplémentaire et avec l'accès aux capacités intégrées, et une workspace gateway séparée, disponible sur Basic v2, Standard v2, Premium et Premium v2, qui achète une forte isolation à l'exécution et un scaling, un hostname et une configuration réseau indépendants, au prix d'un coût supplémentaire, d'un déploiement plus long et d'un support dans moins de régions.

Un détail décide si c'est réversible : la configuration de réseau virtuel d'une workspace gateway ne peut être définie qu'à la création de la gateway, et ne peut pas être changée ensuite. Sa configuration réseau est aussi indépendante de celle de l'instance API Management. Une workspace gateway créée sans isolation, par une équipe qui en a besoin plus tard, est une reconstruction.

Modes de défaillance à surveiller

  • Une dimension à forte cardinalité dans une politique. Elle ne produira pas d'erreur. Elle consommera en silence le budget de time series actives de la région, et le premier symptôme est que les métriques custom des autres équipes cessent d'apparaître.
  • Des keys qui n'expirent jamais. Il n'y a ni expiration ni rotation intégrées. Sans workflow de rotation, le credential émis pour une application décommissionnée fonctionne toujours, et rien ne le signale.
  • La subscription key dans les logs du backend. Le comportement par défaut la transmet. Retirez-la dans l'inbound, et vérifiez une fois les logs du backend pour confirmer au lieu de supposer.
  • Une API qui n'exige pas de subscription. Un accès anonyme dans le contexte de l'API, atteint par une configuration qui se lit comme permissive plutôt que comme ouverte.
  • Un chargeback publié sans son résidu. La première fois qu'un product owner trouve un écart que vous n'avez pas divulgué, chaque chiffre futur devient négociable.

Ce dont hérite la partie 6

Des tenants avec de vraies identités, des quotas qui tiennent, et un chiffre mensuel par équipe avec une exactitude annoncée. Ce qui pose la question suivante avec précision : le token le moins cher est celui qui n'est jamais envoyé, et le cache sémantique est le premier mécanisme de cette série qui baisse la facture au lieu de simplement l'attribuer. Il change aussi discrètement le sens des chiffres ci-dessus, parce qu'un cache hit est une requête qui n'a rien coûté et qui doit quand même apparaître dans le rapport de quelqu'un.

À lire ensuite

Pour le volet infrastructure et plateforme de l'exploitation de tout cela à grande échelle, les notes de terrain sont sur ercan.cloud, et le hub se trouve sur ercanermis.com.

Références