Nous utilisons OVH Managed Kubernetes (MKS) en production depuis un an. Bilan honnête : ce qui fonctionne bien, les limitations rencontrées et notre architecture actuelle.
Contexte et motivations du déploiement
En mars 2024, Move2Cloud a migré l'infrastructure d'un client du secteur médical vers OVH Managed Kubernetes (MKS). Les contraintes étaient strictes : hébergement exclusivement en France, certification HDS (Hébergeur de Données de Santé), et un budget qui excluait de facto AWS EKS. Après douze mois de production, voici notre retour d'expérience sans filtre.
Pourquoi OVH MKS plutôt que EKS ou GKE ? Quatre raisons ont guidé le choix :
- Souveraineté européenne : datacenters en France (GRA7, SBG5), conformité RGPD native, certification HDS et ISO 27001 sans configuration supplémentaire
- Absence de frais d'egress intra-OVH : les transferts entre le cluster MKS, l'Object Storage et la Managed DB sont gratuits — une économie significative à grande échelle
- Private Registry Harbor intégré : OVH propose un registre de conteneurs managé (basé sur Harbor) inclus dans l'offre Public Cloud, avec authentification OIDC
- Tarification compétitive : environ 40 à 57 % moins cher qu'une configuration EKS équivalente, comme nous le détaillons plus bas
Architecture déployée
Le cluster de production repose sur une topologie simple mais robuste. Nous avons privilégié la lisibilité opérationnelle sur la sophistication architecturale, ce qui s'est avéré un bon choix pour une équipe de taille modeste.
MKS Cluster — région GRA7
├── Node Pool "workers" (flavor b3-8 : 8 vCPU / 32 GB RAM)
│ ├── Min nodes : 3 | Max nodes : 10 (autoscaling activé)
│ └── Réseau privé vRack — pas d'IP publique sur les workers
│
├── Namespace: production
│ ├── Deployment: api (3 replicas, requests 500m/512Mi)
│ ├── Deployment: worker (2 replicas, requests 1000m/2Gi)
│ └── StatefulSet: redis-cache (1 replica, PVC 10Gi csi-cinder-high-speed)
│
├── Namespace: monitoring
│ └── kube-prometheus-stack 58.x
│ ├── Prometheus (PVC 50Gi)
│ ├── Grafana
│ └── Alertmanager → webhook Slack
│
└── Namespace: ingress-nginx
└── nginx-ingress-controller
└── Service LoadBalancer → OVH Load Balancer (IP publique)
OVH Object Storage (S3-compatible, région GRA)
├── Bucket: assets-static (CDN activé)
├── Bucket: backups-postgresql
└── Bucket: logs-loki
OVH Managed DB: PostgreSQL 15 (plan Essential-4, 4 vCPU / 15 GB RAM)
Provisioning Terraform du cluster MKS
Nous gérons l'intégralité de l'infrastructure en Terraform avec le provider OVH officiel. Voici les ressources essentielles pour monter un cluster MKS production-ready :
terraform {
required_providers {
ovh = {
source = "ovh/ovh"
version = "~> 0.46"
}
}
}
provider "ovh" {
endpoint = "ovh-eu"
application_key = var.ovh_application_key
application_secret = var.ovh_application_secret
consumer_key = var.ovh_consumer_key
}
# Réseau privé vRack
resource "ovh_cloud_project_network_private" "k8s_network" {
service_name = var.ovh_service_name
name = "k8s-private-net"
regions = ["GRA7"]
vlan_id = 10
}
resource "ovh_cloud_project_network_private_subnet" "k8s_subnet" {
service_name = var.ovh_service_name
network_id = ovh_cloud_project_network_private.k8s_network.id
region = "GRA7"
start = "10.0.0.100"
end = "10.0.0.200"
network = "10.0.0.0/24"
dhcp = true
no_gateway = false
}
# Cluster Kubernetes managé
resource "ovh_cloud_project_kube" "prod" {
service_name = var.ovh_service_name
name = "prod-cluster"
region = "GRA7"
version = "1.30"
private_network_id = tolist(ovh_cloud_project_network_private.k8s_network.regions_attributes)[0].openstackid
private_network_configuration {
default_vrack_gateway = "10.0.0.1"
private_network_routing_as_default = true
}
}
# Node pool avec autoscaling
resource "ovh_cloud_project_kube_nodepool" "workers" {
service_name = var.ovh_service_name
kube_id = ovh_cloud_project_kube.prod.id
name = "workers-b3-8"
flavor_name = "b3-8"
min_nodes = 3
max_nodes = 10
desired_nodes = 3
autoscale = true
template {
metadata {
labels = {
"node-role" = "worker"
}
}
spec {
unschedulable = false
}
}
}
Intégration OVH Managed Private Registry (Harbor)
OVH met à disposition un registre Harbor managé, accessible depuis le cluster MKS sans frais d'egress. Le flux de déploiement passe par ce registre pour toutes les images de production.
# 1. Créer un compte robot dans Harbor (UI ou API Harbor)
# Harbor → Projects → mon-projet → Robot Accounts → New Robot Account
# Permissions: repository:pull, repository:push
# 2. Créer le secret imagePullSecret dans Kubernetes
kubectl create secret docker-registry ovh-registry-secret --docker-server=<region>.registry.ovh.net --docker-username=robot$mon-robot --docker-password=<token> --namespace=production
# 3. Référencer le secret dans les Deployments
# deployment.yaml
spec:
template:
spec:
imagePullSecrets:
- name: ovh-registry-secret
containers:
- name: api
image: gra.registry.ovh.net/mon-projet/api:v1.2.3
# 4. Push depuis la CI
docker tag mon-app:latest gra.registry.ovh.net/mon-projet/api:v1.2.3
docker push gra.registry.ovh.net/mon-projet/api:v1.2.3
Configuration du monitoring : kube-prometheus-stack sur OVH
L'adaptation principale pour OVH concerne la StorageClass. OVH utilise Cinder (OpenStack) pour le stockage bloc. La classe csi-cinder-high-speed offre les meilleures performances pour Prometheus.
# values-kube-prometheus.yaml
prometheus:
prometheusSpec:
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: csi-cinder-high-speed
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
retention: 30d
retentionSize: "45GB"
grafana:
persistence:
enabled: true
storageClassName: csi-cinder-high-speed
size: 10Gi
alertmanager:
alertmanagerSpec:
storage:
volumeClaimTemplate:
spec:
storageClassName: csi-cinder-high-speed
resources:
requests:
storage: 5Gi
# Installation
helm upgrade --install kube-prometheus-stack prometheus-community/kube-prometheus-stack --namespace monitoring --create-namespace --values values-kube-prometheus.yaml --version 58.3.0
Pipeline GitHub Actions : build → Harbor → MKS
Le pipeline CI/CD que nous avons mis en place s'appuie entièrement sur GitHub Actions. L'authentification au cluster MKS utilise un kubeconfig stocké dans les secrets GitHub.
# .github/workflows/deploy-production.yml
name: Deploy to OVH MKS
on:
push:
branches: [main]
env:
REGISTRY: gra.registry.ovh.net
IMAGE_NAME: mon-projet/api
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Log in to OVH Harbor Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.HARBOR_USER }}
password: ${{ secrets.HARBOR_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
deploy:
needs: build-and-push
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Configure kubectl for OVH MKS
run: |
mkdir -p ~/.kube
echo "${{ secrets.KUBECONFIG_OVH }}" | base64 -d > ~/.kube/config
- name: Deploy to MKS
run: |
kubectl set image deployment/api api=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} -n production
kubectl rollout status deployment/api -n production --timeout=5m
Résultats de performance après 6 mois
Les métriques collectées via kube-prometheus-stack sur les six premiers mois de production livrent un bilan positif :
- Latence P99 : 85 ms sur l'API principale (objectif : < 200 ms) — dépassement des attentes
- Disponibilité : 99,95 % sur 6 mois (deux incidents de 8 et 15 minutes liés à des maintenances réseau OVH annoncées)
- Autoscaling : lors d'un pic de charge (campagne marketing), le cluster est passé de 3 à 8 nœuds en 4 minutes 20 secondes
- Utilisation CPU moyenne : 34 % en heure de pointe, 12 % en creux — l'autoscaling descend bien à 3 nœuds la nuit
Points de friction rencontrés
Soyons honnêtes sur les limitations. OVH MKS est excellent pour les workloads Kubernetes "purs", mais plusieurs points méritent attention avant de migrer depuis AWS :
- Écosystème plus restreint qu'EKS : pas d'équivalent à AWS Controllers for Kubernetes (ACK), pas d'intégration native SQS/DynamoDB/SNS. Si votre application consomme intensément des services AWS managés, la migration est coûteuse.
- Réactivité du support : les tickets critiques sur OVH sont résolus en 4 à 8 heures contre 15 à 30 minutes sur AWS Enterprise Support. Pour un client avec des SLA stricts, c'est un facteur bloquant.
- Pas de NFS managé natif : OVH ne propose pas d'équivalent à EFS. Pour les volumes partagés (ReadWriteMany), nous avons déployé un serveur NFS auto-hébergé sur une instance dédiée — une complexité opérationnelle supplémentaire.
- Cluster Autoscaler plus lent : le provisioning d'un nouveau nœud prend 3 à 5 minutes chez OVH contre 1 à 2 minutes sur EKS. Pour les pics très soudains, il faut surdimensionner légèrement le minimum de nœuds.
- Pas d'Istio managé : l'installation du service mesh est manuelle. Nous utilisons Linkerd (plus léger qu'Istio) mais c'est une charge opérationnelle à prévoir.
Comparaison de coûts : OVH MKS vs AWS EKS
Pour une configuration équivalente (6 nœuds actifs en moyenne, Load Balancer, stockage bloc, base de données PostgreSQL managée) :
| Composant | OVH MKS | AWS EKS équivalent |
|---|---|---|
| Control plane | Gratuit | ~73 €/mois |
| 6 nœuds workers (b3-8 / m5.2xlarge) | ~840 €/mois | ~1 400 €/mois |
| Load Balancer | ~20 €/mois | ~55 €/mois |
| Stockage bloc (500 GB) | ~50 €/mois | ~110 €/mois |
| PostgreSQL managé | ~200 €/mois | ~460 €/mois |
| Egress réseau (500 GB/mois) | Gratuit | ~45 €/mois |
| Total mensuel | ~1 110 € | ~2 143 € |
Économie réalisée : 48 %, soit plus de 12 000 € par an pour ce seul projet.
Quand choisir OVH MKS vs EKS ?
Voici notre grille de décision après 12 mois de production :
- Choisissez OVH MKS si : vos données doivent rester en France/UE (RGPD, HDS, secteur public), votre stack est un Kubernetes "pur" sans dépendances aux services AWS propriétaires, la maîtrise des coûts est une priorité, et votre SLA accepte un support moins réactif.
- Choisissez AWS EKS si : vous consommez intensément des services AWS (Lambda, SQS, DynamoDB, Bedrock), vous avez besoin d'un support premium < 1h de réponse, vous utilisez des outils AWS natifs (ACK, IRSA, AWS Load Balancer Controller), ou la vitesse d'autoscaling est critique pour votre activité.
Conclusion
OVH MKS est un service de Kubernetes managé mature, compétitif et souverain. Après 12 mois en production, notre verdict est clair : pour les entreprises françaises avec des contraintes réglementaires et un budget contraint, c'est une excellente alternative à EKS. Le principal sacrifié est l'accès à l'écosystème AWS — mais si votre architecture est conçue pour Kubernetes pur (et non pour l'intégration native AWS), cette contrainte est gérable. L'économie réalisée — souvent supérieure à 40 % — peut financer des ressources humaines supplémentaires pour absorber la charge opérationnelle légèrement plus élevée.
