Eerst de disclosure: ik werk voor croit, dat FlashStore geschreven heeft. Alles hieronder is gelezen uit de broncode en documentatie van Ceph op v21.2.0 en uit de gepubliceerde ceph-rust-snapshot van croit, allemaal gelinkt onderaan de pagina. Waar de eigen redenering van croit aan één kant van een argument staat, zeg ik van wie die redenering is.

Twee Herschrijvingen Van Dezelfde Daemon

De klassieke Ceph-OSD is een C++-server met threads die is opgegroeid op draaiende schijven. Op snelle NVMe en snelle netwerken besteedt hij een groot deel van zijn CPU aan dingen die niet het opslaan van je data zijn: ops doorgeven tussen threadpools, locks nemen, wachten op andere threads. Twee projecten zijn begonnen om dat op te lossen door de OSD helemaal te herschrijven.

Het ene is Crimson, van Ceph zelf. De documentatie van Umbrella noemt het “the next generation ceph-osd”, gebouwd “to deliver enhanced performance on fast network and storage devices”1. Het andere is de FlashStore-OSD van croit, uit het ceph-rust-project, in public preview sinds 9 november 20262.

Allebei zeggen ze drop-in-vervangers te zijn. Allebei zeggen ze voor NVMe te zijn. Allebei zitten ze in preview, en geen van beide hoort vandaag productiedata te bewaren. Dus als je NVMe-Ceph draait en je je afvraagt welke je in de gaten moet houden, loont het om te weten waar ze echt verschillen, want dat is niet waar de koppen het doen vermoeden.

Deze post vergelijkt ze zoals je ze aantreft op Ceph 21.2.0, Umbrella: Crimson zoals die release het documenteert en levert, tegenover FlashStore, dat tegen precies die release gebouwd en getest is2. Hij volgt op FlashStore Tegenover Umbrella BlueStore, en alles wat daar al over FlashStore gezegd is, neem ik hier als bekend aan.

Twee herschrijvingen van één daemonklassieke ceph-osdC++, threadsCrimsonCeph upstream, C++ op Seastarcroit-flashstore-osdcroit, Rust, eigen runtimeBlueStorestandaardSeaStorenativeCyanStoregeen dataFlashStorede enige store
Twee herschrijvingen van de klassieke OSD. Crimson houdt drie stores om uit te kiezen, met BlueStore als standaard; FlashStore heeft er één.

Waar Elk Vandaan Komt

Het eerste verschil is wie het bouwt en hoe.

CrimsonFlashStore
Gebouwd doorCeph upstream, in de hoofdboomcroit
TaalC++Rust
FrameworkSeastareigen single-thread executor van croit
Codein ceph/cephclean-room herschrijving, geen Ceph-code gelinkt
Ontwikkelingupstream, openread-only snapshots in preview; open na de eerste productierelease
Licentiedie van Cephdaemon LGPL-3.0, clients MPL-2.0
Status in eigen woorden“not suitable for production use”“not yet recommended for production data”
Geplande GAniet genoemdQ1 2027

Crimson staat in Ceph’s eigen repository en wordt gebouwd door Ceph’s eigen ontwikkelaars. Het is geschreven op Seastar, een C++-framework voor thread-per-core-servers dat uit ScyllaDB komt3. De docs van Umbrella zeggen het zonder omwegen: het “is in a tech-preview stage and is not suitable for production use”1.

FlashStore is vanaf nul in Rust geschreven en linkt helemaal geen Ceph-code; de C++ van Ceph wordt als referentie gelezen en opnieuw geïmplementeerd vanuit croits eigen specificaties4. De README zegt dat het voor testen en evaluatie is en “not yet recommended for production data”, met algemene beschikbaarheid gepland voor het eerste kwartaal van 20272. De publieke repository is een read-only snapshot: “no issue tracker, no contribution workflow”2.

Die rij is het waard om goed te lezen. Crimson wordt in het open ontwikkeld, en iedereen kan de pull requests lezen en erover in discussie gaan. FlashStore komt voorlopig binnen als afgewerkte snapshots van één bedrijf: je kunt elke regel lezen, maar je kunt er nog geen patch naartoe sturen. Dat is de preview-fase, niet het plan. De preview is er om feedback uit de community te verzamelen terwijl croit intern zijn productietestcases doorloopt, voordat het de OSD als veilig voor gebruik aanmerkt. Na die eerste productierelease wordt de ontwikkeling open, dezelfde weg die de meeste door bedrijven gedragen open-sourceprojecten nemen. Dat komt van binnen croit en niet uit een gepubliceerde roadmap, dus houd ze eraan.

croit heeft wel naar een fork van Crimson gekeken en heeft opgeschreven waarom het dat niet deed. De ADR zegt dat Crimson “tries to support everything (HDD, alienstore/BlueStore, all pool types)”, en voegt toe “Complex code is never fast”4. Dat is croits mening over Crimson, geen meting, en zo zou ik het ook behandelen. Dezelfde ADR wees een fork deels af vanwege de LGPL4, en acht dagen later gaf croit zijn eigen daemon een LGPL-3.0-licentie5. De licentie was dus nooit echt de reden.

Geheugenveiligheid: Rust Tegenover C++

Een OSD is de code die je data vasthoudt. Een use-after-free of een buffer overrun daarin is geen crash waar je van herstart; het is corrupte data op schijf, gekopieerd naar elke replica. Dat is precies de klasse bugs waarvan de westerse cyberagentschappen de industrie de afgelopen drie jaar voorhouden dat ze die moet wegontwerpen.

RichtlijnWie er zijn naam onder zetteWat het zegt
The Case for Memory Safe Roadmaps, december 2023CISA, NSA en FBI (VS), ASD’s ACSC (Australië), CCCS (Canada), NCSC-UK, NCSC-NZ, CERT-NZC en C++ zijn niet geheugenveilig; publiceer een roadmap om ervan af te stappen
Product Security Bad Practices v2.0, januari 2025CISA en FBInieuwe productlijnen voor kritieke infrastructuur in C of C++ zijn “dangerous” waar geheugenveilige talen beschikbaar zijn

De gezamenlijke richtlijn zegt het zonder omwegen: “Programming languages such as C and C++ are examples of memory unsafe programming languages”6. CISA en de FBI gaan verder, en noemen “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++)” gevaarlijk als er een geheugenveilig alternatief gebruikt had kunnen worden7. Dat is een richtlijn, geen wet. Maar opslag onder kritieke diensten is precies de code waar hij op mikt, en dit zijn allebei OSD’s van de volgende generatie die eraan afgemeten zullen worden.

FlashStore voldoet eraan. Het is geschreven in Rust, en de ADR van croit geeft de reden in één regel: “Storage = correctness-critical; memory-safety bugs = data loss”8. De compiler controleert geheugenveiligheid overal behalve in code die als unsafe gemarkeerd is, en dezelfde ADR beperkt dat tot de FFI-, DMA-, NVMe- en netwerkdrivermodules, elk met een SAFETY-commentaar8. Ik heb het geteld in de snapshot: 1.216 regels die unsafe noemen op 696.125 regels Rust, ongeveer 0,17%, en ze zitten in de RDMA-, runtime-, NVMe- en store-crates, waar de code met hardware praat. De gezamenlijke richtlijn noemt die nooduitgang zelf, met de opmerking dat Rust “can contain the ‘unsafe’ keyword”6, dus dat is de eerlijke maatstaf: niet nul, maar klein, afgebakend, en op de plekken waar je het zou verwachten. De C die het wel aanroept, SPDK en DPDK, zit achter diezelfde grenzen8.

Crimson voldoet er niet aan. Het is een nieuwe OSD, geschreven in C++ op een C++-framework13, en dat is de taal die de agentschappen hierboven als niet geheugenveilig noemen. Geen regel ervan valt binnen wat een compiler op geheugenveiligheid kan controleren, en in de standaardconfiguratie geeft het de store door aan BlueStore, en dat is ook C++.

CrimsonFlashStore
TaalC++Rust
Geheugenveiligheid door de compiler gecontroleerdneeja, buiten unsafe
Ongecontroleerde codeallesongeveer 0,17% van de regels, driver- en FFI-code
Standaard-storeBlueStore, C++FlashStore, Rust
Past bij de Five Eyes-richtlijnen voor geheugenveiligheidneeja

De ontwikkelaars van Ceph hebben niet achteloos voor C++ gekozen; Crimson is gegroeid uit een C++-codebase, en ter plekke herschrijven betekende daarin blijven. Dat is een redelijk engineeringpad. Het laat de Ceph-OSD van de volgende generatie nog steeds geschreven in precies het soort taal waarvan de agentschappen van vijf landen gevraagd hebben dat nieuwe kritieke code het achter zich laat.

Hoe Elk Bij Een Cluster Aansluit

Dit is het grootste praktische verschil tussen de twee, en het gaat helemaal niet over performance.

Een FlashStore-OSD sluit aan bij de pools die je al hebt. Hij zit in dezelfde placement groups naast klassieke BlueStore-OSD’s, en je vervangt één schijf tegelijk2.

Een Crimson-OSD doet dat niet. Bij lange na niet. De docs van Umbrella zeggen: “Crimson OSD won’t instantiate PGs from non-Crimson pools”1. De code doet precies dat. Als de monitor een Crimson-OSD vraagt een PG aan te maken in een pool zonder de crimson-vlag, logt hij “pool lacks crimson flag” en annuleert hij het aanmaken9.

Welke pools elk bedientje bestaande poolgeen crimson-vlagklassieke OSDBlueStoreFlashStore-OSDdezelfde PG'sCrimson-OSDalleen crimson-poolsPG's genegeerdnieuwe pool, --crimsonautoscale uit
FlashStore neemt PG’s in je bestaande pools. Crimson bedient alleen pools die met de crimson-vlag zijn aangemaakt, dus het heeft nieuwe pools nodig en je data moet erheen gekopieerd worden.

Een proef met Crimson betekent dus nieuwe pools, aangemaakt met de crimson-vlag, en je data die daarnaartoe verhuist. En die pools komen met voorwaarden die de monitor afdwingt:

Regel voor Crimson-pools (Umbrella)Waar
PG-autoscaling moet uit staan als de pool wordt aangemaaktOSDMonitor, pool aanmaken10
PG-merging (pg_num verkleinen) geweigerdOSDMonitor, wijziging van pg_num11
PG-splitting alleen toegestaan zolang crimson_allow_pg_split true isidem, en de optie12
EC-pools moeten het geoptimaliseerde EC-type zijn, zonder uitzonderingenOSDMonitor, pool aanmaken13
Geen OMAP op EC-poolsidem13

FlashStore bedient klassieke pools, zowel gerepliceerd als erasure-coded, en slaat de EC-configuraties die het niet ondersteunt zelf af in plaats van ze bij de monitor te weigeren14. Geen van beide aanpakken is fout. Maar met de ene kun je testen op een kopie van je echte poolindeling, en met de andere moet je eerst een aparte bouwen.

Geen Weg Over Voor De Pools Die Je Al Hebt

Kun je dan een bestaande pool in een Crimson-pool veranderen, en hem schijf voor schijf overzetten? Nee.

De docs van Umbrella zeggen dat Crimson “aiming to allow seamless migration from existing ceph-osd deployments” is1. Aiming. De release doet het niet, en de broncode laat zien waarom het niet kan. De crimson-vlag is een optie op ceph osd pool create en nergens anders15. ceph osd pool set heeft geen crimson-variabele om te zetten op een pool die al bestaat16. En een Crimson-OSD negeert elke PG in een pool zonder de vlag, zoals hierboven9. Ik heb in de broncode en de docs geen conversietool gevonden.

Een bestaande pool verhuizenCrimson (Umbrella)FlashStore, vandaag
Dezelfde pool houdennee, een nieuwe pool is vereistja
Kan de pool later de vlag krijgennee, alleen bij aanmakenniet nodig
Hoe de data verhuistje kopieert hem, pool naar poolhet cluster backfillt hem
Clients omzettenja, naar de nieuwe poolnee
Eén schijf tegelijkneeja

Dat maakt een overstap naar Crimson een datakopie die je zelf draait: RBD-images kunnen live gemigreerd worden “between different pools”17, en object- of bestandsdata heeft nodig wat je applicaties ook gebruiken om ze te kopiëren. Daarna moet elke client naar de nieuwe pool gewezen worden.

FlashStore is compatibel met de pools die je vandaag draait. Je prepareert hem op een schijf, het cluster backfillt de placement groups die hij krijgt, en je clients merken nooit dat de pool onder ze veranderde, want dat deed hij niet18. Dat is het hele verschil tussen een herschrijving die bij je cluster aansluit en een die ernaast staat.

Wat Elk Aan De Monitor Meldt

Crimson maakt zich bekend. Bij het opstarten stuurt het osd_type=crimson19, en de monitor laat het niet binnen tenzij de OSDMap-vlag allow_crimson gezet is, met een logregel die zegt dat crimson-osd “is considered unstable and may result in crashes or data loss”20. Zo ver komen kost vier commando’s uit de docs, en het eerste daarvan zet een optie die enable_experimental_unrecoverable_data_corrupting_features heet1.

FlashStore doet het omgekeerde. Het stuurt helemaal geen osd_type en meldt osd_objectstore=bluestore, dus de monitor ziet een klassieke OSD en stelt geen vragen21. De vorige post legt uit waarom: de monitor van Umbrella laat features zoals EC-overwrites afhangen van elke OSD in een pool die BlueStore meldt21. Dat is voor de standaard monitors en managers die vandaag in productie draaien. Op croits eigen Ceph-builds, waar die gepatcht zijn om hem te kennen, meldt FlashStore zich als flashstore21.

Wat de monitor bij het opstarten controleertCrimson-OSDosd_type=crimsonmon: allow_crimson gezet?set-allow-crimsonnee: opstart geweigerd"crashes or data loss"FlashStore-OSDgeen osd_typemon: een klassieke OSDobjectstore=bluestorestart, geen vlag nodigbedient bestaande pools
Crimson moet bij naam binnengelaten worden, achter een vlag waar de monitor voor waarschuwt. FlashStore loopt binnen als een klassieke OSD.

Ik heb liever dat software me vertelt wat het is. Crimson doet dat. Zijn manier is de eerlijke, en de naam van de vlag laat je geen twijfel over waar je mee instemt. De manier van FlashStore is wat drop-in laat werken op de standaard monitors en managers die mensen nu draaien, en het is een compatibiliteitsmaatregel, niet de eindtoestand. Allebei zijn ze bewust gekozen, en allebei staan ze op papier. Weet alleen met welke je te maken hebt als je je OSD’s telt.

Cores: Reactors Tegenover Vastgepinde Pollende Threads

Beide projecten hebben de threadpools eruit gegooid. Mooi. Allebei draaien ze één thread per core en verdelen ze hun werk per core. Het verschil zit in hoeveel ze van de beheerder vragen en hoe hard ze de core vasthouden.

CrimsonFlashStore
Eenheid van werkSeastar-reactor per corevastgepinde thread per core
Aantal corescrimson_cpu_num, geen standaard, moet gezet wordenflashstore_cores, standaard 8
Vastgepind op coresalleen met crimson_cpu_setja, flashstore_lcores
Gedrag bij idlepollt 200 µs, gaat dan slapenpollt, adaptieve idle
Volledige busy-polloptioneel, crimson_poll_modehet ontwerp, met idle-backoff
Wijzigen na uitrolneestore-shards vast bij prepare

Over crimson_cpu_num zeggen de docs van Crimson dat het “does not have a default value”, dat het gezet moet worden voordat de OSD’s uitgerold worden, en dat het “cannot be changed after deployment”1. Het pint geen threads vast tenzij je ook crimson_cpu_set zet, wat de docs omschrijven als “generally less recommended due to its complexity”1. De reactor pollt bij idle 200 µs voordat hij weer gaat slapen, en er bestaat een volledige pollmodus “at the expense of 100% cpu usage”, standaard uit22. SeaStore weigert ook een wijziging van het aantal reactors na mkfs23.

FlashStore pint vast door ontwerp, pollt door ontwerp, en schakelt terug bij idle2425. Het aantal store-shards ligt vast wanneer de store geprepareerd wordt, dezelfde beperking op een andere plek26.

In de praktijk willen ze allebei hele cores, en willen ze allebei dat je die dimensioneert voordat je uitrolt. Crimson maakt van het pollen een keuze waar je voor kiest. FlashStore maakt het de standaard en laat de idle-logica een deel van de CPU terugwinnen.

De Standaard-Store Van Crimson Is BlueStore

Dit is het deel dat me verraste. Dat had niet gehoeven.

Crimson kent twee soorten object stores. Native stores draaien binnen de Seastar-reactor; niet-native stores draaien via “a thread pool proxy” naar “alien threads: worker threads not managed by Seastar”1. SeaStore is de native. BlueStore is niet-native. En BlueStore is de standaard.

De docs zijn er bot over. 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 rolt Crimson uit met --objectstore bluestore tenzij je iets anders zegt, en zelfs dan kan SeaStore niet uitgerold worden met --method raw; je wordt verwezen naar LVM1.

De standaard-store van Crimson, tegenover FlashStoreCrimson, standaard-storeSeastar-reactorscrimson_cpu_numthread pool proxyoverdracht uit de reactoralien threadscrimson_bluestore_num_threadsBlueStoreRocksDB op BlueFSFlashStorecore die de PG bezitvastgepind, pollendstore-shard, zelfde coregeen overdrachtNVMe-queue, zelfde coreSPDK of io_uring
Een standaard Crimson-OSD geeft elke store-operatie uit zijn reactor door aan een pool van gewone threads die BlueStore draaien. FlashStore houdt het hele pad op de core die de PG bezit.

Een Crimson-OSD die vandaag met de standaardinstellingen wordt uitgerold, draait dus een Seastar-front-end boven op dezelfde BlueStore, RocksDB en BlueFS die de klassieke OSD gebruikt, met crimson_bluestore_num_threads threads daarvoor gereserveerd22. Aan de store-kant is er niks veranderd ten opzichte van de klassieke OSD. Dat is een verstandige manier om een migratiepad te bouwen. Het is ook de reden dat “Crimson” tegen FlashStore afzetten op performance weinig zegt, tenzij je erbij zegt welke store Crimson draaide.

De eerlijke vergelijking voor de store is SeaStore tegenover FlashStore. Dat is de rest van deze post.

SeaStore En FlashStore: Waar De Metadata Staat

Beide stores zijn vanaf het begin voor NVMe geschreven, beide zijn per core gesharded, en beide bewaren hun metadata in eigen B-trees in plaats van in RocksDB. Hun indeling is toch heel verschillend.

SeaStore geeft elke reactor een eigen root27. Daaronder zitten een onode-boom, een LBA-boom en een backref-boom. De onode van elk object wijst vervolgens naar zijn eigen OMAP-B-tree en zijn eigen XATTR-B-tree, en naar data-extents met logische adressen27. De LBA-boom vertaalt die logische adressen naar fysieke, zodat een blok op schijf kan verhuizen zonder dat de eigen bomen van het object veranderen; de docs noemen die indirectie de reden dat de meeste extents “can be relocated freely”27.

FlashStore stopt alles in één copy-on-write-B+tree per shard: onodes, xattrs, OMAP, extent maps met een crc32c per blok van 4 KiB, de PG-log en de bitmap van de allocator28. Extent maps wijzen rechtstreeks naar fysieke blokken. Er zit geen logische laag tussen.

Waar de metadata staatSeaStorerootonode-boomLBA-boombackref-boomonodeOMAPeigen B-treeXATTReigen B-treedatalogisch adreslogisch adres, dan LBA-boom, dan schijfFlashStoreéén COW-B+tree per shardonodes, xattrsOMAPextent maps + crc32cPG-log, PG-infobitmap van de allocatorextent map, dan schijf
SeaStore: een boom per soort ding, een B-tree per object voor OMAP en xattrs, en een LBA-boom om de data te vinden. FlashStore: één boom per shard, die rechtstreeks naar de schijf wijst.

Beide keuzes hebben een reden. De indirectie van SeaStore is wat zijn cleaner goedkoop maakt: hij kan levende data verplaatsen zonder elke boom te herschrijven die ernaar wijst. FlashStore heeft dat niet nodig, omdat het geen cleaner heeft, zoals hieronder blijkt. De ADR noemt “Per-object omap subtree/root” onder de alternatieven die overwogen en afgewezen zijn28.

Eén verschil in checksums dat de moeite waard is om te kennen: SeaStore berekent zijn crc32c over een hele gecachete extent29, waar FlashStore er één per blok van 4 KiB bijhoudt28.

De Volgorde Waarin Een Write Commit

Het standaard device-type van SeaStore is SSD, dat de gesegmenteerde backend gebruikt30. Op die backend is een transactie een journal record met delta’s, en met de data kunnen twee dingen gebeuren.

Kleine, kortlevende extents kunnen inline in het journal record meeliften, en dan is het record de hele commit27. Grotere of langerlevende extents gaan naar aparte out-of-line-segmenten, en dan leggen de docs de volgorde vast: het “final record with the deltas should be written only once the other blocks are persisted”27. Dat zijn twee writes na elkaar, dezelfde vorm als de commit van BlueStore, eerst data en dan RocksDB.

FlashStore schrijft de data-extent en de WAL-unit tegelijk, zet de crc32c van de nieuwe data in het WAL-record zodat replay hem kan controleren, en bevestigt als beide duurzaam zijn28. Eén trip naar het device, ongeacht de grootte.

Wanneer de commit eruit kanSeaStorekleine extentjournal recordextent inline + delta'sack1 tripSeaStoreout-of-lineextent naar OOL-segmentwacht tot weggeschrevenjournal recorddelta'sack2 tripsFlashStoredata, nieuwe 4 KiBWAL-unit, data-crcack1 triptijd
SeaStore op zijn standaard gesegmenteerde device: één trip als de extent in het journal record past, twee na elkaar als hij out-of-line gaat. FlashStore: data en logrecord samen.

Hoeveel dat uitmaakt hangt van je workload af, precies zoals in de vergelijking met BlueStore. Bij een lage queue depth, waar clients op elke write wachten, is een tweede trip echte latency. Onder belasting verbergt batching het meeste daarvan.

Ruimte Terugkrijgen

De andere helft van een log-structured ontwerp is het opruimen.

SeaStore op de gesegmenteerde backend schrijft alleen ooit naar open segmenten. Voordat een segment hergebruikt kan worden, moeten de levende blokken erin ergens anders herschreven worden, en het designdocument zegt wat dat kost: “we must ‘clean’ one byte of an existing segment for every byte written at steady state”27. Het mengt een deel van dat opruimen door de lopende writes, om pieken te vermijden, en doet de rest op de achtergrond als de schijf rustiger is27. De segmentgrootte is standaard 64 MiB31.

SeaStore heeft wel een tweede backend voor NVMe, de random block manager, waarvan de docs zeggen dat hij “Preferred for fast NVMe devices where overwrites are efficient enough that log structured updates aren’t worth the overhead” is27. Het is niet de standaard. Je kiest hem met seastore_main_device_type30.

FlashStore heeft geen segment cleaner. Geen. Een vervangen blok gaat terug naar de allocator van de shard zodra een checkpoint er voorbij is, wat elke vijf seconden gebeurt zolang er werk is dat nog niet weggeschreven is, of eerder als de WAL-ring halfvol is28. Het designdocument wees een log-structured indeling ronduit af28. Dat betekent niet dat er geen achtergrondwerk is: het voegt nog steeds boompagina’s samen en compacteert ze, en defragmenteert vrije ruimte, getemperd onder client-I/O28. Maar het kopieert nooit je levende data om ruimte te maken.

Ruimte terugkrijgenSeaStore, gesegmenteerd (standaard)gesloten segmentlevende + dode blokkencleaner herschrijft levendnaar een open segmentsegment leegdiscard, hergebruiksteady state: ongeveer één byte opruimen per geschreven byteFlashStoreblok vervangendoor een nieuwe extentvast tot checkpointelke 5 s of WAL halfvolterug in de bitmapgeen levende data verplaatst
De standaard-backend van SeaStore betaalt voor sequentiële writes met een cleaner die levende data verplaatst. FlashStore geeft vervangen blokken ter plekke vrij na een checkpoint en verplaatst niks.

Op flash, dat binnen de schijf al zijn eigen garbage collection draait, heb ik liever dat de OSD er niet nog een tweede bovenop draait. De eigen docs van SeaStore lijken het daarmee eens, gezien wat ze over de RBM-backend zeggen. Het verschil is dat FlashStore dat de enige optie maakte, en SeaStore het de niet-standaardoptie maakte.

Waar Elk Op Draait

Crimson (Umbrella)FlashStore
HDDja, met BlueStore; SeaStore heeft een HDD-segmenttypenee
NVMejaja, het enige doel
Power-loss protectiongeen eis genoemdvereist, mkfs weigert zonder
Device-indelingLVM voor SeaStore via cephadmhele namespaces, geen partities
Wire protocolalleen msgr2alleen msgr2
I/O-backendio_uring standaard; linux-aio, epollSPDK standaard, io_uring-tier
Poolsnieuwe pools met de crimson-vlagbestaande klassieke pools
Bestaande data verhuizenkopiëren naar een nieuwe poolbackfill in dezelfde pool
Uitgerold metcephadm, --osd-type crimsonpakketten, croit-flashstore-tool
Aanbevolen buildnieuwste CI-build van mainrelease-snapshots

Crimson houdt de breedte. De docs zeggen dat SeaStore “may not be suitable for traditional HDDs”, maar dat “Crimson will continue to support BlueStore ensuring compatibility with HDDs and slower SSDs”1, en het designdocument van SeaStore noemt nog steeds interesse in HDD’s27. De messenger weigert v1 ronduit, “ProtocolV1 is no longer supported”32, dezelfde keuze die FlashStore maakte33. De docs raden “one of the latest available builds, as Crimson evolves rapidly” aan, wat in de praktijk CI-images van main betekent1.

FlashStore versmalt alles tot NVMe met power-loss protection, en haalt daar zijn eenvoud uit34. Wat precies de afweging is die de ADR van croit beschrijft, van de andere kant bekeken.

Twee Antwoorden Op Dezelfde Vraag

Beide projecten begonnen bij dezelfde waarneming: de klassieke OSD verspilt snelle hardware. Ze gaven heel verschillende antwoorden.

Het antwoord van Crimson is dat van de community. Herschrijf de OSD ter plekke, binnen Ceph, houd elke oude store en elke oude schijf werkend terwijl de nieuwe store volwassen wordt, en laat iedereen het werk zien terwijl het gebeurt. Dat gaat langzaam, en dat zie je. In Umbrella draait de standaard Crimson-OSD nog steeds BlueStore via een threadpool, zijn eigen pools zijn van de jouwe afgeschermd, en hem aanzetten betekent de woorden “unrecoverable data corrupting” intikken. Maar het is van iedereen die Ceph draait, en niemand kan het je afpakken.

Het antwoord van FlashStore is dat van de leverancier. Kies een smaller doel, NVMe met power-loss protection, gooi alles eruit wat alleen voor andere hardware bestond, en lever een store die instapt in de pools die je al hebt. Dat gaat sneller, en dat zie je ook. Maar het komt van één bedrijf, als read-only snapshots tot de eerste productierelease, en op een standaardcluster komt het binnen door de monitor te vertellen dat het BlueStore is.

Ik werk voor dat bedrijf, dus weeg wat volgt daarnaar. croit heeft de juiste technische gok gedaan voor all-flash-clusters. Crimson heeft de juiste gok gedaan voor Ceph als project. Dat is niet hetzelfde. Een project dat iedereen bedient kan HDD’s niet laten vallen. Een leverancier kan dat wel, en hoort dat te doen als dat is wat zijn klanten kopen.

Wat ik niet zou doen, is tussen de twee kiezen op basis van een benchmarkgrafiek van welke kant dan ook. De cijfers van Crimson hangen ervan af welke van zijn drie stores er draaide; die van FlashStore komen uit croits eigen lab. Beide projecten publiceren hun designdocumenten. Lees ze, zet dan allebei op de schijven die je echt zou uitrollen en draai je eigen workload. Degene die nog steeds doet wat zijn documenten zeggen als het jouw data is die op het spel staat, is degene waarop het wachten waard is.


  1. Ceph Umbrella, Crimson (Tech Preview) — “the next generation ceph-osd”, “not suitable for production use”, de vereiste vlaggen, crimson_cpu_num, native en niet-native backends, SeaStore “not the default”, --method raw niet ondersteund. Bron: doc/crimson/crimson.rst op v21.2.0. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  2. croit ceph-rust, README at snapshot 48f9014 — drop-in-claim, preview sinds 9 november 2026, GA Q1 2027, “not yet recommended for production data”, “no issue tracker, no contribution workflow”. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  3. Seastar — het C++-framework waarop Crimson gebouwd is. ↩︎ ↩︎

  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 afgewezen vanwege “C++, complexity, LGPL”. ↩︎ ↩︎ ↩︎

  5. ceph-rust ADR 0164, licences — gedateerd 2026-10-17; daemon 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) — nieuwe productlijnen voor kritieke infrastructuur “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 en 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)”, standaard true. ↩︎

  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 — legacy en geoptimaliseerde EC standaard bediend; niet-ondersteunde pools door de OSD afgeslagen. ↩︎

  15. Ceph v21.2.0, MonCommands.h, osd pool create — name=crimson,type=CephBool,req=false, de enige plek waar de vlag geaccepteerd wordt. ↩︎

  16. Ceph v21.2.0, MonCommands.h, osd pool set — de instelbare variabelen; crimson zit er niet tussen. ↩︎

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

  18. ceph-rust docs, migrate from classic — een schijf toevoegen of vrijmaken, FlashStore prepareren, backfill de data laten verhuizen. ↩︎

  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 — geen osd_type-key, de BlueStore-feature-gates van de monitor. ↩︎ ↩︎ ↩︎

  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” standaard false, crimson_bluestore_num_threads. ↩︎ ↩︎

  23. Ceph v21.2.0, seastore_require_partition_count_match_reactor_count — “disable osd shards changes upon restart”, standaard true. ↩︎

  24. ceph-rust ADR 0006, thread-per-core runtime — één vastgepinde busy-pollende thread per core, PG’s eigendom van één core. ↩︎

  25. ceph-rust ADR 0004, storage I/O — SPDK en de io_uring-tier, idle getimed op het device. ↩︎

  26. ceph-rust docs, configuration reference — flashstore_cores standaard 8, flashstore_lcores, flashstore_store_shards vast bij prepare. ↩︎

  27. Ceph Umbrella, SeaStore developer documentation — root per reactor, onode-, OMAP-, LBA- en backref-bomen, “clean” één byte per geschreven byte, de volgorde van het journal record, de RBM-backend. Bron: doc/dev/crimson/seastore.rst op v21.2.0. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  28. ceph-rust ADR 0021, storage engine — één COW-B+tree per shard, parallelle commit, checkpoints, achtergrondonderhoud, afgewezen alternatieven waaronder log-structured en “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)”, standaard SSD. ↩︎ ↩︎

  31. Ceph v21.2.0, seastore_segment_size — standaard 64 MiB. ↩︎

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

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

  34. ceph-rust docs, hardware and host requirements — PLP vereist, hele namespaces. ↩︎