Solution française • Hébergement souverain • Conformité européenne Blog IA souveraine

Architecture de référence LLM souverain on-premise — schéma complet 2026

Déployer un LLM en production dans votre datacenter ne s'improvise pas. Entre le choix des GPU, la stack logicielle, la gestion de l'identité et la haute disponibilité, les décisions d'architecture structurent la réussite ou l'échec du projet. Ce guide présente une architecture de référence complète, couche par couche, avec les choix technologiques justifiés et les configurations de sizing pour 100, 500 et 1000 utilisateurs concurrents.

Vue d'ensemble en couches

Une architecture LLM souveraine on-premise se décompose en six couches fonctionnelles distinctes, chacune avec ses responsabilités et ses interdépendances. Le schéma ci-dessous représente l'architecture cible pour une organisation de 200 à 2000 collaborateurs.

┌─────────────────────────────────────────────────────────────────┐
│                     COUCHE APPLICATIONS                         │
│  Chat UI (Open WebUI)  │  Apps métier  │  IDE plugins (Continue)│
└───────────────┬────────────────────────────────────────────────┘
                │ HTTPS / WebSocket
┌───────────────▼─────────────────────────────────────────────────┐
│                     COUCHE API GATEWAY                           │
│   Kong OSS  ─ Rate limiting ─ JWT auth ─ Audit logs ─ Routing   │
└───────────────┬─────────────────────────────────────────────────┘
                │ HTTP/2
┌───────────────▼─────────────────────────────────────────────────┐
│                  COUCHE ORCHESTRATION LLM                        │
│   LangChain / LlamaIndex ─ RAG pipeline ─ Agent frameworks      │
└──────┬────────────────────────────────────┬───────────────────┘
       │ OpenAI-compat API                  │ Vector search
┌──────▼───────────────┐        ┌───────────▼──────────────────┐
│   COUCHE SERVING LLM │        │   COUCHE DONNÉES VECTORIELLES │
│  vLLM 0.4 (primary)  │        │  Milvus 2.4 / Qdrant 1.9     │
│  Ray Serve (scaling)  │        │  MinIO (stockage objets)      │
│  2-4 nodes GPU        │        │  PostgreSQL (métadonnées)     │
└──────┬───────────────┘        └──────────────────────────────┘
       │ CUDA / NVLink
┌──────▼───────────────────────────────────────────────────────────┐
│               COUCHE INFRASTRUCTURE GPU                          │
│  Nodes: 4× H100 80GB SXM5  │  NVMe NVLink switch               │
│  CPU: 2× AMD EPYC 9654     │  RAM: 768 GB DDR5 ECC             │
│  Réseau: 2× 100GbE RDMA    │  Storage: 8× 3.84TB NVMe U.2     │
└──────────────────────────────────────────────────────────────────┘
       │
┌──────▼───────────────────────────────────────────────────────────┐
│               COUCHE IAM & SÉCURITÉ                              │
│  Keycloak 24  ─ LDAP/AD sync ─ OAuth2/OIDC ─ MFA               │
│  HashiCorp Vault ─ Secrets ─ PKI interne ─ Encryption at rest   │
└──────────────────────────────────────────────────────────────────┘
6couches fonctionnelles
80 GBVRAM par H100 SXM5
100 GbEréseau RDMA inter-nodes
<200 mslatence P95 cible

Choix GPU : H100 vs A100 vs L40S

Le GPU est le composant le plus structurant de l'architecture. Son choix conditionne la taille des modèles supportés, les performances d'inférence et le budget sur 3-5 ans. Voici une analyse comparative des trois options principales disponibles en France en 2026.

GPUVRAMBF16 TFLOPSBande passante mémoirePrix achat (€)Dispo France
H100 SXM580 GB HBM31 9793.35 TB/s~28 000–35 000Via OVHcloud, Scaleway
H100 PCIe80 GB HBM2e1 5132.0 TB/s~22 000–28 000Bonne disponibilité
A100 SXM480 GB HBM2e3122.0 TB/s~14 000–18 000Marché secondaire
A100 PCIe40 GB HBM2e3121.55 TB/s~8 000–12 000Bonne disponibilité
L40S48 GB GDDR6366864 GB/s~9 000–12 000Très bonne dispo

Ce qu'il faut retenir

  • H100 SXM5 : meilleur rapport performance/VRAM, indispensable pour les modèles 70B en FP16. Privilégier pour la production haute charge.
  • A100 80 GB : excellent choix secondaire pour modèles 32B (ELODIE, Mistral), coût d'achat 35-40% inférieur au H100.
  • L40S : GPU « inference-optimisé » GDDR6, idéal pour les modèles quantisés INT8 ≤ 32B. Meilleur TCO pour usage modéré.
  • Règle de sizing : un modèle 32B en BF16 requiert ~64 GB VRAM ; en INT8, ~32 GB ; en INT4, ~16 GB.

Pour un déploiement du modèle ELODIE 32B ou KEVINA 32B en production avec 100 utilisateurs concurrents, 2× A100 80 GB (ou 2× H100 PCIe) constituent le minimum viable. Pour 500 utilisateurs, il faut passer à 4× H100 avec Ray Serve en mode distribué.

Calcul VRAM par modèle

La formule standard pour estimer la VRAM nécessaire :

# VRAM estimation formula
# params_billions: nombre de paramètres en milliards
# precision: 2 (BF16/FP16), 1 (INT8), 0.5 (INT4)
# kv_cache_factor: overhead KV cache (typiquement 1.2)

def estimate_vram_gb(params_billions, precision_bytes=2, kv_cache_factor=1.2):
    model_size_gb = params_billions * precision_bytes
    total_vram = model_size_gb * kv_cache_factor
    return round(total_vram, 1)

# Exemples
print(f"ELODIE 32B BF16: {estimate_vram_gb(32, 2)} GB")   # 76.8 GB → 2× A100 40GB
print(f"ELODIE 32B INT8: {estimate_vram_gb(32, 1)} GB")   # 38.4 GB → 1× A100 40GB
print(f"ELODIE 32B INT4: {estimate_vram_gb(32, 0.5)} GB") # 19.2 GB → 1× L40S
print(f"Llama 3.3 70B BF16: {estimate_vram_gb(70, 2)} GB") # 168 GB → 3× H100 80GB
print(f"Llama 3.3 70B INT8: {estimate_vram_gb(70, 1)} GB") # 84 GB → 2× H100 80GB

Stack logicielle complète

Chaque couche logicielle de l'architecture correspond à un composant open source éprouvé en production. Voici le détail complet avec les versions recommandées en 2026.

Serving LLM : vLLM 0.4+

vLLM est le moteur d'inférence de référence pour les LLM en production. Sa fonctionnalité clé, le PagedAttention, permet de gérer la mémoire KV cache de manière dynamique — similaire à la pagination mémoire d'un OS — éliminant la fragmentation et multipliant le débit par 2 à 4× comparé à Hugging Face Transformers naïf.

# Installation vLLM 0.4.x sur Ubuntu 22.04 + CUDA 12.3
pip install vllm==0.4.3

# Lancement serving ELODIE 32B en BF16 sur 2 GPU
python -m vllm.entrypoints.openai.api_server \
  --model /models/elodie-32b \
  --tensor-parallel-size 2 \
  --dtype bfloat16 \
  --max-model-len 8192 \
  --max-num-seqs 256 \
  --host 0.0.0.0 \
  --port 8000 \
  --api-key "${VLLM_API_KEY}" \
  --enable-prefix-caching \
  --gpu-memory-utilization 0.90

Scaling horizontal : Ray Serve

Ray Serve permet de distribuer la charge sur plusieurs nœuds GPU et d'implémenter des stratégies de routing avancées (round-robin, least-loaded, affinity). Il s'intègre nativement avec vLLM depuis la version 0.4.

# ray_serve_llm.py — déploiement Ray Serve + vLLM
import ray
from ray import serve
from vllm import AsyncLLMEngine, SamplingParams
from vllm.engine.arg_utils import AsyncEngineArgs

@serve.deployment(
    num_replicas=2,
    ray_actor_options={"num_gpus": 2},
    max_concurrent_queries=50
)
class ELODIEDeployment:
    def __init__(self):
        engine_args = AsyncEngineArgs(
            model="/models/elodie-32b",
            tensor_parallel_size=2,
            dtype="bfloat16",
            max_model_len=8192,
            gpu_memory_utilization=0.90,
            enable_prefix_caching=True
        )
        self.engine = AsyncLLMEngine.from_engine_args(engine_args)

    async def __call__(self, request):
        data = await request.json()
        prompt = data["prompt"]
        sampling_params = SamplingParams(
            temperature=data.get("temperature", 0.7),
            max_tokens=data.get("max_tokens", 2048),
            top_p=data.get("top_p", 0.9)
        )
        results = []
        async for output in self.engine.generate(prompt, sampling_params, request_id="req"):
            results.append(output)
        return {"text": results[-1].outputs[0].text}

ray.init(address="auto")
serve.start(http_options={"host": "0.0.0.0", "port": 8001})
handle = serve.run(ELODIEDeployment.bind())

VectorDB : Milvus 2.4 vs Qdrant 1.9

CritèreMilvus 2.4Qdrant 1.9PGVector 0.7
ArchitectureDistribué (etcd + MinIO)Standalone ou clusterExtension PostgreSQL
Index supportésHNSW, IVF_FLAT, DISKANNHNSW, ScaNNHNSW, IVF
Performance 1M vecteurs2-5 ms P991-3 ms P9910-50 ms P99
Filtrage métadonnéesExcellentExcellentNatif SQL
ScalabilitéMilliards de vecteurs100M+ vecteurs10M vecteurs max
OpérationnelComplexe (Helm chart)Simple (binaire Rust)Très simple

Stockage objets : MinIO

# docker-compose.yml — MinIO haute disponibilité (4 nœuds)
version: '3.8'
services:
  minio1:
    image: minio/minio:RELEASE.2024-03-15T01-07-19Z
    command: server http://minio{1...4}/data{1...2} --console-address ":9001"
    environment:
      MINIO_ROOT_USER: "${MINIO_ACCESS_KEY}"
      MINIO_ROOT_PASSWORD: "${MINIO_SECRET_KEY}"
      MINIO_VOLUMES: "/data1 /data2"
    volumes:
      - /nvme/minio/data1:/data1
      - /nvme/minio/data2:/data2
    ports:
      - "9000:9000"
      - "9001:9001"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3

IAM : Keycloak 24

Keycloak gère l'authentification centralisée avec synchronisation Active Directory/LDAP, émission de tokens JWT, et support du protocole OIDC pour l'API Gateway.

# keycloak-realm-config.json — configuration realm LLM
{
  "realm": "intelligence-privee",
  "enabled": true,
  "sslRequired": "external",
  "clients": [
    {
      "clientId": "llm-api",
      "protocol": "openid-connect",
      "publicClient": false,
      "authorizationServicesEnabled": true,
      "directAccessGrantsEnabled": false,
      "standardFlowEnabled": true
    }
  ],
  "roles": {
    "realm": [
      {"name": "llm-user", "description": "Accès standard LLM"},
      {"name": "llm-power", "description": "Modèles avancés + contexte étendu"},
      {"name": "llm-admin", "description": "Administration et monitoring"}
    ]
  },
  "ldapFederationProviders": [
    {
      "name": "AD-Sync",
      "providerType": "ldap",
      "connectionUrl": "ldaps://ad.entreprise.fr:636",
      "syncPeriod": 3600
    }
  ]
}

Réseau isolé et sécurité

L'isolation réseau est fondamentale pour une infrastructure LLM souveraine. L'architecture recommandée utilise un VLAN dédié pour les nœuds GPU, complètement isolé du réseau bureautique.

RÉSEAU BUREAUTIQUE (VLAN 100 — 10.10.0.0/24)
         │
    [Firewall/UTM]
         │ DMZ
    [Load Balancer] ──── VLAN 200 — 10.20.0.0/24
         │               └── Kong API Gateway
         │               └── Open WebUI
         │
    [API Gateway] ──────  VLAN 300 — 10.30.0.0/24 (INTERNE SÉCURISÉ)
                          └── Ray Serve Cluster
                          └── vLLM nodes (GPU)
                          └── Keycloak
                          │
                     VLAN 400 — 10.40.0.0/24 (DONNÉES)
                          └── Milvus / Qdrant
                          └── MinIO
                          └── PostgreSQL
                          └── HashiCorp Vault

Isolation réseau obligatoire

Les nœuds GPU (VLAN 300) ne doivent jamais être directement accessibles depuis le réseau bureautique. Tout trafic transite par l'API Gateway authentifiée. Activez le chiffrement inter-nœuds avec WireGuard ou IPSec pour les communications Ray Serve distribué.

Chiffrement au repos

# Chiffrement LUKS pour les volumes NVMe de modèles
cryptsetup luksFormat --type luks2 --key-size 512 \
  --hash sha512 --iter-time 5000 /dev/nvme0n1

# Montage automatique via clevis + TPM2
clevis luks bind -d /dev/nvme0n1 tpm2 '{"pcr_bank":"sha256","pcr_ids":"0,1,7"}'

# Vérification
clevis luks list -d /dev/nvme0n1

Haute disponibilité et backups

Une infrastructure LLM de production doit viser un SLA de 99.9% (8.7h de downtime/an maximum). Cela impose une architecture HA sur toutes les couches critiques.

# Architecture HA — composants redondés

API Gateway (Kong):
  - Mode: active-active, 2 instances minimum
  - Load balancer: HAProxy ou Keepalived VIP
  - Config sync: Kong DB mode (PostgreSQL cluster)

vLLM / Ray Serve:
  - Mode: multi-replica via Ray
  - Failover: automatique (Ray détecte les nœuds down)
  - Modèles stockés sur MinIO (partagé NFS-over-RDMA)

Keycloak:
  - Mode: cluster Infinispan (cache distribué)
  - DB: PostgreSQL en streaming replication
  - Instances: 2 minimum, 3 recommandé

Milvus:
  - Mode: cluster (etcd x3, MinIO HA, QueryNode x2)
  - Backup: snapshot S3-compatible vers MinIO secondaire

MinIO:
  - Mode: erasure coding (4 nœuds, parité 2+2)
  - RPO: 0 (réplication synchrone)
  - RTO: < 30 secondes (bascule automatique)

Stratégie de backup

# Backup quotidien des modèles et configurations
#!/bin/bash
BACKUP_DATE=$(date +%Y%m%d)
BACKUP_BUCKET="s3://backup-llm-$(hostname)"

# 1. Snapshot Milvus
milvus-backup create --name "backup-${BACKUP_DATE}" \
  --config /etc/milvus/backup.yaml

# 2. Export config Keycloak
/opt/keycloak/bin/kc.sh export \
  --dir /backup/keycloak/${BACKUP_DATE} \
  --realm intelligence-privee

# 3. Sync vers MinIO secondaire
mc mirror --overwrite /backup/ \
  minio-secondary/${BACKUP_BUCKET}/

# 4. Vérification intégrité
mc stat minio-secondary/${BACKUP_BUCKET}/keycloak/${BACKUP_DATE}/
echo "Backup ${BACKUP_DATE} completed" | \
  curl -X POST "${ALERTMANAGER_URL}/api/v1/alerts" -d @-

Sizing : 100, 500 et 1000 utilisateurs concurrents

Le sizing d'une infrastructure LLM dépend de plusieurs variables : taille du modèle, longueur moyenne des contextes, temps de réponse attendu, et pic de charge simultanée. Voici trois configurations de référence validées en production.

Paramètre100 utilisateurs500 utilisateurs1000 utilisateurs
GPU nodes1× serveur 2× A100 80GB2× serveurs 4× H100 80GB4× serveurs 4× H100 80GB
VRAM totale160 GB640 GB1 280 GB
CPU (total vCores)64256512
RAM système512 GB2 TB4 TB
Stockage NVMe10 TB40 TB80 TB
Réseau inter-nœuds10 GbE100 GbE RDMA200 GbE InfiniBand
Modèle recommandéELODIE 32B INT8ELODIE 32B BF16 × 2KEVINA 32B BF16 × 4
Débit tokens/s~500 tok/s~2 000 tok/s~4 000 tok/s
Latence P95 estimée~180 ms TTFT~150 ms TTFT~120 ms TTFT
Budget matériel (€)60 000–80 000250 000–320 000500 000–650 000

Attention au pic de charge

Les 100/500/1000 utilisateurs sont des utilisateurs concurrents (requêtes simultanées), pas des utilisateurs totaux. Pour une organisation de 1000 collaborateurs, le pic réel est généralement de 100-150 requêtes simultanées (taux de simultanéité de 10-15%). Sizez en conséquence pour éviter le sur-dimensionnement.

Configuration vLLM pour la densité de requêtes

# Configuration optimisée pour 500 utilisateurs concurrents
# Sur 4× H100 80GB avec ELODIE 32B BF16

python -m vllm.entrypoints.openai.api_server \
  --model /models/elodie-32b \
  --tensor-parallel-size 4 \
  --pipeline-parallel-size 1 \
  --dtype bfloat16 \
  --max-model-len 16384 \
  --max-num-seqs 512 \
  --max-num-batched-tokens 32768 \
  --enable-prefix-caching \
  --enable-chunked-prefill \
  --gpu-memory-utilization 0.92 \
  --scheduler-delay-factor 0.1 \
  --host 0.0.0.0 --port 8000

Ce qu'il faut retenir

  • L'architecture en 6 couches (Applications → API GW → Orchestration → Serving → Infrastructure → IAM) est la référence pour toute plateforme LLM souveraine.
  • Le H100 SXM5 est la référence performance, mais le L40S offre le meilleur TCO pour les modèles ≤ 32B quantisés.
  • vLLM 0.4+ avec PagedAttention et continuous batching est incontournable : 2-4× plus efficient qu'une inférence naïve.
  • Pour 100 utilisateurs concurrents avec ELODIE 32B : 2× A100 80GB suffisent en INT8 (budget ~70k€ matériel).
  • L'isolation réseau par VLAN et le chiffrement LUKS des volumes NVMe sont des prérequis non-négociables pour la conformité RGPD.

Concevoir votre architecture LLM souveraine

Nos architectes techniques accompagnent les DSI dans la conception et le déploiement d'infrastructures LLM on-premise adaptées à vos contraintes réelles — datacenter existant, budget, exigences sectorielles et conformité RGPD.

Parler à un architecte →

FAQ

Peut-on utiliser des GPU AMD RDNA3 à la place de NVIDIA ?

Techniquement oui : vLLM supporte ROCm 6.x depuis la version 0.3. En pratique, l'écosystème logiciel (CUDA, cuDNN, les bibliothèques d'optimisation comme FlashAttention-2, CUTLASS) reste très largement centré NVIDIA. Pour une production 2026, NVIDIA reste recommandé sauf contrainte spécifique d'approvisionnement. AMD MI300X (192 GB HBM3) est une alternative prometteuse pour les très grands modèles.

Combien de temps prend le chargement d'un modèle 32B en mémoire GPU ?

Avec un modèle stocké sur NVMe U.2 (lecture séquentielle ~6 GB/s) et 2× A100 reliés en NVLink, le chargement d'un modèle ELODIE 32B (environ 64 GB en BF16) prend 10 à 15 secondes. Depuis MinIO via réseau 100 GbE, comptez 30 à 60 secondes. Utilisez le préchargement au démarrage du pod Kubernetes pour éliminer ce délai des premiers utilisateurs.

vLLM supporte-t-il nativement l'API OpenAI ?

Oui. vLLM expose un endpoint /v1/chat/completions et /v1/completions compatibles avec l'API OpenAI. Vous pouvez pointer n'importe quel client OpenAI (Python SDK, LangChain, LlamaIndex, Open WebUI) vers votre instance vLLM en changeant simplement la variable OPENAI_BASE_URL et OPENAI_API_KEY. Zéro modification de code applicatif.

Comment gérer la reprise après un crash GPU (GPU OOM) ?

Configurez Kubernetes avec un liveness probe sur le port vLLM et un restartPolicy Always. En cas de GPU OOM (CUDA out of memory), vLLM renvoie une erreur 500 et redémarre automatiquement via le kubelet. Pour prévenir les OOM, ajustez --gpu-memory-utilization à 0.85-0.90 et activez --max-num-seqs pour limiter la concurrence. DCGM Exporter + Prometheus vous alertera avant saturation avec la métrique DCGM_FI_DEV_FB_USED.