Architecture physique phys Décidé
Trois datacenters géographiquement séparés, zéro RAID : chaque disque est une brique autonome, la redondance appartient à l'application — erasure coding 8+3 local, réplication asynchrone des segments scellés entre sites, quorum PostgreSQL à trois pour rendre le split-brain impossible. Une seule couche de redondance, du disque au continent.
Vue d’ensemble — les trois datacenters
Topologie idéale — trois DC actifs, quorum synchrone, données asynchrones
Les trois DC sont actifs — chacun primaire pour un tiers des tenants, réplique pour un autre tiers, arbitre pour tous. Le plan de contrôle (minuscule) est synchrone ; les données (massives) sont asynchrones : chaque plan au régime que sa taille permet.
Décision 1 — Zéro RAID : la brique disque
Chaque HDD est une brique autonome : un XFS nu, une identité (UUID), un inventaire de segments auto-descriptif — un scan du disque suffit à reconstituer ce qu’il contient, dans la droite ligne de la hiérarchie de vérité. Pas de contrôleur RAID : un HBA simple — moins cher, pas de write-hole, pas de batterie de cache, pas de firmware propriétaire entre nous et nos octets. Ce que le sans-RAID apporte structurellement :
- Pas de reshape, jamais — ajouter un disque = une cible de plus pour les nouveaux segments. Le parc peut être hétérogène (des 16 To et des 24 To cohabitent), on achète le disque du moment au prix du moment.
- Le scrub RAID est licencié aussi — nos checksums sont de bout en bout (chaque entrée de segment se revérifie en rehachant) là où le RAID ne vérifie que le plateau. Le scrubbing applicatif itère les segments par disque, en tâche de fond throttlée.
- Le rayon de panne est un disque, pas un array — un disque meurt, les 11 autres ne sont pas dégradés, aucun client ne le sent.
Décision 2 — Le cycle de vie d’un segment : chaud sous escorte, froid dans le béton
Le cycle de vie d'un segment — répliqué chaud, encodé scellé, géo-copié vérifié
Le chemin chaud reste simple (2 répliques, append, fsync groupé) ; la redondance définitive (EC) ne s'applique qu'aux segments scellés, immuables — l'encodage n'est jamais dans le chemin de latence du client.
Le détail qui compte : Reed-Solomon systématique — les 8 premiers shards contiennent les octets tels quels. Une lecture normale (restauration) lit directement le shard concerné, sans aucun décodage ; les 3 parités ne servent qu’à la réparation. La parité est une roue de secours, pas un pneu de route. Overhead : 1,375× — comparable au RAID6 (1,2×), pour une tolérance de 3 pannes arbitraires et une couche unique.
Décision 3 — Le placement hiérarchique des shards
La règle, formulée une fois pour tous les étages : ne jamais placer dans un même domaine de panne plus de shards que la parité ne peut en absorber.
- Domaines emboîtés — disque ⊂ nœud ⊂ (rangée/salle) ⊂ site. Le placeur connaît la topologie et répartit les 11 shards en conséquence.
- Avec 6 nœuds par DC : ≤ 2 shards par nœud → la perte d'un nœud entier + un disque ailleurs reste réparable (2 + 1 = 3 = m). Avec 11+ nœuds : 1 shard par nœud, tolérance de 3 nœuds.
- Les métadonnées ne sont pas en EC — segments métadonnées répliqués 3× sur les NVMe de 3 nœuds : le volume est faible (le 3× ne coûte rien) et la latence de lecture est critique (pas de décodage sur le chemin des arbres parents ni du mark). L'index LSM : local par nœud, sans redondance — on ne protège pas un cache reconstructible.
Décision 4 — La réparation déclusterisée
Panne d'un disque de 20 To — l'entonnoir RAID contre le maillage déclusterisé
Un disque de 20 To meurt : l'index liste ses shards, la reconstruction lit les survivants sur des dizaines de disques et réécrit les manquants sur des dizaines d'autres. Heures au lieu de jours, fenêtre de double-panne écrasée, zéro dégradation perçue par les clients.
Décision 5 — Les trois DC en détail : qui fait quoi
- Chaque tenant a un DC primaire et un DC réplique, assignés à l'enrôlement du tenant et documentés (la résidence des données par client que la HDS exige). La charge s'équilibre : chaque DC est primaire pour ~⅓ des tenants.
- Plan de contrôle synchrone, données asynchrones — Postgres réplique en synchrone sur le quorum (l'état est minuscule, quelques ms de latence inter-DC sont indolores) ; les segments (massifs) voyagent en asynchrone une fois scellés. Chaque plan au régime que sa taille permet.
- Le RPO géographique est plus doux qu'il n'y paraît — spécificité du backup : si le DC primaire brûle avec des segments pas encore répliqués, le client possède toujours ses données sources — la reprise par dédup re-uploade le manquant au run suivant vers la réplique promue. Seuls les snapshots committés non répliqués sont perdus. Pour les tenants qui exigent zéro : l'option commit géo (la racine n'est committée qu'après réplication de ses segments) — RPO géo = 0, au prix de la latence de commit. Par plan, évidemment.
- Bascule — DC primaire d'un tenant perdu : le quorum élit, la réplique est promue, les agents rebasculent via leurs multi-endpoints (bootstrap) et retrouvent leurs sessions. RTO : minutes.
- L'immuabilité voyage — le DC réplique applique le plancher WORM indépendamment : compromettre le primaire ne suffit pas à effacer l'historique répliqué.
| Sinistre | RPO | RTO | Mécanisme |
|---|---|---|---|
| Disque | 0 | 0 (transparent) | EC 8+3, réparation déclusterisée en heures |
| Nœud entier | 0 | 0 (transparent) | placement ≤2 shards/nœud |
| DC primaire d’un tenant | lag async (minutes) — 0 en commit géo | minutes | promotion réplique + quorum + multi-endpoints |
| Deux DC | selon option 3ᵉ copie (par plan) | heures | le 3ᵉ DC garde quorum + ses tenants |
Le nœud de référence & le dimensionnement
| Composant | Spécification | Pourquoi |
|---|---|---|
| Châssis | 2U, 12 baies 3,5“ | l’unité de croissance — on ajoute des châssis, pas des arrays |
| Données | 12 × HDD 20-22 To, JBOD sur HBA | segments append-only séquentiels : le cas idéal du disque rotatif |
| Métadonnées | 2-3 × NVMe 3,84 To | segments méta (répliqués 3× inter-nœuds), index LSM, WAL |
| RAM | 128 Go | blooms GC (~60 Mo/gros tenant), cache métadonnées, LSM |
| CPU | 16-24 cœurs, milieu de gamme | on est network-bound — BLAKE3 rehache à plusieurs Go/s par cœur |
| Réseau | 2 × 25 GbE + IPMI dédié | trois plans : front 443 · stockage interne · management hors bande |
L’unité de déploiement par DC : 6 nœuds de stockage + 3 nœuds de contrôle (Postgres, OpenBao, API/front) + 2 switches. Capacité : 6 × 12 × 20 To ÷ 1,375 ≈ 1 Po utile par DC. Comptabilité globale : chaque octet logique coûte 1,375× au primaire + 1,375× à la réplique = 2,75× brut — contre 3× pour de la triple réplication naïve, avec une bien meilleure tolérance aux pannes. Au-delà : on ajoute des châssis (le placement rééquilibre seul), puis des rangées — la règle des domaines de panne absorbe chaque étage sans changement de code.