OVHcloud Managed OpenSearch : déploiement, SLA et haute disponibilité 3-AZ

Déploiement et exploitation OVHcloud Managed OpenSearch en HA 3‑AZ : distinguer SLA/SLO, gérer shards & réplicas, snapshots, observabilité et intégration PrestaShop.

Ordinateurs affichant des schémas et du code pour la gestion d'OpenSearch dans un contexte de cloud computing.

Table des matières :

  1. SLA, SLO et disponibilité réelle : arrêter de confondre contrat et architecture
  2. Déploiement OVHcloud Managed OpenSearch : ce que vous contrôlez vraiment (et ce que vous ne contrôlez pas)
  3. Haute disponibilité 3-AZ : mécanique des shards, réplicas et tolérance à la perte d’une zone
  4. Exploitation : snapshots, upgrades, observabilité et runbooks (la partie que le “managé” ne fait pas)
  5. Intégration e-commerce / PrestaShop : recherche produit, facettes et usage “logs” sans casser la prod

SLA, SLO et disponibilité réelle : arrêter de confondre contrat et architecture

Un déploiement OVHcloud Managed OpenSearch “haute disponibilité 3-AZ” résout une partie du problème (perte d’une zone), pas tous les problèmes (mauvais mapping, surcharge, erreurs applicatives, requêtes pathologiques, index corrompu, etc.). Le point de départ technique, c’est de distinguer SLA (contractuel) et SLO (objectif interne mesuré). En prod e-commerce, vous avez aussi besoin de RTO (temps de remise en service) et RPO (perte de données acceptable). Si vous n’écrivez pas ces quatre indicateurs noir sur blanc, vous finirez par surdimensionner “pour être tranquille”… tout en gardant des angles morts (snapshots non testés, alerting absent, mauvais sharding).

Une façon simple d’éviter les malentendus consiste à formaliser, dès le départ, sur quoi vous mesurez la disponibilité : la réponse HTTP 200 du point de terminaison (endpoint) OpenSearch ? la réussite d’une requête fonctionnelle (recherche + facettes) ? la capacité d’indexer en bulk en continu ? En e-commerce, un service peut être “up” au sens monitoring infra, tout en étant “down” au sens business si la recherche produit dépasse 2 secondes ou retourne des facettes vides.

Voici un rappel pragmatique (à adapter à votre contexte) :

Indicateur Ce que ça mesure Exemple e-commerce (recherche) Qui le porte
SLA Engagement contractuel du fournisseur (disponibilité) “99,9 % sur le mois” Fournisseur
SLO Objectif interne mesuré (perf + erreurs) p95 < 250 ms, taux d’erreur < 0,2 % Équipe produit/tech
RTO Durée max de remise en service acceptable 30 min pour retrouver une recherche utilisable Équipe ops
RPO Perte de données max acceptable 15 min de perte max sur logs d’audit Produit + conformité

Le SLA est une promesse de disponibilité calculée sur une période donnée. Pour rappeler l’ordre de grandeur, 99,9 % d’uptime autorise ~43 min d’indisponibilité par mois, 99,99 % ~4 min, 99,5 % ~3 h 36.

Disponibilité Indisponibilité max / mois (30j) Indisponibilité max / an (365j)
99,9 % ~43 min ~8 h 46
99,99 % ~4 min 19 ~52 min 34
99,5 % ~3 h 36 ~1 j 19 h

Le SLA ne dit pas si votre cluster tient le débit d’indexation (bulk) + la recherche (front) + l’analytics (dashboards). L’HA 3-AZ ne dit pas si votre applicatif gère correctement les timeouts, retries, et la backpressure. Dans les systèmes distribués, l’idée “tout finit par tomber” (souvent attribuée à Werner Vogels) est surtout un rappel opérationnel : une zone peut tomber, un nœud peut se faire éjecter du cluster, un thread pool peut saturer, un GC peut se déclencher au mauvais moment, et vos p95/p99 explosent sans “downtime” officiel.

Concrètement, si vous voulez que le “99,9 %” soit utile, reliez-le à un SLO mesuré côté utilisateur. Exemple de mini-scénario (très courant) : pendant une promo, les requêtes facettées (marque, taille, prix) augmentent, les caches se vident plus vite, les temps de réponse passent de 120 ms à 900 ms, puis les timeouts applicatifs déclenchent des retries → vous avez un cluster “green”, mais une recherche inutilisable et un taux d’abandon qui grimpe. Le contrat n’a rien “cassé”, c’est l’architecture + l’usage qui n’étaient pas alignés.

Déploiement OVHcloud Managed OpenSearch : ce que vous contrôlez vraiment (et ce que vous ne contrôlez pas)

Sur un service managé, la promesse est simple : vous n’administrez pas l’OS, vous ne gérez pas les paquets, et vous n’avez pas à bricoler la sécurité système. En contrepartie, vous perdez des leviers : tuning kernel, placement fin des rôles, plugins “exotiques”, accès root, parfois certaines APIs d’administration. Avant de parler 3-AZ, relisez le périmètre “moteur managé” et ses cas d’usage (search/logs) dans l’article interne : OVHcloud Managed OpenSearch : moteur NoSQL managé pour logs et recherche. Ça évite de l’utiliser comme une base transactionnelle, ce qu’OpenSearch n’est pas.

Même si l’interface OVHcloud masque une partie de l’architecture, vous devez raisonner en rôles : nœuds “cluster-manager” (ex-master), nœuds data (stockage + requêtes), nœuds ingest (pipelines), et nœuds coordinating (front-door). Les clusters OpenSearch 2.x reposent toujours sur une coordination distribuée : si vous n’avez pas de quorum stable pour le cluster state, vous aurez des “red/yellow” sans comprendre pourquoi. En pratique, pour une topologie 3-AZ, on vise une répartition qui garde un quorum malgré la perte d’une AZ (donc un nombre impair de nœuds manager, typiquement 3).

Ce que vous contrôlez vraiment (et qui fait la différence en prod) se situe souvent plus haut dans la pile :

  • Modèle d’indexation : mappings, analyzers, templates, alias, stratégie de reindex.
  • Stratégie de shards/réplicas : nombre de shards primaires, réplicas par index critique, stratégie de rollover.
  • Politiques de cycle de vie : rétention logs, bascule hot/warm si disponible, index state management.
  • Sécurité applicative : secrets, rotation, filtrage réseau (IP allowlist, firewalling), gestion des droits (principe du moindre privilège).
  • Client & résilience : timeouts, retries bornés, circuit breaker, mise en file (queue) côté ingestion.

Le sizing n’est pas “au feeling”. Les limites les plus fréquentes en e-commerce : heap JVM (GC), IO (merge de segments Lucene), et nombre de shards (overhead). Règles pragmatiques : heap ~50 % de la RAM (sans dépasser les valeurs recommandées par l’écosystème JVM), surveiller l’espace disque par rapport aux watermarks, et limiter l’explosion du nombre de shards (un index par jour pour les logs, un index par langue/boutique pour le catalogue, mais pas un index par catégorie…). En ordre de grandeur, beaucoup d’équipes visent des shards “ni minuscules ni énormes” (souvent ~10 à 50 Go par shard), mais la seule règle fiable est empirique : mesurer vos temps de merge, vos latences p95/p99 et votre vitesse de recovery après incident.

Si vous déployez via IaC, alignez la config avec vos pipelines (création de cluster, secrets, firewalling, DNS). Sur ce volet, la référence interne utile est : DevOps : Infrastructure as Code avec Terraform et conteneurs.

Enfin, ajoutez une couche “géographie” sans la sur-vendre : choisir une région proche de votre base d’utilisateurs (France/UE si votre trafic est majoritairement FR/UE) réduit la latence réseau moyenne, mais ne corrige ni les requêtes pathologiques ni une saturation IO. Et si vous avez des contraintes de conformité (RGPD, localisation), documentez noir sur blanc où résident les données indexées (y compris logs, qui contiennent parfois des identifiants).

Haute disponibilité 3-AZ : mécanique des shards, réplicas et tolérance à la perte d’une zone

La HA 3-AZ n’est pas magique : elle repose sur des copies et sur des règles de placement. Dans OpenSearch, un index est découpé en primary shards et replica shards (implémentés par Lucene). La conséquence immédiate : si vous voulez survivre à la perte d’une AZ sans perdre de capacité de lecture et en gardant une marge de relocalisation, vous devez dimensionner au minimum : (1) suffisamment de nœuds data par AZ, (2) suffisamment de réplicas. Pour une vraie stratégie 3-AZ, un réglage classique est number_of_replicas: 2 sur les index critiques (catalogue, logs d’audit), afin d’avoir 3 copies (1 primaire + 2 réplicas) et donc une copie potentielle par zone.

Deux nuances importantes (souvent oubliées) :

  • Capacité vs survie : survivre à la perte d’une zone n’implique pas que vous gardez les mêmes p95/p99. En pratique, vous perdez 1/3 de la capacité (et parfois plus, si les shards “chauds” étaient concentrés). Si votre cluster tourne déjà à 70–80 % en régime nominal, l’incident devient une crise de performance.
  • Écriture et ack : selon vos réglages et votre client, vous pouvez “réussir” des écritures alors qu’une partie des réplicas est indisponible, ou au contraire bloquer des écritures si vous exigez un certain nombre de copies actives. Il faut que ce comportement soit voulu (et testé), pas découvert pendant un incident.

Le piège, c’est de poser 2 réplicas sans “awareness” de placement. Il faut s’assurer que l’allocation des shards est consciente des zones (allocation awareness / forced awareness selon la plateforme), sinon OpenSearch peut colocaliser primaire + réplicas de manière sous-optimale lors d’un incident ou d’un rebalance. L’objectif est de forcer : pas deux copies du même shard dans la même AZ. En environnement managé, cette capacité dépend de l’implémentation OVHcloud ; votre boulot est de vérifier, via les APIs, que la distribution des shards respecte bien la contrainte avant de déclarer “HA”. La documentation OpenSearch sur le sujet (référence utile pour comprendre ce que vous cherchez à valider côté managé) : https://opensearch.org/docs/latest/cluster-administration/cluster-settings/#shard-allocation-awareness

Exemple de commandes de contrôle (OpenSearch 2.x) :

# Santé globale et statut (green/yellow/red)
curl -u user:pass https://endpoint:9200/_cluster/health?pretty

# Distribution des shards et nœuds
curl -u user:pass https://endpoint:9200/_cat/shards?v
curl -u user:pass https://endpoint:9200/_cat/allocation?v

Ajoutez un réflexe très opérationnel : quand quelque chose “ne s’alloue pas”, ne restez pas au niveau “yellow”. Demandez l’explication :

# Pourquoi un shard reste unassigned ? (souvent plus actionable que _cluster/health)
curl -u user:pass https://endpoint:9200/_cluster/allocation/explain?pretty

Enfin, la perte d’une AZ déclenche une phase de recovery : relocalisation, rebalancing, recomputation des routings, et parfois promotion de réplicas en primaires. Pendant cette fenêtre, vos latences p95/p99 prennent cher si le cluster est déjà proche de sa limite IO. Vous pouvez avoir un service “up” mais inutilisable. Donc : testez le scénario (chaos engineering light), mesurez les temps de recovery, et prévoyez des garde-fous côté applicatif (timeouts stricts, retries bornés, circuit breaker).

Checklist simple de validation “3-AZ utile” (avant de communiquer “HA OK”) :

  • [ ] Quorum stable des nœuds cluster-manager (perte d’1 AZ sans split-brain).
  • [ ] Réplicas suffisants sur les index critiques (pas seulement “le cluster”).
  • [ ] Distribution effective des copies sur des zones distinctes (pas une supposition).
  • [ ] Test de charge pendant un recovery (pas seulement en nominal).
  • [ ] Comportement applicatif validé sur timeouts/retries (pas de tempête de retries).
  • [ ] Plan B snapshot/restore testé (voir section suivante).

Pour les migrations/snapshots (souvent le vrai plan B), l’article interne connexe est : Elasticsearch managé : migration zéro interruption via snapshot, restore et parallélisation.

Exploitation : snapshots, upgrades, observabilité et runbooks (la partie que le “managé” ne fait pas)

L’HA 3-AZ protège surtout contre la panne d’infra dans une région. Elle ne remplace pas une stratégie backup/restore. Votre baseline : snapshots fréquents + rétention + tests de restauration. Pour un catalogue produit, un snapshot toutes les X heures peut suffire si l’index est reconstruisible depuis la base (MySQL/MariaDB) ; pour des logs/audits, l’exigence RPO peut être plus stricte (et là, la perte de quelques heures n’est pas acceptable). Si vous ne faites jamais de restore en environnement isolé, vous n’avez pas de backup, vous avez un fichier sur un stockage.

Une routine réaliste (et tenable) ressemble souvent à ceci :

  • Catalogue : snapshot régulier (par ex. 1–4 fois/jour) + capacité à reconstruire l’index (job de réindex) + test de restore mensuel.
  • Logs / audit : snapshots plus fréquents + rétention définie (ex. 30/90/180 jours selon obligations) + test de restore trimestriel + contrôle d’intégrité (un index restauré doit être requêtable).
  • Test : restauration dans un cluster/namespace isolé, puis exécution d’une requête “synthetic” (ex. top 10 produits, facettes, agrégations) pour valider que ce n’est pas juste “restauré”, mais utilisable.

Côté upgrades : “managé” ne veut pas dire “sans impact”. Vous devez anticiper :

  • compatibilité des clients (versions),
  • changements d’analyseurs/mappings (rare, mais coûteux),
  • fenêtres de maintenance (même si rolling),
  • et surtout régression de perf (les upgrades peuvent modifier le comportement mémoire/IO).

Côté observabilité, vous devez surveiller ce qui casse réellement : heap JVM, pressure mémoire, taille des queues (search/write thread pools), latence d’indexation, refresh/merge, “unassigned shards”, et saturation disque. Si vous avez déjà un stack Prometheus/Alertmanager, c’est le bon moment pour standardiser vos alertes (seuils, durations, burn rate de SLO). Deux ressources internes utiles pour l’alerting et la collecte : Prometheus : configuration des alertes, métriques et requêtes PromQL et Netdata : intégrer Prometheus, SNMP et StatsD pour tout surveiller. Même si OVHcloud expose des métriques managées, gardez aussi des checks externes (synthetic queries) : le “cluster green” n’est pas un KPI UX.

Exemple de “synthetic query” utile (à exécuter toutes les 1–5 minutes depuis l’extérieur) : une recherche courte + une agrégation représentative, avec un timeout strict. Objectif : détecter les cas où le cluster répond, mais trop lentement pour le front.

Les runbooks doivent couvrir des incidents très concrets : (1) index bloqué en read_only_allow_delete après watermark disque, (2) mapping explosion (trop de champs dynamiques), (3) requête agrégation qui OOM, (4) “hot shards” sur un routing déséquilibré, (5) storm de reindex après déploiement. Sur un e-commerce, ces incidents arrivent souvent pendant les pics (feed, import ERP, mises à jour de prix).

Un runbook exploitable tient en une page par incident, avec :

  • symptômes observables (métriques + logs),
  • diagnostic rapide (3 commandes max : health, cat shards, allocation explain),
  • actions d’urgence (réduire refresh, limiter analytics, couper une source de bulk, augmenter temporairement timeouts côté jobs, etc.),
  • correctifs durables (templates, quotas, limitation du dynamic mapping, re-sharding, séparation des workloads).

Le service managé ne connaît pas votre modèle de données ni votre cadence d’updates : c’est donc à vous de poser des limites (templates d’index, dynamic: strict sur certaines parties, politiques ISM, quotas applicatifs) et d’automatiser les rollbacks.

Intégration e-commerce / PrestaShop : recherche produit, facettes et usage “logs” sans casser la prod

Côté PrestaShop, le cœur historique s’appuie sur MySQL/MariaDB pour la recherche, ce qui devient vite une contrainte dès que vous voulez : tolérance aux fautes, synonymes, facettes rapides, tri multi-critères, et surtout une latence stable sur gros catalogue. Pour cadrer les attentes (fonctionnel + perf), l’article interne à lire avant de brancher un moteur externe est : Recherche interne PrestaShop : live search, tolérance fautes et tri commercial. Ensuite seulement, vous faites le choix OpenSearch vs Elasticsearch vs Meilisearch, en sachant que certains modules PrestaShop “Elasticsearch” marchent via l’API compatible, mais pas à 100 % (analyzers, plugins, sécurité, versions).

La partie la plus sous-estimée est le design d’index. Exemple minimal côté catalogue : un document “product” avec champs name, description, categories, attributes, price, in_stock, et des champs de ranking (popularité, marge, nouveauté). Pour que les facettes restent fiables et rapides, vous avez généralement besoin de champs “bruts” dédiés (ex. brand_id en keyword, price en scaled_float/numérique, attributs facettables en keyword) et de champs “texte” séparés pour le full-text (ex. name en text avec analyzer). Mélanger les deux mène vite à des surprises (fielddata, consommation mémoire, agrégations lentes).

Si vous indexez en multi-boutique / multi-langue, vous devez trancher : un index par boutique/langue (simplifie les analyzers) ou un index unique avec champs shop_id, lang_id (simplifie l’admin mais complexifie la pertinence). Un compromis fréquent : index par langue (car analyzer), puis filtrage par boutique (car business rules).

Ensuite viennent les choix Lucene : analyzers (stemmer FR/EN), normalizers (tri insensible à la casse), synonymes, edge n-grams pour l’autocomplete. Un point très “terrain” : si vous activez des n-grams agressifs partout, vous payez en taille d’index et en temps de merge. Il vaut mieux réserver l’autocomplete à un champ dédié (ex. name_autocomplete) et garder name plus “propre” pour la recherche standard.

En PHP 8.3, vous pouvez interroger OpenSearch via HTTP (cURL/Guzzle) ou via un client compatible. Exemple ultra direct :

<?php
// Exemple volontairement simple : à sécuriser (secrets, TLS, timeouts)
$endpoint = 'https://opensearch.example:9200';
$index = 'ps_products_fr';

$query = [
  'size' => 12,
  'query' => [
    'multi_match' => [
      'query' => 'chaussure running',
      'fields' => ['name^3', 'description', 'categories^2']
    ]
  ],
  'aggs' => [
    'brand' => ['terms' => ['field' => 'brand_id']]
  ]
];

$ch = curl_init("$endpoint/$index/_search");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode($query),
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CONNECTTIMEOUT => 1,
  CURLOPT_TIMEOUT => 2,
  // En production, gardez la vérification TLS activée et gérez proprement les CA/certificats.
]);

$response = curl_exec($ch);
if ($response === false) {
  throw new RuntimeException(curl_error($ch));
}

echo $response;

Sur la synchro catalogue, le piège n’est pas la requête _search, c’est l’ingestion :

  • flux “événementiel” (à chaque mise à jour produit) vs batch (import nocturne),
  • gestion des suppressions (produit désactivé, déclinaisons),
  • et stratégie de “zéro interruption” (aliases + reindex) pour éviter de servir un index partiellement rempli.

Enfin, ne limitez pas OVHcloud Managed OpenSearch à la recherche produit : c’est aussi très pertinent pour la centralisation de logs (Nginx, PHP-FPM, erreurs applicatives, jobs d’indexation, webhooks). Mais attention à l’effet “couteau suisse” : un cluster qui sert à la fois (1) le front search en temps réel et (2) l’ingestion massive de logs peut se tirer une balle dans le pied (contention IO, merges, caches).

Mini-scénario réaliste : un job d’import (ERP) déclenche un reindex partiel de 50 000 produits pendant que les logs applicatifs explosent (campagne marketing + quelques erreurs 500). Les merges Lucene montent, les files write gonflent, et la recherche front se met à “ramer” sans être officiellement down. Si vous n’avez qu’un cluster, isolez au minimum par index + policies de rétention + limitations de refresh (par exemple, refresh plus long sur les logs, plus court sur le catalogue), et mettez une vraie discipline de cache côté boutique (à recroiser avec Cache PrestaShop : stratégie 2026 OPcache, Redis, Varnish et CDN et un plan d’optimisation global type PrestaShop OVH : optimisations performance, sécurité et UX après installation).

La HA 3-AZ garantit une tolérance à la panne d’une zone, pas une immunité contre vos propres charges : si vous ne posez pas de budgets (SLO, quotas, backpressure), le cluster restera “up” pendant que votre recherche devient inutilisable.


À lire aussi