Je le dis d’emblée : je travaille pour croit, qui a écrit FlashStore. Tout ce qui suit est lu dans le code source et la documentation de Ceph en v21.2.0 et dans le snapshot ceph-rust publié par croit, tous liés en bas de page. Là où le raisonnement de croit se trouve d’un côté d’un argument, je dis à qui appartient ce raisonnement.

Deux réécritures du même démon

L’OSD classique de Ceph est un serveur C++ multithread qui a grandi sur des disques rotatifs. Sur du NVMe rapide et des réseaux rapides, il passe une bonne partie de son CPU à autre chose qu’à stocker vos données : se passer des opérations entre pools de threads, prendre des verrous, attendre d’autres threads. Deux projets ont entrepris de régler ça en réécrivant l’OSD de fond en comble.

L’un est Crimson, celui de Ceph. La documentation d’Umbrella l’appelle « the next generation ceph-osd », construit « to deliver enhanced performance on fast network and storage devices »1. L’autre est l’OSD FlashStore de croit, issu du projet ceph-rust, en préversion publique depuis le 9 novembre 20262.

Les deux se disent remplaçants directs. Les deux se disent faits pour le NVMe. Les deux sont en préversion, et aucun ne devrait garder des données de production aujourd’hui. Si vous faites tourner Ceph sur NVMe et que vous vous demandez lequel suivre, il vaut donc la peine de savoir où ils diffèrent vraiment, parce que ce n’est pas là où les gros titres le laisseraient croire.

Cet article les compare tels que vous les trouveriez sur Ceph 21.2.0, Umbrella : Crimson tel que cette version le documente et le livre, face à FlashStore, qui est compilé et testé contre cette même version2. Il fait suite à FlashStore contre BlueStore d’Umbrella, et tout ce qui y est déjà dit sur FlashStore est considéré comme acquis.

Deux réécritures d'un même démonceph-osd classiqueC++, threadsCrimsonCeph upstream, C++ sur Seastarcroit-flashstore-osdcroit, Rust, runtime propreBlueStorepar défautSeaStorenatifCyanStoresans donnéesFlashStorele seul magasin
Deux réécritures de l’OSD classique. Crimson garde trois magasins au choix, BlueStore étant celui par défaut ; FlashStore n’en a qu’un.

D’où vient chacun

La première différence, c’est qui le construit et comment.

CrimsonFlashStore
Construit parCeph upstream, dans l’arbre principalcroit
LangageC++Rust
FrameworkSeastarexécuteur monothread propre à croit
Codedans ceph/cephréécriture en salle blanche, aucun code Ceph lié
Développementupstream, ouvertsnapshots en lecture seule pendant la préversion ; ouvert après la première version de production
Licencecelle de CephLGPL-3.0 pour le démon, MPL-2.0 pour les clients
Statut, dans ses propres mots« not suitable for production use »« not yet recommended for production data »
GA prévueaucune annoncéeT1 2027

Crimson vit dans le dépôt de Ceph et il est construit par les développeurs de Ceph. Il est écrit sur Seastar, un framework C++ pour serveurs à un thread par cœur, issu de ScyllaDB3. La documentation d’Umbrella le dit sans détour : il « is in a tech-preview stage and is not suitable for production use »1.

FlashStore est écrit de zéro en Rust et ne lie aucun code Ceph ; le C++ de Ceph est lu comme référence et réimplémenté à partir des propres spécifications de croit4. Son README dit qu’il sert aux tests et à l’évaluation et qu’il est « not yet recommended for production data », avec une disponibilité générale prévue pour le premier trimestre 20272. Le dépôt public est un snapshot en lecture seule : « no issue tracker, no contribution workflow »2.

Cette ligne mérite une lecture attentive. Crimson est développé à découvert, et n’importe qui peut lire les pull requests et en débattre. FlashStore, pour l’instant, arrive sous forme de snapshots finis venant d’une seule entreprise : vous pouvez lire chaque ligne, mais vous ne pouvez pas encore lui envoyer un patch. C’est le stade de la préversion, pas le projet. La préversion est là pour recueillir les retours de la communauté pendant que croit fait tourner ses cas de test de production en interne, avant de déclarer l’OSD sûr à l’usage. Le développement ouvert suit cette première version de production, le chemin que prennent la plupart des projets open source soutenus par une entreprise. Cela vient de l’intérieur de croit et non d’une feuille de route publiée, alors tenez-les à cette promesse.

croit a bien envisagé de forker Crimson, et a mis par écrit pourquoi il ne l’a pas fait. Son ADR dit que Crimson « tries to support everything (HDD, alienstore/BlueStore, all pool types) », et ajoute « Complex code is never fast »4. C’est l’opinion de croit sur Crimson, pas une mesure, et je la traiterais comme telle. Le même ADR a aussi rejeté un fork en partie à cause de la LGPL4, et croit a ensuite placé son propre démon sous LGPL-3.0 huit jours plus tard5. La licence n’a donc jamais vraiment été la raison.

Sûreté mémoire : Rust contre C++

Un OSD, c’est le code qui garde vos données. Un use-after-free ou un dépassement de tampon là-dedans n’est pas un plantage dont on redémarre ; ce sont des données corrompues sur disque, copiées sur chaque réplica. C’est exactement la classe de bugs que les agences de cybersécurité occidentales ont passé les trois dernières années à demander à l’industrie d’éliminer dès la conception.

RecommandationQui l’a signéeCe qu’elle dit
The Case for Memory Safe Roadmaps, décembre 2023CISA, NSA et FBI (États-Unis), ASD’s ACSC (Australie), CCCS (Canada), NCSC-UK, NCSC-NZ, CERT-NZC et C++ ne sont pas sûrs en mémoire ; publiez une feuille de route pour en sortir
Product Security Bad Practices v2.0, janvier 2025CISA et FBIde nouvelles gammes de produits pour infrastructures critiques en C ou C++ sont « dangerous » là où des langages sûrs en mémoire sont disponibles

La recommandation conjointe le dit sans détour : « Programming languages such as C and C++ are examples of memory unsafe programming languages »6. La CISA et le FBI vont plus loin, et qualifient de dangereux « the development of new product lines for use in service of critical infrastructure or NCFs in a memory-unsafe language (e.g., C or C++) » quand une solution sûre en mémoire pourrait être utilisée7. Ce sont des recommandations, pas une loi. Mais le stockage sous des services critiques est précisément le code qu’elles visent, et ce sont deux OSD de nouvelle génération qui seront jugés à cette aune.

FlashStore les satisfait. Il est écrit en Rust, et l’ADR de croit en donne la raison en une ligne : « Storage = correctness-critical; memory-safety bugs = data loss »8. Le compilateur vérifie la sûreté mémoire partout sauf dans le code marqué unsafe, et le même ADR cantonne celui-ci aux modules FFI, DMA, NVMe et pilotes réseau, chacun avec un commentaire SAFETY8. Je l’ai compté dans le snapshot : 1 216 lignes qui mentionnent unsafe sur 696 125 lignes de Rust, environ 0,17 %, et elles se trouvent dans les crates RDMA, runtime, NVMe et magasin, là où le code parle au matériel. La recommandation conjointe nomme elle-même cette porte de sortie, en notant que Rust « can contain the ‘unsafe’ keyword »6, c’est donc la mesure honnête : pas zéro, mais peu, cloisonné, et aux endroits où on l’attendrait. Le C qu’il appelle, SPDK et DPDK, se trouve derrière ces mêmes frontières8.

Crimson, non. C’est un nouvel OSD écrit en C++ sur un framework C++13, le langage que les agences ci-dessus désignent comme non sûr en mémoire. Aucune de ses lignes n’est à la portée d’une vérification de sûreté mémoire par le compilateur, et dans sa configuration par défaut il confie le magasin à BlueStore, qui est aussi en C++.

CrimsonFlashStore
LangageC++Rust
Sûreté mémoire vérifiée par le compilateurnonoui, hors unsafe
Code non vérifiéla totalitéenviron 0,17 % des lignes, pilotes et FFI
Magasin par défautBlueStore, C++FlashStore, Rust
Conforme aux recommandations des Five Eyes sur la sûreté mémoirenonoui

Les développeurs de Ceph n’ont pas choisi le C++ à la légère ; Crimson est né d’une base de code C++, et réécrire sur place voulait dire y rester. C’est un chemin d’ingénierie raisonnable. Il laisse quand même l’OSD Ceph de nouvelle génération écrit dans le seul type de langage que les agences de cinq pays ont demandé au nouveau code critique d’abandonner.

Comment chacun rejoint un cluster

C’est la plus grosse différence pratique entre les deux, et elle n’a rien à voir avec la performance.

Un OSD FlashStore rejoint les pools que vous avez déjà. Il prend place dans les mêmes placement groups à côté des OSD BlueStore classiques, et vous changez un disque à la fois2.

Un OSD Crimson, non. Loin de là. La documentation d’Umbrella dit : « Crimson OSD won’t instantiate PGs from non-Crimson pools »1. Le code fait exactement ça. Quand le moniteur demande à un OSD Crimson de créer un PG dans un pool sans l’option crimson, il journalise « pool lacks crimson flag » et annule la création9.

Les pools que chacun serviravotre pool existantsans option crimsonOSD classiqueBlueStoreOSD FlashStoremêmes PGOSD Crimsonpools crimson seulementPG ignorésnouveau pool, --crimsonautoscale désactivé
FlashStore prend des PG dans vos pools existants. Crimson ne sert que les pools créés avec l’option crimson, il lui faut donc de nouveaux pools et les données copiées dedans.

Un essai de Crimson veut donc dire de nouveaux pools, créés avec l’option crimson, et vos données déplacées dedans. Et ces pools viennent avec des conditions que le moniteur impose :

Règle des pools Crimson (Umbrella)Où
L’autoscaling des PG doit être désactivé à la création du poolOSDMonitor, création de pool10
Fusion de PG (réduire pg_num) refuséeOSDMonitor, changement de pg_num11
Scission de PG permise seulement tant que crimson_allow_pg_split vaut trueidem, et l’option12
Les pools EC doivent être du type EC optimisé, sans exceptionOSDMonitor, création de pool13
Pas d’OMAP sur les pools ECidem13

FlashStore sert les pools classiques, répliqués comme à code d’effacement, et décline les configurations EC qu’il ne prend pas en charge au lieu de les refuser au niveau du moniteur14. Aucune des deux approches n’est mauvaise. Mais l’une vous laisse tester sur une copie de la disposition réelle de vos pools, et l’autre vous oblige d’abord à en construire une à part.

Aucun passage pour les pools que vous avez déjà

Peut-on alors transformer un pool existant en pool Crimson, et le faire passer un disque à la fois ? Non.

La documentation d’Umbrella dit de Crimson qu’il est « aiming to allow seamless migration from existing ceph-osd deployments »1. Il y vise, seulement. La version ne le fait pas, et le code source montre pourquoi elle ne le peut pas. L’option crimson est une option de ceph osd pool create et de rien d’autre15. ceph osd pool set n’a aucune variable crimson à poser sur un pool qui existe déjà16. Et un OSD Crimson ignore chaque PG d’un pool sans l’option, comme on l’a vu plus haut9. Je n’ai trouvé aucun outil de conversion, ni dans le code source ni dans la documentation.

Déplacer un pool existantCrimson (Umbrella)FlashStore, aujourd’hui
Garder le même poolnon, un nouveau pool est requisoui
Poser l’option plus tardnon, seulement à la créationinutile
Comment les données passentvous les copiez, de pool à poolle cluster fait le backfill
Clients à redirigeroui, vers le nouveau poolnon
Un disque à la foisnonoui

Passer à Crimson revient donc à une copie de données que vous menez vous-même : les images RBD peuvent faire l’objet d’une migration à chaud « between different pools »17, et les données objet ou fichier demandent ce que vos applications utilisent pour les copier. Chaque client doit ensuite être redirigé vers le nouveau pool.

FlashStore est compatible avec les pools que vous faites tourner aujourd’hui. Vous le préparez sur un disque, le cluster fait le backfill des placement groups qui lui sont attribués, et vos clients ne remarquent jamais que le pool a changé sous eux, parce qu’il n’a pas changé18. Toute la différence est là, entre une réécriture qui rejoint votre cluster et une qui reste à côté.

Ce que chacun dit au moniteur

Crimson s’annonce. Au démarrage, il envoie osd_type=crimson19, et le moniteur refuse de le laisser entrer tant que l’option d’OSDMap allow_crimson n’est pas posée, avec une ligne de journal qui dit que crimson-osd « is considered unstable and may result in crashes or data loss »20. Arriver jusque-là demande quatre commandes tirées de la documentation, dont la première pose une option appelée enable_experimental_unrecoverable_data_corrupting_features1.

FlashStore fait l’inverse. Il n’envoie aucun osd_type et déclare osd_objectstore=bluestore, si bien que le moniteur voit un OSD classique et ne pose aucune question21. L’article précédent explique pourquoi : le moniteur d’Umbrella conditionne des fonctionnalités comme les EC overwrites au fait que chaque OSD du pool se déclare BlueStore21. C’est pour les moniteurs et gestionnaires d’origine en production aujourd’hui. Sur les propres builds de Ceph de croit, patchés pour le connaître, FlashStore se déclare flashstore21.

Ce que le moniteur vérifie au démarrageOSD Crimsonosd_type=crimsonmon : allow_crimson posée ?set-allow-crimsonnon : démarrage refusé"crashes or data loss"OSD FlashStoresans osd_typemon : un OSD classiqueobjectstore=bluestoredémarre, sans optionsert les pools existants
Crimson doit être admis, nommément, derrière une option contre laquelle le moniteur met en garde. FlashStore entre comme un OSD classique.

Je préfère qu’un logiciel me dise ce qu’il est. Crimson le fait. Sa façon de faire est la plus honnête, et le nom de l’option ne vous laisse aucun doute sur ce que vous acceptez. Celle de FlashStore est ce qui rend le remplacement direct possible sur les moniteurs et gestionnaires d’origine que l’on fait tourner aujourd’hui, et c’est une mesure de compatibilité, pas l’état final. Les deux sont délibérées, et les deux sont écrites noir sur blanc. Sachez simplement à laquelle vous avez affaire quand vous comptez vos OSD.

Cœurs : des réacteurs contre des threads épinglés en polling

Les deux projets ont jeté les pools de threads. Tant mieux. Les deux font tourner un thread par cœur et répartissent leur travail par cœur. La différence tient à ce qu’ils demandent à l’exploitant et à la force avec laquelle ils s’accrochent au cœur.

CrimsonFlashStore
Unité de travailun réacteur Seastar par cœurun thread épinglé par cœur
Nombre de cœurscrimson_cpu_num, sans défaut, à fixer obligatoirementflashstore_cores, 8 par défaut
Épinglé aux cœursseulement avec crimson_cpu_setoui, flashstore_lcores
Au repospolling 200 µs, puis sommeilpolling, repos adaptatif
Busy-polling completen option, crimson_poll_modele principe même, avec repli au repos
Changement après déploiementnonshards du magasin fixés à la préparation

Sur Crimson, crimson_cpu_num « does not have a default value », doit être fixé avant le déploiement des OSD, et « cannot be changed after deployment »1. Il n’épingle pas les threads à moins de fixer aussi crimson_cpu_set, que la documentation décrit comme « generally less recommended due to its complexity »1. Au repos, le réacteur fait du polling pendant 200 µs avant de se rendormir, et un mode de polling complet existe « at the expense of 100% cpu usage », désactivé par défaut22. SeaStore refuse en outre tout changement du nombre de réacteurs après mkfs23.

FlashStore épingle par conception, fait du polling par conception, et se met en retrait au repos2425. Son nombre de shards de magasin est fixé à la préparation du magasin, la même contrainte à un autre endroit26.

En pratique, les deux veulent des cœurs entiers et les deux veulent que vous les dimensionniez avant de déployer. Crimson fait du polling un choix auquel vous adhérez. FlashStore en fait le défaut et laisse la logique de repos récupérer une partie du CPU.

Le magasin par défaut de Crimson, c’est BlueStore

C’est la partie qui m’a surpris. Elle n’aurait pas dû.

Crimson a deux sortes de magasins d’objets. Les natifs tournent à l’intérieur du réacteur Seastar ; les non natifs passent par « a thread pool proxy » vers des « alien threads: worker threads not managed by Seastar »1. SeaStore est le natif. BlueStore est non natif. Et c’est BlueStore qui est le défaut.

La documentation est franche là-dessus. SeaStore « is the primary native object store for Crimson OSD, though it is not the default as the support is in early stages »1. Cephadm déploie Crimson avec --objectstore bluestore sauf indication contraire, et même alors SeaStore ne peut pas être déployé avec --method raw ; on vous dit d’utiliser LVM1.

Le magasin par défaut de Crimson, face à FlashStoreCrimson, magasin par défautréacteurs Seastarcrimson_cpu_numproxy de pool de threadssortie hors du réacteurthreads aliencrimson_bluestore_num_threadsBlueStoreRocksDB sur BlueFSFlashStorecœur qui possède le PGépinglé, en pollingshard magasin, même cœuraucun passage de mainfile NVMe, même cœurSPDK ou io_uring
Un OSD Crimson par défaut fait sortir chaque opération de magasin de son réacteur vers un pool de threads ordinaires qui font tourner BlueStore. FlashStore garde tout le chemin sur le cœur qui possède le PG.

Un OSD Crimson déployé aujourd’hui avec les valeurs par défaut fait donc tourner un frontal Seastar au-dessus des mêmes BlueStore, RocksDB et BlueFS que l’OSD classique, avec crimson_bluestore_num_threads threads mis de côté pour eux22. Côté magasin, rien n’a bougé par rapport à l’OSD classique. C’est une façon sensée de construire un chemin de migration. C’est aussi pourquoi comparer « Crimson » à FlashStore sur la performance ne veut pas dire grand-chose si l’on ne précise pas quel magasin Crimson faisait tourner.

La comparaison juste pour le magasin, c’est SeaStore contre FlashStore. C’est le reste de cet article.

SeaStore et FlashStore : où vivent les métadonnées

Les deux magasins ont été écrits pour le NVMe dès le départ, les deux sont répartis par cœur, et les deux gardent leurs métadonnées dans leurs propres arbres B plutôt que dans RocksDB. Leurs agencements restent très différents.

SeaStore donne à chaque réacteur sa propre racine27. En dessous se trouvent un arbre d’onodes, un arbre LBA et un arbre de backrefs. L’onode de chaque objet pointe ensuite vers son propre arbre B d’OMAP et son propre arbre B de XATTR, et vers des extents de données à adresses logiques27. L’arbre LBA fait correspondre ces adresses logiques à des adresses physiques, si bien qu’un bloc peut bouger sur le disque sans que les arbres de l’objet changent ; la documentation fait de cette indirection la raison pour laquelle la plupart des extents « can be relocated freely »27.

FlashStore met tout dans un seul arbre B+ en copie sur écriture par shard : onodes, xattrs, OMAP, cartes d’extents avec un crc32c par bloc de 4 Kio, le journal des PG et la bitmap de l’allocateur28. Les cartes d’extents pointent directement vers des blocs physiques. Il n’y a pas de couche logique entre les deux.

Où vivent les métadonnéesSeaStoreracinearbre onodearbre LBAarbre backrefonodeOMAPson arbre BXATTRson arbre Bdonnéesadr. logiqueadresse logique, puis arbre LBA, puis disqueFlashStoreun arbre B+ COW par shardonodes, xattrsOMAPcartes d'extents + crc32cjournal PG, info PGbitmap d'allocationcarte d'extents, puis disque
SeaStore : un arbre par sorte de chose, un arbre B par objet pour l’OMAP et les xattrs, et un arbre LBA pour trouver les données. FlashStore : un arbre par shard, qui pointe directement vers le disque.

Les deux choix ont une raison. L’indirection de SeaStore est ce qui rend son nettoyeur peu coûteux : il peut déplacer des données vivantes sans réécrire chaque arbre qui pointe vers elles. FlashStore n’en a pas besoin, parce qu’il n’a pas de nettoyeur, comme on le verra plus bas. Son ADR range « Per-object omap subtree/root » parmi les solutions envisagées et rejetées28.

Une différence à connaître sur les sommes de contrôle : SeaStore calcule son crc32c sur un extent entier en cache29, là où FlashStore en garde un par bloc de 4 Kio28.

L’ordre dans lequel une écriture est validée

Le type de périphérique par défaut de SeaStore est SSD, qui utilise le backend segmenté30. Sur ce backend, une transaction est un enregistrement de journal portant des deltas, et deux choses peuvent arriver aux données.

Les extents petits et éphémères peuvent voyager en ligne dans l’enregistrement de journal, et l’enregistrement constitue alors toute la validation27. Les extents plus gros ou plus durables vont dans des segments hors ligne séparés, et la documentation fixe alors l’ordre : le « final record with the deltas should be written only once the other blocks are persisted »27. Ce sont deux écritures en série, la même forme que la validation données puis RocksDB de BlueStore.

FlashStore écrit l’extent de données et l’unité de WAL en même temps, met le crc32c des nouvelles données dans l’enregistrement du WAL pour que le rejeu puisse le vérifier, et acquitte quand les deux sont durables28. Un seul aller-retour vers le périphérique, quelle que soit la taille.

Quand la validation peut partirSeaStorepetit extentenreg. de journalextent en ligne + deltasacquit1 trajetSeaStorehors ligneextent en segment OOLattente de persistanceenreg. de journaldeltasacquit2 trajetsFlashStoredonnées, 4 Kio neufsunité WAL, crc donnéesacquit1 trajettemps
SeaStore sur son périphérique segmenté par défaut : un aller-retour quand l’extent tient dans l’enregistrement de journal, deux en série quand il part hors ligne. FlashStore : données et enregistrement de journal ensemble.

L’importance de tout ça dépend de votre charge, exactement comme dans la comparaison avec BlueStore. À faible profondeur de file, où les clients attendent chaque écriture, un second aller-retour est une vraie latence. Sous charge, le regroupement en masque l’essentiel.

Récupérer l’espace

L’autre moitié d’une conception structurée en journal, c’est le ménage.

SeaStore, sur le backend segmenté, n’écrit jamais que dans des segments ouverts. Avant qu’un segment puisse être réutilisé, ses blocs vivants doivent être réécrits ailleurs, et le document de conception dit ce que ça coûte : « we must ‘clean’ one byte of an existing segment for every byte written at steady state »27. Il mêle une partie de ce nettoyage aux écritures en cours, pour éviter les pics, et fait le reste en arrière-plan quand le disque est plus calme27. La taille de segment par défaut est de 64 Mio31.

SeaStore a bien un second backend pour le NVMe, le random block manager, que la documentation dit « Preferred for fast NVMe devices where overwrites are efficient enough that log structured updates aren’t worth the overhead »27. Ce n’est pas le défaut. Vous le choisissez avec seastore_main_device_type30.

FlashStore n’a pas de nettoyeur de segments. Aucun. Un bloc remplacé retourne à l’allocateur du shard une fois qu’un checkpoint l’a dépassé, ce qui arrive toutes les cinq secondes tant qu’il reste du travail non persisté, ou plus tôt quand l’anneau du WAL est à moitié plein28. Son document de conception a rejeté d’emblée une disposition structurée en journal28. Cela ne veut pas dire qu’il n’a aucun travail d’arrière-plan : il fusionne et compacte toujours des pages d’arbre et défragmente l’espace libre, au rythme permis par les I/O clientes28. Mais il ne copie jamais vos données vivantes pour faire de la place.

Récupérer l'espaceSeaStore, segmenté (défaut)segment ferméblocs vivants + mortsle nettoyeur réécritle vivant ailleurssegment vidediscard, réemploirégime établi : nettoyer environ un octet par octet écritFlashStorebloc remplacépar un extent neufgardé jusqu'au checkpoint5 s ou WAL à 50 %rendu à la bitmaprien de vivant déplacé
Le backend par défaut de SeaStore paie ses écritures séquentielles avec un nettoyeur qui déplace les données vivantes. FlashStore libère les blocs remplacés sur place après un checkpoint et ne déplace rien.

Sur la flash, qui fait déjà tourner son propre ramasse-miettes à l’intérieur du disque, je préfère que l’OSD n’en fasse pas tourner un second par-dessus. La documentation de SeaStore semble d’accord, vu ce qu’elle dit du backend RBM. La différence, c’est que FlashStore en a fait la seule option et que SeaStore en a fait l’option qui n’est pas par défaut.

Sur quoi chacun tourne

Crimson (Umbrella)FlashStore
HDDoui, avec BlueStore ; SeaStore a un type de segment HDDnon
NVMeouioui, la seule cible
Protection contre les coupures de courantaucune exigence annoncéeexigée, mkfs refuse sans
Disposition des périphériquesLVM pour SeaStore via cephadmnamespaces entiers, pas de partitions
Protocole réseaumsgr2 seulementmsgr2 seulement
Backend d’I/Oio_uring par défaut ; linux-aio, epollSPDK par défaut, tier io_uring
Poolsnouveaux pools avec l’option crimsonpools classiques existants
Déplacer les données existantesles copier vers un nouveau poolbackfill dans le même pool
Déployé aveccephadm, --osd-type crimsonpaquets, croit-flashstore-tool
Build recommandédernier build CI de mainsnapshots de version

Crimson garde l’étendue. La documentation dit que SeaStore « may not be suitable for traditional HDDs », mais que « Crimson will continue to support BlueStore ensuring compatibility with HDDs and slower SSDs »1, et le document de conception de SeaStore mentionne toujours un intérêt pour les HDD27. Sa messagerie refuse la v1 net, « ProtocolV1 is no longer supported »32, le même choix que FlashStore33. Sa documentation recommande « one of the latest available builds, as Crimson evolves rapidly », ce qui veut dire en pratique des images CI de main1.

FlashStore réduit tout au NVMe avec protection contre les coupures de courant, et tire sa simplicité de là34. C’est exactement le compromis que décrit l’ADR de croit, vu de l’autre côté.

Deux réponses à la même question

Les deux projets sont partis du même constat : l’OSD classique gaspille le matériel rapide. Ils ont donné des réponses très différentes.

La réponse de Crimson est celle de la communauté. Réécrire l’OSD sur place, à l’intérieur de Ceph, garder chaque ancien magasin et chaque ancien disque en état de marche pendant que le nouveau magasin mûrit, et laisser tout le monde voir le travail au fil de l’eau. C’est lent, et ça se voit. Dans Umbrella, l’OSD Crimson par défaut fait encore tourner BlueStore à travers un pool de threads, ses propres pools sont tenus à l’écart des vôtres, et l’activer veut dire taper les mots « unrecoverable data corrupting ». Mais il appartient à tous ceux qui font tourner Ceph, et personne ne peut vous l’enlever.

La réponse de FlashStore est celle d’un éditeur. Choisir une cible plus étroite, le NVMe avec protection contre les coupures de courant, jeter tout ce qui n’existait que pour d’autres matériels, et livrer un magasin qui entre dans les pools que vous avez déjà. C’est plus rapide, et ça se voit aussi. Mais il vient d’une seule entreprise, sous forme de snapshots en lecture seule jusqu’à sa première version de production, et sur un cluster d’origine, il entre en disant au moniteur qu’il est BlueStore.

Je travaille pour cette entreprise, alors pesez la suite en conséquence. croit a fait le bon pari technique pour les clusters entièrement flash. Crimson a fait le bon pari pour Ceph en tant que projet. Ce n’est pas la même chose. Un projet qui sert tout le monde ne peut pas abandonner les HDD. Un éditeur le peut, et devrait le faire, si c’est ce que ses clients achètent.

Ce que je ne ferais pas, c’est choisir entre les deux sur un graphique de benchmark venu de l’un ou l’autre camp. Les chiffres de Crimson dépendent de celui de ses trois magasins qui tournait ; ceux de FlashStore sortent du propre labo de croit. Les deux projets publient leurs documents de conception. Lisez-les, puis mettez les deux sur les disques que vous déploieriez réellement et faites tourner votre propre charge. Celui qui fait encore ce que disent ses documents quand ce sont vos données qui sont en jeu est celui qui vaut la peine d’être attendu.


  1. Ceph Umbrella, Crimson (Tech Preview) — « the next generation ceph-osd », « not suitable for production use », les options requises, crimson_cpu_num, backends natifs et non natifs, SeaStore « not the default », --method raw non pris en charge. Source : doc/crimson/crimson.rst at v21.2.0. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  2. croit ceph-rust, README at snapshot 48f9014 — revendication de remplacement direct, préversion depuis le 9 novembre 2026, GA au T1 2027, « not yet recommended for production data », « no issue tracker, no contribution workflow ». ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  3. Seastar — le framework C++ sur lequel Crimson est construit. ↩︎ ↩︎

  4. ceph-rust ADR 0003, green-field, no Crimson fork — « Crimson = C++/seastar, tries to support everything (HDD, alienstore/BlueStore, all pool types) -> complexity. Complex code is never fast. » ; fork rejeté pour « C++, complexity, LGPL ». ↩︎ ↩︎ ↩︎

  5. ceph-rust ADR 0164, licences — daté du 2026-10-17 ; démon en LGPL-3.0-only. ↩︎

  6. CISA, NSA, FBI, ASD’s ACSC, CCCS, NCSC-UK, NCSC-NZ, CERT-NZ: The Case for Memory Safe Roadmaps (December 2023) — « Programming languages such as C and C++ are examples of memory unsafe programming languages » ; Rust « can contain the ‘unsafe’ keyword ». ↩︎ ↩︎

  7. CISA and FBI: Product Security Bad Practices, v2.0 (January 2025) — les nouvelles gammes de produits pour infrastructures critiques « in a memory-unsafe language (e.g., C or C++) where readily available alternative memory-safe languages could be used is dangerous ». ↩︎

  8. ceph-rust ADR 0002, language: Rust — « Storage = correctness-critical; memory-safety bugs = data loss » ; unsafe « confined to ffi/dma/nvme/net-driver modules with SAFETY comments » ; SPDK et DPDK via FFI. ↩︎ ↩︎ ↩︎

  9. Ceph v21.2.0, crimson/osd/shard_services.cc — « ignoring pgid {}, pool lacks crimson flag ». ↩︎ ↩︎

  10. Ceph v21.2.0, OSDMonitor.cc, crimson pool creation — « crimson-osd does not support changing pg_num or pgp_num, pg_autoscale_mode must be set to ‘off’ ». ↩︎

  11. Ceph v21.2.0, OSDMonitor.cc, crimson pg_num changes — « pg merging is not yet supported in Crimson ». ↩︎

  12. Ceph v21.2.0, crimson_allow_pg_split — « Allow Crimson pools to increase their PG count (split) », true par défaut. ↩︎

  13. Ceph v21.2.0, OSDMonitor.cc, EC pools for Crimson — « For Crimson - only EC-optimized pools are supported », « Omap is not supported by EC pools in crimson ». ↩︎ ↩︎

  14. ceph-rust docs, erasure-coded pools — EC classique et optimisé servis par défaut ; pools non pris en charge déclinés par l’OSD. ↩︎

  15. Ceph v21.2.0, MonCommands.h, osd pool create — name=crimson,type=CephBool,req=false, le seul endroit où l’option est acceptée. ↩︎

  16. Ceph v21.2.0, MonCommands.h, osd pool set — les variables modifiables ; crimson n’en fait pas partie. ↩︎

  17. Ceph Umbrella, RBD image live-migration — « RBD images can be live-migrated between different pools ». ↩︎

  18. ceph-rust docs, migrate from classic — ajouter ou libérer un disque, préparer FlashStore, laisser le backfill déplacer les données. ↩︎

  19. Ceph v21.2.0, crimson/osd/osd.cc — m->metadata["osd_type"] = "crimson". ↩︎

  20. Ceph v21.2.0, OSDMonitor.cc, boot check — « Disallowing boot of crimson-osd without allow_crimson OSDMap flag », « considered unstable and may result in crashes or data loss ». ↩︎

  21. ceph-rust ADR 0019, report osd_objectstore=bluestore — aucune clé osd_type, les verrous de fonctionnalités BlueStore du moniteur. ↩︎ ↩︎ ↩︎

  22. Ceph v21.2.0, crimson.yaml.in — crimson_reactor_idle_poll_time_us 200, crimson_poll_mode « at the expense of 100% cpu usage », false par défaut, crimson_bluestore_num_threads. ↩︎ ↩︎

  23. Ceph v21.2.0, seastore_require_partition_count_match_reactor_count — « disable osd shards changes upon restart », true par défaut. ↩︎

  24. ceph-rust ADR 0006, thread-per-core runtime — un thread épinglé en busy-polling par cœur, PG possédés par un seul cœur. ↩︎

  25. ceph-rust ADR 0004, storage I/O — SPDK et le tier io_uring, repos calé sur le périphérique. ↩︎

  26. ceph-rust docs, configuration reference — flashstore_cores 8 par défaut, flashstore_lcores, flashstore_store_shards fixé à la préparation. ↩︎

  27. Ceph Umbrella, SeaStore developer documentation — racine par réacteur, arbres onode, OMAP, LBA et backref, « clean » un octet par octet écrit, l’ordre de l’enregistrement de journal, le backend RBM. Source : doc/dev/crimson/seastore.rst at v21.2.0. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  28. ceph-rust ADR 0021, storage engine — un arbre B+ COW par shard, validation parallèle, checkpoints, maintenance en arrière-plan, solutions rejetées dont la structure en journal et « Per-object omap subtree/root ». ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  29. Ceph v21.2.0, crimson/os/seastore/cached_extent.h — « Returns crc32c of buffer ». ↩︎

  30. Ceph v21.2.0, seastore_main_device_type — « The main device type seastore uses (SSD or RANDOM_BLOCK_SSD) », SSD par défaut. ↩︎ ↩︎

  31. Ceph v21.2.0, seastore_segment_size — 64 Mio par défaut. ↩︎

  32. Ceph v21.2.0, crimson/net/SocketMessenger.cc — « ProtocolV1 is no longer supported ». ↩︎

  33. ceph-rust ADR 0168, out of scope — msgr1 exclu, v2 seulement. ↩︎

  34. ceph-rust docs, hardware and host requirements — PLP exigée, namespaces entiers. ↩︎