Aller au contenu principal

Azure en production

Mis à jour le 29 juillet 2026

Préparer un déploiement Azure robuste

Un prototype qui fonctionne sur votre poste et un système de production ne diffèrent pas par le code d’appel, qui reste identique, mais par tout ce qui l’entoure : d’où viennent les secrets, comment on observe ce qui se passe, ce qui arrive quand le trafic double, et par quel chemin réseau transitent les données. Cette leçon parcourt ces quatre dimensions pour un déploiement Mistral sur Azure.

Architecture de production

Un déploiement typique articule cinq briques. L’endpoint Azure AI héberge le modèle Mistral en MaaS ; Azure Key Vault conserve les clés API ; Azure Monitor et Application Insights assurent l’observabilité ; Azure API Management joue le rôle de gateway avec throttling et authentification devant votre application ; enfin, un Azure Virtual Network apporte l’isolation réseau, optionnelle mais souvent exigée dès que les données sont sensibles.

Le premier réflexe consiste à sortir les secrets du code et des variables d’environnement pour les faire lire au démarrage depuis Key Vault.

from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
from mistralai import MistralAzure

# Récupérer la clé API depuis Key Vault
credential = DefaultAzureCredential()
vault_url = "https://mon-keyvault.vault.azure.net"
secret_client = SecretClient(vault_url=vault_url, credential=credential)

endpoint = secret_client.get_secret("mistral-endpoint").value
api_key = secret_client.get_secret("mistral-api-key").value

client = MistralAzure(azure_endpoint=endpoint, azure_api_key=api_key)

L’intérêt dépasse la simple confidentialité : le jour où vous faites tourner la clé, aucun redéploiement applicatif n’est nécessaire, puisque la valeur est lue dans le coffre et non figée dans une configuration.

Monitoring avec Application Insights

Sans instrumentation, la seule chose que vous saurez d’un incident, c’est qu’un utilisateur trouve l’application « lente ». Tracer chaque appel avec sa durée, ses tokens et son modèle vous donne au contraire de quoi répondre en quelques minutes.

import time
import logging
from opencensus.ext.azure.log_exporter import AzureLogHandler

logger = logging.getLogger(__name__)
logger.addHandler(AzureLogHandler(
    connection_string="InstrumentationKey=votre-clé"
))

def monitored_call(client, messages, model="azureai"):
    """Appel Mistral avec métriques Azure Monitor."""
    start = time.time()
    try:
        response = client.chat.complete(model=model, messages=messages)
        duration = time.time() - start
        logger.info(
            "MistralCall",
            extra={
                "custom_dimensions": {
                    "duration_ms": int(duration * 1000),
                    "prompt_tokens": response.usage.prompt_tokens,
                    "completion_tokens": response.usage.completion_tokens,
                    "model": model
                }
            }
        )
        return response
    except Exception as e:
        duration = time.time() - start
        logger.error(
            f"MistralError: {e}",
            extra={
                "custom_dimensions": {
                    "duration_ms": int(duration * 1000),
                    "error_type": type(e).__name__
                }
            }
        )
        raise

Ces métriques ne valent que si quelqu’un les regarde. Configurez donc dans Azure Monitor les alertes correspondantes :

  • Latence P95 > 5s — dégradation des performances
  • Taux d’erreurs 5xx > 1% — problèmes côté serveur
  • Erreurs 429 > 10/min — rate limiting atteint
  • Consommation tokens > 80% quota — approche de la limite

Scalabilité

Quand le volume grimpe, la première erreur consiste à appeler le modèle de façon synchrone depuis la requête HTTP entrante : le moindre ralentissement se propage jusqu’à l’utilisateur. Découpler avec Azure Service Bus permet d’absorber les pics — les requêtes s’accumulent dans une file et sont consommées au rythme que votre quota autorise.

from azure.servicebus import ServiceBusClient, ServiceBusMessage
import json

# Producteur : envoyer les requêtes dans la queue
def enqueue_request(prompt: str, request_id: str):
    with ServiceBusClient.from_connection_string(conn_str) as sb_client:
        sender = sb_client.get_queue_sender(queue_name="mistral-requests")
        message = ServiceBusMessage(
            json.dumps({"prompt": prompt, "request_id": request_id})
        )
        sender.send_messages(message)

# Consommateur : traiter les requêtes depuis la queue
def process_queue():
    with ServiceBusClient.from_connection_string(conn_str) as sb_client:
        receiver = sb_client.get_queue_receiver(queue_name="mistral-requests")
        for msg in receiver:
            data = json.loads(str(msg))
            response = client.chat.complete(
                model="azureai",
                messages=[{"role": "user", "content": data["prompt"]}]
            )
            # Stocker le résultat...
            receiver.complete_message(msg)

Si le goulot d’étranglement vient du débit lui-même et non de la charge instantanée, déployez plusieurs endpoints du même modèle et répartissez les appels entre eux.

import random

endpoints = [
    {"url": os.environ["AZUREAI_ENDPOINT_1"], "key": os.environ["AZUREAI_KEY_1"]},
    {"url": os.environ["AZUREAI_ENDPOINT_2"], "key": os.environ["AZUREAI_KEY_2"]},
]

def get_client():
    """Round-robin simple sur les endpoints."""
    ep = random.choice(endpoints)
    return MistralAzure(azure_endpoint=ep["url"], azure_api_key=ep["key"])

Sécurité réseau

Pour les données sensibles, Azure Private Link garantit que le trafic entre votre application et l’endpoint Mistral ne traverse jamais l’Internet public. La configuration se déroule en quatre temps :

  1. Créez un Private Endpoint dans votre VNet
  2. Liez-le à votre ressource Azure AI
  3. Désactivez l’accès public sur l’endpoint
  4. Configurez un DNS privé pour la résolution

La troisième étape est celle que l’on oublie, et sans elle le chemin public reste ouvert en parallèle : le Private Link existe, mais rien n’empêche d’y échapper.

Dans le même esprit, une Managed Identity supprime la clé API du dispositif. L’application obtient un token auprès d’Azure et le présente comme clé, ce qui vous dispense de stocker et de faire tourner un secret de plus.

from azure.identity import ManagedIdentityCredential

credential = ManagedIdentityCredential()
token = credential.get_token("https://cognitiveservices.azure.com/.default")

# Utiliser le token comme clé API
client = MistralAzure(
    azure_endpoint=os.environ["AZUREAI_ENDPOINT"],
    azure_api_key=token.token
)

Checklist de mise en production

Avant de déclarer votre déploiement prêt, reprenez la chaîne dans l’ordre où elle a été construite. Les variables d’environnement et les secrets doivent avoir migré vers Key Vault, et le code d’appel être protégé par un retry exponentiel couvrant aussi bien les erreurs 429 que les 5xx. Le monitoring Application Insights doit remonter latence, erreurs et tokens, et les alertes correspondantes être réellement configurées sur les métriques critiques — pas seulement envisagées. Vient enfin ce que l’on repousse volontiers : des tests de charge effectivement passés, un accès réseau privé si les données sont sensibles, et une rotation des clés API planifiée avec une date, non laissée à l’appréciation générale.

Points clés à retenir

  • Utilisez Azure Key Vault pour stocker les clés API, pas des variables d’environnement en clair
  • Monitorez chaque appel avec Application Insights (latence, tokens, erreurs)
  • Découplage avec Service Bus pour les workloads à fort volume
  • Private Link et Managed Identity pour les environnements sécurisés
  • Testez la charge et configurez des alertes avant de passer en production