Une grande DSI a cinq applications d'IA générative en production, onze déploiements de modèles répartis sur trois abonnements Azure, une facture mensuelle d'environ 38 000 euros, et aucun moyen fiable de dire laquelle des cinq l'a dépensée. Rien n'est cassé. Chaque app fonctionne, chaque équipe a livré, chaque revue de sécurité est passée en son temps. Ce qui n'existe pas, c'est un endroit unique où un token est compté, où un appelant est identifié, où un modèle est retiré, et c'est cette absence que cette série en dix parties construit : une gateway GenAI gouvernée sur Azure par laquelle chaque application passe, et que rien ne contourne.

L'entreprise, et ce qu'elle paie réellement

Appelons l'entreprise par son nom : une DSI établie, environ 400 ingénieurs répartis sur une quarantaine d'équipes produit, la plupart des workloads sur Azure, un groupe plateforme qui possède déjà les landing zones et les templates CI. L'IA générative est arrivée comme elle arrive d'habitude, par les bords. Un assistant de service client a été livré en premier parce qu'un product owner avait du budget. Puis un résumeur d'exploitation IT, un assistant de code interne, une recherche documentaire retail sur la documentation produit, et un outil de rédaction marketing. Cinq équipes, cinq décisions, cinq intégrations directes contre Azure OpenAI.

Chacune de ces décisions était correcte prise isolément. Ensemble, elles produisent une forme précise et désormais familière :

  • Onze déploiements de modèles répartis sur trois abonnements. Deux d'entre eux sont des doublons du même modèle dans la même région, créés parce qu'une équipe n'arrivait pas à obtenir de quota attaché à la ressource qu'elle avait déjà.
  • Environ 38 000 euros par mois de dépense modèles que la gestion des coûts rapporte à la granularité de l'abonnement, ce qui veut dire qu'elle peut donner le total à la finance et ne peut donner à aucun product owner son propre chiffre.
  • Quatre des cinq apps gardent une clé dans les paramètres d'application. L'une la gardait dans un dépôt jusqu'à ce qu'un scanner de secrets la trouve. Aucune app ne peut être révoquée individuellement sans qu'un ingénieur modifie la configuration de cette app.
  • Un préavis de retrait de modèle de 60 jours est arrivé par e-mail, et le groupe plateforme a passé deux jours à faire du grep dans les dépôts pour déterminer quelles applications casseraient, parce que rien n'enregistrait quelle app appelait quelle version de modèle.

Puis l'incident qui a réellement forcé la décision. Un job batch de l'outil de rédaction marketing a consommé la majeure partie du quota tokens-per-minute d'un déploiement partagé pendant environ quarante minutes. L'assistant de service client, qui partageait ce déploiement, s'est mis à renvoyer des HTTP 429 à de vrais clients. Aucune des deux équipes n'a rien fait de mal. Il n'existait aucun mécanisme sur le chemin où exprimer « un appelant ne doit pas épuiser le quota dont un autre appelant dépend », parce qu'il n'existait aucun chemin partagé du tout.

Voilà l'argument honnête pour une gateway. Pas « le contrôle centralisé est une bonne architecture ». C'est que le quota, l'attribution des coûts, la rotation des identifiants et le cycle de vie des modèles sont tous des propriétés de l'appel, et si aucun composant ne voit tous les appels, aucune de ces propriétés ne peut être imposée nulle part, sinon par convention.

Ce que le schéma par application coûte réellement

L'intégration directe est réellement moins chère le premier jour. Un client SDK, une clé, un endpoint, pas d'équipe plateforme sur le chemin critique. Le coût arrive plus tard et atterrit ailleurs que chez l'équipe qui a fait ce choix, ce qui est exactement la raison pour laquelle ce choix continue d'être fait.

Les coûts qui s'accumulent sont au nombre de trois, et ce sont tous le même coût sous des habits différents. Le coût du changement : un retrait de modèle, un changement de prix, une migration de région ou une panne de fournisseur doit être géré une fois par application, par cinq équipes avec cinq backlogs et cinq niveaux d'intérêt différents. Le coût d'attribution : la dépense est visible par ressource et invisible par consommateur, donc personne ne peut recevoir de budget, ce qui veut dire que personne ne peut recevoir de limite. Le coût de gouvernance : chaque nouveau contrôle, la journalisation des prompts, le caviardage des PII, une exigence de transparence de l'EU AI Act, doit être implémenté cinq fois et vérifié cinq fois, et l'effort de revue croît avec le nombre d'applications plutôt qu'avec le nombre de contrôles.

Une gateway ne supprime pas ces coûts. Elle les déplace vers un seul endroit où une équipe plateforme peut les payer une fois. C'est tout l'argument, et toute version plus ambitieuse de cet argument mérite la méfiance.

Construire ou acheter sur Azure

L'équipe a évalué trois formes, et la réponse n'est pas celle qu'un ingénieur voudrait.

Azure API Management comme gateway IA. API Management livre un ensemble de capacités explicitement destinées au trafic des modèles de langage, et la liste est plus longue que ce que la plupart des gens supposent avant de la lire. La politique llm-token-limit impose des tokens-per-minute ou un quota de tokens par heure, jour, semaine, mois ou année contre n'importe quelle clé de compteur, y compris une clé d'abonnement, une IP d'appelant ou une expression de politique arbitraire, et elle peut précalculer les tokens du prompt sur la gateway pour qu'une requête au-dessus de la limite n'atteigne jamais le backend. Les politiques llm-semantic-cache-store et llm-semantic-cache-lookup font du cache de complétions par similarité vectorielle contre Azure Managed Redis ou un autre cache compatible RediSearch. La politique llm-emit-token-metric émet les comptes de tokens vers Application Insights avec des dimensions personnalisées, ce qui est la matière première de l'attribution par consommateur. Les backends supportent l'équilibrage round-robin, pondéré, par priorité et sensible à la session, ainsi qu'un circuit breaker dont la durée de coupure respecte l'en-tête Retry-After du backend lui-même, si bien qu'un endpoint pay-as-you-go peut absorber le débordement d'un déploiement Provisioned Throughput Unit saturé sans que personne n'écrive de code de retry.

La couverture des fournisseurs compte ici, et il est facile de se tromper. API Management sert d'intermédiaire pour les API de modèles de langage conformes aux schémas OpenAI Chat Completions et Responses, à l'API Anthropic Messages (dans les tiers v2) et à l'API Google Vertex AI, face à des modèles déployés dans Microsoft Foundry ou chez des fournisseurs non Microsoft, dont Amazon Bedrock. Une API de modèle unifiée, en préversion au moment où ces lignes sont écrites, expose plusieurs backends derrière un seul endpoint compatible OpenAI et traduit les formats, si bien qu'un même jeu de politiques de gouvernance s'applique à tous les fournisseurs. Anthropic Claude, Mistral et Llama sont accessibles via cette couche plutôt que d'exiger chacun une intégration séparée.

Un proxy open source sur AKS. LiteLLM et les projets similaires donnent la traduction de fournisseurs et le routage dans un conteneur que vous contrôlez entièrement, avec un chemin plus rapide vers une fonctionnalité voulue et aucune dépendance à une préversion. Vous héritez d'une rotation d'astreinte pour un composant qui se trouve désormais devant chaque requête IA de l'entreprise, plus le travail d'identité, de réseau et d'audit qu'API Management a déjà fait certifier.

Un service FastAPI sur mesure. Le contrôle maximal, et la seule option où chaque défaillance est la vôtre. Raisonnable pour un composant aux exigences réellement inhabituelles, ce qu'un reverse proxy compteur de tokens n'est pas.

La décision que cette série suit : API Management est le data plane, et ce qu'API Management ne fait pas est construit sous la forme d'un petit control plane Python sur AKS. C'est la séparation qu'il faut intérioriser, parce que c'est là que la plupart des projets de gateway échouent. Soit les équipes essaient de tout exprimer en XML de politique, ce qui produit un artefact impossible à maintenir que personne ne peut tester, soit elles font passer le trafic par leur propre service et réimplémentent mal la limitation de débit. La gateway porte la requête. Le control plane porte l'état : quels modèles existent, qui peut les appeler, ce qu'un appel coûte, et ce qui se passe quand un modèle est retiré.

Ce qu'il reste à construire

Cinq choses, et chacune d'elles est une partie ultérieure de cette série.

  • Un catalogue de modèles et leur cycle de vie. Quels noms logiques de modèles existent, quels déploiements physiques les portent, lesquels sont dépréciés et quand ils disparaissent. Les applications doivent appeler chat-default, jamais un nom de déploiement, sinon l'e-mail de retrait à 60 jours redevient un projet de migration de 60 jours.
  • L'identité des tenants et leur onboarding. Une équipe reçoit un identifiant client, un quota, une liste blanche de modèles et un centre de coûts, provisionnés comme du code plutôt que comme un ticket.
  • L'attribution des coûts et la refacturation. Les métriques de tokens avec une dimension tenant ne sont que l'entrée. En faire un chiffre mensuel par équipe que la finance accepte est un pipeline de données avec ses propres tests.
  • Des portes d'évaluation dans le pipeline. Promouvoir une nouvelle version de modèle est un déploiement. Un déploiement qui change le comportement du modèle sans résultat d'éval attaché est une panne qui attend qu'un client la trouve.
  • Le travail asynchrone et de longue durée. La synthèse en batch des tickets de support n'a pas sa place sur le même chemin synchrone qu'un client qui attend son premier token. Cette séparation est une file de messages, pas un réglage de timeout.

Architecture cible

La plateforme est délibérément ennuyeuse et délibérément additive. Si le control plane est en panne, le data plane continue de servir le trafic sur sa dernière configuration connue, parce qu'une gateway qui se ferme sur une panne du control plane est une panne à l'échelle de l'entreprise.

graph TD
  subgraph consumers["Consumer apps"]
    A1["customer-service assistant"]
    A2["IT-ops summarizer"]
    A3["code assistant"]
    A4["retail knowledge search"]
    A5["marketing copy tool"]
  end

  subgraph gw["Data plane: API Management"]
    POL["policies:
llm-token-limit, semantic cache,
emit-token-metric, JWT validate"] LB["backend pool:
priority + weighted, circuit breaker"] end subgraph cp["Control plane: Python on AKS"] CAT["model catalog"] TEN["tenant registry"] COST["cost attribution job"] end subgraph models["Model layer"] FDRY["Microsoft Foundry:
GPT deployments, PTU + PAYG"] ANTH["Anthropic Claude"] OSS["Mistral, Llama"] end ID["Microsoft Entra ID"] RED["Azure Managed Redis
semantic cache"] SRCH["Azure AI Search
retrieval"] MON["Azure Monitor +
Application Insights"] A1 --> POL A2 --> POL A3 --> POL A4 --> POL A5 --> POL ID -. "OAuth2 client credentials" .-> POL POL --> LB POL <--> RED LB --> FDRY LB --> ANTH LB --> OSS POL -- token metrics, prompt logs --> MON CAT -. "backend + policy config" .-> gw TEN -. "subscriptions, quotas" .-> gw MON --> COST A4 -. "grounding data" .-> SRCH

Deux propriétés de ce diagramme portent la charge. D'abord, chaque flèche vers la couche modèles part de l'intérieur d'API Management, ce qui veut dire que les règles réseau sur les ressources Foundry refusent tout le reste : la gateway n'est pas une suggestion, c'est la seule route qui dispose d'un chemin. Ensuite, le control plane écrit la configuration dans la gateway et lit la télémétrie depuis Azure Monitor, mais ne se trouve jamais sur le chemin de la requête. Il peut être redéployé à midi.

La stack, en un seul endroit

Ce que les dix parties touchent, pour que la forme de la série soit visible dès maintenant. L'infrastructure as code en Terraform, avec la comparaison Bicep et ARM menée honnêtement dans la partie 2 plutôt qu'évacuée d'office. Des images Docker et AKS pour le control plane. Azure DevOps pour les pipelines, le versionnage et la gestion des releases. Python partout où vit la logique. Microsoft Entra ID avec OAuth2 client credentials, et des clés API là où un appelant legacy ne peut pas faire mieux. Azure AI Search et une base vectorielle dédiée pour la récupération, comparées plutôt que décrétées. Azure Managed Redis pour le cache sémantique. Azure Monitor et Application Insights pour la télémétrie, aux côtés d'une observabilité spécifique aux LLM dans LangSmith et Openlayer, et Dataiku là où une équipe data science vit déjà. LangChain pour l'orchestration dans la seule partie où un framework mérite sa place, et dans celles où il ne la mérite pas. Le streaming en server-sent events, WebSockets là où une session est réellement bidirectionnelle, et une file de messages pour tout ce qui n'a pas besoin d'une réponse tout de suite.

Les dix parties, dans l'ordre : l'argumentaire pour une gateway ; Terraform face à Bicep et ARM ; l'abstraction de fournisseur et le streaming ; le travail asynchrone et événementiel ; identité, quota et refacturation ; le cache sémantique ; la récupération avec Azure AI Search face à une vraie base vectorielle ; l'orchestration au-dessus de la gateway ; la CI/CD et le cycle de vie des modèles dans Azure DevOps ; et l'observabilité avec la gouvernance de l'IA.

À quoi ressemble le résultat visé

La dernière partie revient sur ces points, les chiffres de l'inventaire plus haut rendus mesurables :

  • Chaque product owner peut voir sa propre dépense de tokens pour le mois en cours, dans la journée qui suit la dépense, sans rien demander à l'équipe plateforme.
  • Aucune application ne détient d'identifiant de modèle longue durée. Révoquer l'accès d'une équipe est un changement de configuration dans le registre des tenants, pas une modification des paramètres d'application de cette équipe.
  • Un préavis de retrait de modèle produit une requête, pas une enquête : le catalogue sait déjà quels tenants ont résolu vers ce déploiement au cours des 30 derniers jours.
  • Un tenant ne peut pas épuiser le quota d'un autre tenant, vérifié en rejouant l'incident 429 ci-dessus comme test de charge contre la gateway.
  • La latence médiane ajoutée par la gateway reste sous les 60 millisecondes au 95e percentile pour les appels non mis en cache, et les hits du cache sémantique reviennent en une fraction d'un appel de modèle.

Modes de défaillance à surveiller dès le premier jour

Trois, et ils méritent d'être nommés avant d'écrire le moindre Terraform. La gateway devient un point de défaillance unique dès l'instant où elle est la seule route, ce qui est le but recherché, donc son objectif de disponibilité doit être plus élevé que celui de l'application la plus exigeante derrière elle, et son déploiement doit être redondant entre zones dès le premier apply plutôt qu'après le premier incident. La prolifération des politiques arrive sans bruit : le XML de politique est du code, il est exécuté à chaque requête, et il est facile de l'écrire à un endroit où personne ne le relit. Sa place est dans le contrôle de version avec le reste de la plateforme, appliqué par pipeline, jamais modifié dans le portail. Et le chemin de contournement ruine tout le reste, parce qu'une seule équipe qui garde une clé directe vers un endpoint Foundry rend approximatifs chaque chiffre d'attribution et chaque garantie de quota. C'est une règle réseau et une alerte, pas un document de politique interne.

À 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