déployer un modèle ML open source en production avec FastAPI et Kubernetes : guide technique pas à pas
16/09/2026
déployer un modèle ML open source en production avec FastAPI et Kubernetes
Ce guide s’adresse aux CTO, lead dev et ingénieurs DevOps qui veulent passer d’un prototype à un service d’inférence fiable et scalable. Nous couvrons une chaîne complète : API d’inférence légère avec FastAPI, containerisation, bonnes pratiques Docker, déploiement Kubernetes, autoscaling, observabilité et sécurité. À la fin vous aurez un plan d’action reproductible, des snippets prêts à adapter et les pièges à éviter.
Pourquoi FastAPI + Kubernetes ?
FastAPI permet de construire rapidement une API d’inférence asynchrone et performante. Kubernetes apporte l’orchestration, l’autoscaling et la résilience nécessaires en production. Cette combinaison est idéale pour transformer un modèle open source (PyTorch, TensorFlow, scikit-learn, etc.) en API REST/HTTP prête pour un SaaS ou un logiciel métier.
Prérequis techniques
- Code model prêt à charger via Python (ex : model = load_model(...)).
- Conteneurisation Docker et accès à un registry.
- Cluster Kubernetes (minikube, cloud managed ou on-prem).
- CI/CD pour build & déploiement (optionnel mais recommandé).
Étapes détaillées
1. API d’inférence minimale avec FastAPI
Créer une API légère qui expose un endpoint /predict et charge le modèle en mémoire au démarrage. Exemple minimal :
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
class RequestIn(BaseModel):
text: str
# charger le modèle (ex: PyTorch, scikit-learn, transformers)
model = load_model("models/my_model")
@app.post("/predict")
async def predict(payload: RequestIn):
try:
result = model.predict([payload.text])
return {"prediction": result[0]}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
Conseil : isolez la logique de pré/post-traitement et rendez-la testable. Ajoutez un endpoint /healthz pour les probes Kubernetes.
2. Dockerfile simple et sécurisé
Exemple Dockerfile optimisé :
FROM python:3.11-slim
# créer un user non-root
RUN groupadd -r app && useradd -r -g app app
WORKDIR /app
COPY pyproject.toml requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY src/ ./src
COPY models/ ./models
USER app
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8080", "--proxy-headers"]
Bonnes pratiques : utiliser un utilisateur non-root, layerer intelligemment pour le cache, évitez d’installer des paquets inutiles. Lancer uvicorn en production derrière un process manager (gunicorn + uvicorn workers) si vous avez besoin de plus de robustesse.
3. Container build & test local
docker build -t registry.example.com/my-model:stable .
docker run --rm -p 8080:8080 registry.example.com/my-model:stable
curl -X POST localhost:8080/predict -d '{"text":"bonjour"}' -H "Content-Type: application/json"
Ajoutez des tests d’intégration qui appellent /healthz et /predict dans votre pipeline CI.
4. Déploiement Kubernetes : manifestes essentiels
Exemple Deployment + Service minimal :
apiVersion: apps/v1
kind: Deployment
metadata:
name: model-api
spec:
replicas: 2
selector:
matchLabels:
app: model-api
template:
metadata:
labels:
app: model-api
spec:
containers:
- name: api
image: registry.example.com/my-model:stable
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1"
memory: "2Gi"
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: model-api
spec:
selector:
app: model-api
ports:
- port: 80
targetPort: 8080
type: ClusterIP
Pour comprendre les probes et leur configuration, reportez-vous à la documentation officielle Kubernetes sur les probes : kubernetes.io - liveness/readiness probes.
5. Autoscaling et gestion des coûts
Pour l’inférence, l’autoscaling peut être horizontal (HPA/KEDA) ou vertical (upgrade des nodes). Pour des charges HTTP classiques, HPA basé sur CPU/mémoire suffit :
kubectl autoscale deployment model-api --cpu-percent=60 --min=2 --max=10
Si vous avez des files d’attente (RabbitMQ, Kafka, Kinesis) ou des metrics custom (latence, queue length), KEDA permet un scaling plus fin. Voir la doc KEDA : keda.sh.
Astuce coûts : testez le comportement de votre modèle (latence, mémoire) en CPU avant d’ajouter GPU. Les GPU sont coûteux ; utilisez des node pools GPU uniquement si le modèle l’exige vraiment.
Bonnes pratiques performance et sécurité
Performance
- Pré-chauffer le modèle au démarrage pour éviter la latence "cold start".
- Métriques à suivre : p95/p99 latency, throughput (req/s), OOM events. Collectez via Prometheus + Grafana.
- Batching si le modèle le supporte : regrouper N requêtes pour améliorer le throughput (attention à la latence).
- Limiter les requests concurrency via sidecar ou configuration du serveur (gunicorn workers / uvicorn workers).
Sécurité
- Terminez TLS au niveau de l’ingress (Traefik/NGINX). Voir doc Traefik : traefik.io.
- Ne stockez pas de secrets en clair ; utilisez des Secrets Kubernetes ou un vault.
- Scanner les images (clair/Trivy) et appliquer le principe du moindre privilège.
- Limiter la taille des payloads et contrôler les inputs pour éviter la surconsommation mémoire ou injections.
Observabilité
Exposer des metrics (Prometheus) et des traces (OpenTelemetry) depuis l’API. Mesurez latence, erreurs et saturation mémoire. Ajoutez des logs structurés (JSON) pour faciliter le diagnostic.
Erreurs fréquentes et comment les résoudre
- OOMKilled en prod : augmenter memory.requests ou optimiser le modèle (quantization, ONNX).
- HPA n’augmente pas : vérifier metrics-server et que les metrics CPU sont disponibles.
- Cold start lent : charger modèle en background et retourner rapidement un 503 si non prêt avec un retry côté client.
- Incohérence entre staging et prod : utilisez les mêmes images et tests d’intégration incluant le modèle.
Exemples d'optimisations modèles (rapide)
- Quantization / pruning pour réduire la mémoire et accélérer l’inférence.
- Exporter en ONNX et utiliser un runtime optimisé pour CPU.
- Servir des modèles lourds via un microservice d’inférence séparé (gérer la latence inter-service).
Ressources internes utiles
Pour intégrer ce type d’architecture dans un produit SaaS ou un logiciel métier, nos pages sur services SaaS et intelligence artificielle proposent des approches projet. Pour la partie containerisation, voir aussi la page sur Docker.
Checklist rapide avant mise en production
- Endpoint /healthz et /ready ok
- Image scannée et taggée
- Ressources requests/limits définies
- Probes configurées
- Autoscaling (HPA/KEDA) validé en charge
- TLS et secrets en place
- Monitoring & alerting configurés
- Tests d’intégration incluant le modèle
Conclusion
Passer un modèle open source en production demande d’industrialiser plusieurs couches : API, packaging, orchestration et observabilité. Avec FastAPI et Kubernetes vous obtenez une base flexible et scalable. Commencez par une image Docker reproducible, des probes et des limites bien calibrées, puis ajoutez autoscaling et observabilité. Testez la latence et le comportement mémoire avant d’ouvrir le service à vos utilisateurs.
Besoin d’un accompagnement pour produire et déployer votre API d’inférence dans votre SaaS ou ERP ? Contactez-nous discrètement pour une première évaluation : novane.io/contact.

