Offenlegung vorweg: Ich arbeite für croit, die FlashStore geschrieben haben. Alles unten ist aus Cephs Quellcode und Dokumentation bei v21.2.0 und aus croits veröffentlichtem ceph-rust-Snapshot gelesen, alles verlinkt am Ende der Seite. Wo croits eigene Begründung auf einer Seite eines Arguments steht, sage ich, wessen Begründung es ist.
Zwei Neuschreibungen desselben Daemons
Das klassische Ceph-OSD ist ein Thread-Server in C++, der auf drehenden Platten groß geworden ist. Auf schnellem NVMe und schnellen Netzen verbringt es viel seiner CPU mit Dingen, die nicht deine Daten speichern: Operationen zwischen Thread-Pools weiterreichen, Locks nehmen, auf andere Threads warten. Zwei Projekte haben sich vorgenommen, das zu beheben, indem sie das OSD komplett neu schreiben.
Das eine ist Crimson, Cephs eigenes.
Umbrellas Dokumentation nennt es „the next generation ceph-osd“, gebaut „to deliver enhanced performance on fast network and storage devices“1.
Das andere ist croits FlashStore-OSD aus dem Projekt ceph-rust, seit 9. November 2026 in Public Preview2.
Beide sagen, sie seien Drop-in-Ersatz. Beide sagen, sie seien für NVMe. Beide sind in der Preview, und keins von beiden sollte heute Produktivdaten halten. Wenn du also NVMe-Ceph betreibst und überlegst, welches du im Auge behalten solltest, lohnt es sich zu wissen, wo sie sich wirklich unterscheiden, denn das ist nicht da, wo die Schlagzeilen es vermuten lassen.
Hier stehen sie so nebeneinander, wie du sie auf Ceph 21.2.0, Umbrella, vorfindest: Crimson, wie dieses Release es dokumentiert und ausliefert, gegen FlashStore, das gegen genau dieses Release gebaut und getestet wird2. Es schließt an FlashStore gegen Umbrella-BlueStore an, und was dort über FlashStore schon steht, setze ich voraus.
Woher jedes kommt
Der erste Unterschied ist, wer es baut und wie.
| Crimson | FlashStore | |
|---|---|---|
| Gebaut von | Ceph upstream, im Hauptbaum | croit |
| Sprache | C++ | Rust |
| Framework | Seastar | croits eigener Single-Thread-Executor |
| Code | in ceph/ceph | Clean-Room-Neuschreibung, kein Ceph-Code gelinkt |
| Entwicklung | upstream, offen | schreibgeschützte Snapshots in der Preview; offen nach dem ersten Produktiv-Release |
| Lizenz | die von Ceph | Daemon LGPL-3.0, Clients MPL-2.0 |
| Status in eigenen Worten | „not suitable for production use“ | „not yet recommended for production data“ |
| Geplante GA | keine genannt | Q1 2027 |
Crimson lebt in Cephs eigenem Repository und wird von Cephs eigenen Entwicklern gebaut. Es ist auf Seastar geschrieben, einem C++-Framework für Thread-per-Core-Server, das von ScyllaDB stammt3. Die Umbrella-Doku sagt klar, dass es „is in a tech-preview stage and is not suitable for production use“1.
FlashStore ist von Grund auf in Rust geschrieben und linkt überhaupt keinen Ceph-Code; Cephs C++ wird als Referenz gelesen und nach croits eigenen Spezifikationen neu implementiert4. Seine README sagt, es sei für Tests und Evaluierung und „not yet recommended for production data“, die allgemeine Verfügbarkeit ist für das erste Quartal 2027 geplant2. Das öffentliche Repository ist ein schreibgeschützter Snapshot: „no issue tracker, no contribution workflow“2.
Diese Zeile solltest du genau lesen. Crimson wird offen entwickelt, und jeder kann die Pull Requests lesen und darüber streiten. FlashStore kommt vorerst als fertige Snapshots von einer Firma: Du kannst jede Zeile lesen, aber noch keinen Patch schicken. Das ist die Preview-Phase, nicht der Plan. Die Preview ist dazu da, Feedback aus der Community zu sammeln, während croit intern seine Produktions-Testfälle durchläuft, bevor es das OSD als sicher für den Einsatz freigibt. Nach diesem ersten Produktiv-Release wird die Entwicklung offen, der Weg, den die meisten von Firmen getragenen Open-Source-Projekte gehen. Das kommt aus croit selbst und nicht aus einer veröffentlichten Roadmap, also nimm sie beim Wort.
croit hat sich tatsächlich einen Fork von Crimson angeschaut und aufgeschrieben, warum es keinen gemacht hat. Sein ADR sagt, Crimson „tries to support everything (HDD, alienstore/BlueStore, all pool types)“, und fügt hinzu: „Complex code is never fast“4. Das ist croits Meinung über Crimson, keine Messung, und so würde ich sie auch behandeln. Dasselbe ADR hat einen Fork auch wegen der LGPL abgelehnt4, und acht Tage später hat croit seinen eigenen Daemon unter LGPL-3.0 gestellt5. Die Lizenz war also nie wirklich der Grund.
Speichersicherheit: Rust gegen C++
Ein OSD ist der Code, der deine Daten hält. Ein Use-after-free oder ein Pufferüberlauf darin ist kein Absturz, nach dem du neu startest; es sind kaputte Daten auf der Platte, kopiert auf jedes Replikat. Genau diese Klasse von Fehlern sollen Hersteller nach dem Willen der westlichen Cyber-Behörden seit drei Jahren per Design ausschließen.
| Leitlinie | Wer sie unterzeichnet hat | Was sie sagt |
|---|---|---|
| The Case for Memory Safe Roadmaps, Dezember 2023 | CISA, NSA und FBI (USA), ASD’s ACSC (Australien), CCCS (Kanada), NCSC-UK, NCSC-NZ, CERT-NZ | C und C++ sind speicherunsicher; veröffentlicht eine Roadmap weg von ihnen |
| Product Security Bad Practices v2.0, Januar 2025 | CISA und FBI | neue Produktlinien für kritische Infrastruktur in C oder C++ sind „dangerous“, wo speichersichere Sprachen verfügbar sind |
Die gemeinsame Leitlinie sagt es klar: „Programming languages such as C and C++ are examples of memory unsafe programming languages“6. CISA und FBI gehen weiter und nennen „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++)“ gefährlich, wenn eine speichersichere Alternative verwendet werden könnte7. Das ist eine Leitlinie, kein Gesetz. Aber Storage unter kritischen Diensten ist genau der Code, auf den sie zielt, und beide hier sind OSDs der nächsten Generation, die daran gemessen werden.
FlashStore erfüllt sie.
Es ist in Rust geschrieben, und croits ADR gibt den Grund in einer Zeile: „Storage = correctness-critical; memory-safety bugs = data loss“8.
Der Compiler prüft die Speichersicherheit überall außer in Code, der als unsafe markiert ist, und dasselbe ADR beschränkt den auf die Module für FFI, DMA, NVMe und Netzwerktreiber, jeweils mit einem SAFETY-Kommentar8.
Ich habe im Snapshot nachgezählt: 1.216 Zeilen, die unsafe erwähnen, von 696.125 Zeilen Rust, etwa 0,17 %, und sie sitzen in den Crates für RDMA, Runtime, NVMe und Store, wo der Code mit der Hardware spricht.
Die gemeinsame Leitlinie nennt diese Hintertür selbst und merkt an, dass Rust „can contain the ‘unsafe’ keyword“6, also ist das das ehrliche Maß: nicht null, aber klein, abgezäunt und an den Stellen, an denen du es erwarten würdest.
Das C, das es aufruft, SPDK und DPDK, sitzt hinter denselben Grenzen8.
Crimson erfüllt sie nicht. Es ist ein neues OSD, in C++ auf einem C++-Framework geschrieben13, also in der Sprache, die die Behörden oben als speicherunsicher benennen. Jede Zeile davon liegt außerhalb dessen, was ein Compiler auf Speichersicherheit prüfen kann, und in seiner Standardkonfiguration übergibt es den Store an BlueStore, das ebenfalls C++ ist.
| Crimson | FlashStore | |
|---|---|---|
| Sprache | C++ | Rust |
| Speichersicherheit vom Compiler geprüft | nein | ja, außerhalb von unsafe |
| Ungeprüfter Code | alles | etwa 0,17 % der Zeilen, Treiber- und FFI-Code |
| Standard-Store | BlueStore, C++ | FlashStore, Rust |
| Passt zu den Five-Eyes-Leitlinien zur Speichersicherheit | nein | ja |
Cephs Entwickler haben C++ nicht leichtfertig gewählt; Crimson ist aus einer C++-Codebasis gewachsen, und an Ort und Stelle neu zu schreiben hieß, darin zu bleiben. Das ist ein vernünftiger technischer Weg. Es bleibt trotzdem dabei, dass das Ceph-OSD der nächsten Generation in genau der Art von Sprache geschrieben ist, die neuer kritischer Code nach dem Wunsch der Behörden von fünf Ländern hinter sich lassen soll.
Wie jedes einem Cluster beitritt
Das ist der größte praktische Unterschied zwischen beiden, und mit Performance hat er überhaupt nichts zu tun.
Ein FlashStore-OSD tritt den Pools bei, die du schon hast. Es sitzt in denselben Placement Groups neben klassischen BlueStore-OSDs, und du tauschst ein Laufwerk nach dem anderen2.
Ein Crimson-OSD tut das nicht.
Nicht mal annähernd.
Umbrellas Doku sagt: „Crimson OSD won’t instantiate PGs from non-Crimson pools“1.
Der Code macht genau das. Wenn der Monitor ein Crimson-OSD bittet, eine PG in einem Pool ohne das crimson-Flag anzulegen, loggt es „pool lacks crimson flag“ und bricht das Anlegen ab9.
Ein Crimson-Test heißt also neue Pools, mit dem crimson-Flag angelegt, und deine Daten dorthin umgezogen.
Und diese Pools kommen mit Bedingungen, die der Monitor durchsetzt:
| Regel für Crimson-Pools (Umbrella) | Wo |
|---|---|
| PG-Autoscaling muss beim Anlegen des Pools aus sein | OSDMonitor, Pool-Anlage10 |
PG-Merging (pg_num verkleinern) abgelehnt | OSDMonitor, pg_num-Änderung11 |
PG-Splitting nur erlaubt, solange crimson_allow_pg_split true ist | dort, und die Option12 |
| EC-Pools müssen vom optimierten EC-Typ sein, ohne Ausnahme | OSDMonitor, Pool-Anlage13 |
| Kein OMAP auf EC-Pools | dort13 |
FlashStore bedient klassische Pools, replizierte wie erasure-codierte, und lehnt die EC-Konfigurationen, die es nicht unterstützt, selbst ab, statt dass der Monitor sie verweigert14. Keiner der beiden Ansätze ist falsch. Aber mit dem einen testest du auf einer Kopie deines echten Pool-Layouts, und der andere lässt dich erst ein separates bauen.
Kein Weg hinüber für die Pools, die du schon hast
Kannst du also einen bestehenden Pool in einen Crimson-Pool verwandeln und ihn Laufwerk für Laufwerk umziehen? Nein.
Umbrellas Doku sagt, Crimson sei „aiming to allow seamless migration from existing ceph-osd deployments“1.
Aiming. Das Release kann es nicht, und der Quellcode zeigt, warum es nicht geht.
Das crimson-Flag ist eine Option von ceph osd pool create und sonst nirgends15.
ceph osd pool set hat keine crimson-Variable, die du auf einem schon bestehenden Pool setzen könntest16.
Und ein Crimson-OSD ignoriert, wie oben, jede PG in einem Pool ohne das Flag9.
Ein Umwandlungswerkzeug habe ich weder im Quellcode noch in der Doku gefunden.
| Einen bestehenden Pool umziehen | Crimson (Umbrella) | FlashStore, heute |
|---|---|---|
| Derselbe Pool bleibt | nein, ein neuer Pool ist Pflicht | ja |
| Pool später flaggen | nein, nur beim Anlegen | nicht nötig |
| Wie die Daten wandern | du kopierst sie, Pool zu Pool | der Cluster macht Backfill |
| Clients umstellen | ja, auf den neuen Pool | nein |
| Ein Laufwerk nach dem anderen | nein | ja |
Ein Umzug zu Crimson ist damit eine Datenkopie, die du selbst fährst: RBD-Images lassen sich live „between different pools“ migrieren17, und Objekt- oder Dateidaten brauchen das, womit deine Anwendungen sie eben kopieren. Danach muss jeder Client auf den neuen Pool zeigen.
FlashStore ist mit den Pools kompatibel, die du heute fährst. Du bereitest es auf einem Laufwerk vor, der Cluster füllt per Backfill die Placement Groups auf, die es zugeteilt bekommt, und deine Clients merken nie, dass sich der Pool unter ihnen geändert hat, weil er das nicht hat18. Das ist der ganze Unterschied zwischen einer Neuschreibung, die deinem Cluster beitritt, und einer, die daneben sitzt.
Was jedes dem Monitor meldet
Crimson meldet sich an.
Beim Booten schickt es osd_type=crimson19, und der Monitor lässt es nicht rein, solange das OSDMap-Flag allow_crimson nicht gesetzt ist, mit einer Logzeile, die sagt, crimson-osd „is considered unstable and may result in crashes or data loss“20.
Bis dahin brauchst du laut Doku vier Befehle, und der erste setzt eine Option namens enable_experimental_unrecoverable_data_corrupting_features1.
FlashStore macht das Gegenteil.
Es schickt überhaupt kein osd_type und meldet osd_objectstore=bluestore, also sieht der Monitor ein klassisches OSD und stellt keine Fragen21.
Der vorige Post erklärt, warum: Umbrellas Monitor macht Features wie EC-Overwrites davon abhängig, dass jedes OSD in einem Pool BlueStore meldet21.
Das gilt für die Standard-Monitore und -Manager, die heute in Produktion laufen.
Auf croits eigenen Ceph-Builds, wo sie so gepatcht sind, dass sie es kennen, meldet sich FlashStore als flashstore21.
Mir ist lieber, wenn Software mir sagt, was sie ist. Crimson tut das. Sein Weg ist der ehrliche, und der Name des Flags lässt keinen Zweifel daran, worauf du dich einlässt. FlashStores Weg ist das, womit Drop-in auf den Standard-Monitoren und -Managern funktioniert, die die Leute heute fahren, und er ist eine Kompatibilitätsmaßnahme, nicht der Endzustand. Beides ist Absicht, und beides ist aufgeschrieben. Du solltest nur wissen, mit welchem du es zu tun hast, wenn du deine OSDs zählst.
Kerne: Reaktoren gegen gepinnte pollende Threads
Beide Projekte haben die Thread-Pools rausgeworfen. Gut so. Beide fahren einen Thread pro Kern und verteilen ihre Arbeit nach Kern. Der Unterschied liegt darin, wie viel sie vom Betreiber verlangen und wie fest sie den Kern halten.
| Crimson | FlashStore | |
|---|---|---|
| Arbeitseinheit | Seastar-Reaktor pro Kern | gepinnter Thread pro Kern |
| Anzahl Kerne | crimson_cpu_num, kein Standard, muss gesetzt werden | flashstore_cores, Standard 8 |
| Auf Kerne gepinnt | nur mit crimson_cpu_set | ja, flashstore_lcores |
| Verhalten im Leerlauf | pollt 200 µs, schläft dann | pollt, adaptiver Leerlauf |
| Volles Busy-Polling | optional, crimson_poll_mode | das Design, mit Leerlauf-Backoff |
| Änderung nach dem Deployment | nein | Store-Shards beim Prepare festgelegt |
Für Crimsons crimson_cpu_num gilt: Es „does not have a default value“, muss vor dem Deployment der OSDs gesetzt werden und „cannot be changed after deployment“1.
Es pinnt keine Threads, solange du nicht auch crimson_cpu_set setzt, was die Doku als „generally less recommended due to its complexity“ beschreibt1.
Der Reaktor pollt im Leerlauf 200 µs, bevor er wieder schlafen geht, und einen vollen Poll-Modus gibt es „at the expense of 100% cpu usage“, standardmäßig aus22.
SeaStore verweigert außerdem nach mkfs eine Änderung der Reaktorzahl23.
FlashStore pinnt per Design, pollt per Design und fährt im Leerlauf zurück2425. Seine Zahl der Store-Shards wird beim Prepare des Stores festgelegt, dieselbe Einschränkung an einer anderen Stelle26.
In der Praxis wollen beide ganze Kerne, und beide wollen, dass du sie vor dem Deployment dimensionierst. Crimson macht das Polling zu einer Wahl, für die du dich entscheidest. FlashStore macht es zum Standard und lässt die Leerlauf-Logik einen Teil der CPU zurückholen.
Crimsons Standard-Store ist BlueStore
Das ist der Teil, der mich überrascht hat. Hätte er nicht sollen.
Crimson hat zwei Arten von Object Store. Native laufen im Seastar-Reaktor; nicht-native laufen über „a thread pool proxy“ zu „alien threads: worker threads not managed by Seastar“1. SeaStore ist der native. BlueStore ist nicht-nativ. Und BlueStore ist der Standard.
Die Doku sagt das unverblümt.
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 deployt Crimson mit --objectstore bluestore, solange man nichts anderes sagt, und selbst dann lässt sich SeaStore nicht mit --method raw deployen; du sollst LVM nehmen1.
Ein Crimson-OSD, das heute mit Standardeinstellungen deployt wird, fährt also ein Seastar-Frontend auf demselben BlueStore, RocksDB und BlueFS, die das klassische OSD nutzt, mit crimson_bluestore_num_threads Threads, die dafür abgestellt sind22.
Auf der Store-Seite hat sich gegenüber dem klassischen OSD rein gar nix geändert.
Als Migrationspfad ist das vernünftig gebaut. Es ist auch der Grund, warum ein Performance-Vergleich von „Crimson“ gegen FlashStore sehr wenig heißt, solange du nicht sagst, welchen Store Crimson gefahren hat.
Der faire Vergleich für den Store ist SeaStore gegen FlashStore. Darum geht es im Rest dieses Posts.
SeaStore und FlashStore: Wo die Metadaten liegen
Beide Stores wurden von Anfang an für NVMe geschrieben, beide sind nach Kern geshardet, und beide halten ihre Metadaten in eigenen B-Bäumen statt in RocksDB. Ihre Layouts sind trotzdem sehr verschieden.
SeaStore gibt jedem Reaktor seine eigene Wurzel27. Darunter sitzen ein Onode-Baum, ein LBA-Baum und ein Backref-Baum. Der Onode jedes Objekts zeigt dann auf seinen eigenen OMAP-B-Baum und seinen eigenen XATTR-B-Baum, und auf Daten-Extents mit logischen Adressen27. Der LBA-Baum bildet diese logischen Adressen auf physische ab, sodass ein Block auf der Platte wandern kann, ohne dass sich die Bäume des Objekts ändern; die Doku nennt diese Indirektion den Grund, warum die meisten Extents „can be relocated freely“27.
FlashStore legt alles in einen Copy-on-Write-B+-Baum pro Shard: Onodes, Xattrs, OMAP, Extent-Maps mit einem crc32c pro 4-KiB-Block, das PG-Log und die Bitmap des Allocators28. Extent-Maps zeigen direkt auf physische Blöcke. Dazwischen gibt es keine logische Schicht.
Beide Entscheidungen haben einen Grund. SeaStores Indirektion macht seinen Cleaner billig: Er kann lebende Daten verschieben, ohne jeden Baum neu zu schreiben, der auf sie zeigt. FlashStore braucht das nicht, weil es keinen Cleaner hat, wie unten beschrieben. Sein ADR führt „Per-object omap subtree/root“ unter den Alternativen auf, die es erwogen und verworfen hat28.
Ein Unterschied bei den Prüfsummen, den du kennen solltest: SeaStore berechnet sein crc32c über einen ganzen gecachten Extent29, FlashStore hält eins pro 4-KiB-Block28.
Die Reihenfolge, in der ein Write committet
SeaStores Standard-Gerätetyp ist SSD, und der nutzt das segmentierte Backend30.
Auf diesem Backend ist eine Transaktion ein Journal-Eintrag mit Deltas, und mit den Daten kann eins von zwei Dingen passieren.
Kleine, kurzlebige Extents können inline im Journal-Eintrag mitfahren, und dann ist der Eintrag der ganze Commit27. Größere oder langlebigere Extents gehen in separate Out-of-Line-Segmente, und dann legt die Doku die Reihenfolge fest: Der „final record with the deltas should be written only once the other blocks are persisted“27. Das sind zwei Writes hintereinander, dieselbe Form wie BlueStores Commit erst der Daten, dann RocksDB.
FlashStore schreibt den Daten-Extent und die WAL-Einheit gleichzeitig, legt das crc32c der neuen Daten in den WAL-Eintrag, damit das Replay es prüfen kann, und bestätigt, wenn beides dauerhaft gespeichert ist28. Ein Weg zum Gerät, egal wie groß.
Wie viel das ausmacht, hängt von deiner Last ab, genau wie im BlueStore-Vergleich. Bei niedriger Queue-Tiefe, wo Clients auf jeden Write warten, ist ein zweiter Weg echte Latenz. Unter Last versteckt das Bündeln das meiste davon.
Platz zurückbekommen
Die andere Hälfte eines Log-Structured-Designs ist das Aufräumen.
SeaStore auf dem segmentierten Backend schreibt nur in offene Segmente. Bevor ein Segment wiederverwendet werden kann, müssen seine lebenden Blöcke woanders neu geschrieben werden, und das Design-Dokument sagt, was das kostet: „we must ‘clean’ one byte of an existing segment for every byte written at steady state“27. Einen Teil dieses Aufräumens mischt es in die laufenden Writes, um Spitzen zu vermeiden, den Rest erledigt es im Hintergrund, wenn das Laufwerk ruhiger ist27. Die Segmentgröße steht standardmäßig auf 64 MiB31.
SeaStore hat zwar ein zweites Backend für NVMe, den Random Block Manager, laut Doku „Preferred for fast NVMe devices where overwrites are efficient enough that log structured updates aren’t worth the overhead“27.
Es ist nicht der Standard. Du wählst es mit seastore_main_device_type30.
FlashStore hat keinen Segment-Cleaner. Keinen. Ein ersetzter Block geht an den Allocator des Shards zurück, sobald ein Checkpoint ihn hinter sich gelassen hat, und das passiert alle fünf Sekunden, solange etwas nicht persistiert ist, oder früher, wenn der WAL-Ring halb voll ist28. Sein Design-Dokument hat ein Log-Structured-Layout rundweg abgelehnt28. Das heißt nicht, dass es keine Hintergrundarbeit hat: Es führt weiterhin Baumseiten zusammen, kompaktiert sie und defragmentiert freien Platz, getaktet unter der Client-I/O28. Aber es kopiert nie deine lebenden Daten, um Platz zu schaffen.
Auf Flash, das in seinem Inneren schon seine eigene Garbage Collection fährt, wäre mir lieber, das OSD fährt nicht noch eine zweite obendrauf. SeaStores eigene Doku scheint das ähnlich zu sehen, nach dem, was sie über das RBM-Backend sagt. Der Unterschied ist, dass FlashStore das zur einzigen Option gemacht hat und SeaStore zur Nicht-Standard-Option.
Worauf jedes läuft
| Crimson (Umbrella) | FlashStore | |
|---|---|---|
| HDD | ja, mit BlueStore; SeaStore hat einen HDD-Segmenttyp | nein |
| NVMe | ja | ja, das einzige Ziel |
| Power-Loss-Protection | keine genannte Anforderung | Pflicht, mkfs verweigert ohne |
| Geräte-Layout | LVM für SeaStore über cephadm | ganze Namespaces, keine Partitionen |
| Wire-Protokoll | nur msgr2 | nur msgr2 |
| I/O-Backend | Standard io_uring; linux-aio, epoll | Standard SPDK, io_uring-Stufe |
| Pools | neue Pools mit dem crimson-Flag | bestehende klassische Pools |
| Bestehende Daten umziehen | in einen neuen Pool kopieren | Backfill in denselben Pool |
| Deployt mit | cephadm, --osd-type crimson | Paketen, croit-flashstore-tool |
| Empfohlener Build | neuester CI-Build von main | Release-Snapshots |
Crimson behält die Breite.
Die Doku sagt, SeaStore „may not be suitable for traditional HDDs“, aber „Crimson will continue to support BlueStore ensuring compatibility with HDDs and slower SSDs“1, und SeaStores Design-Dokument führt noch immer ein Interesse an HDDs auf27.
Sein Messenger lehnt v1 rundweg ab, „ProtocolV1 is no longer supported“32, dieselbe Entscheidung, die FlashStore getroffen hat33.
Seine Doku empfiehlt „one of the latest available builds, as Crimson evolves rapidly“, was in der Praxis CI-Images von main heißt1.
FlashStore verengt alles auf NVMe mit Power-Loss-Protection und holt seine Einfachheit genau daraus34. Was genau der Tausch ist, den croits ADR beschreibt, nur von der anderen Seite.
Zwei Antworten auf dieselbe Frage
Beide Projekte sind von derselben Beobachtung ausgegangen: Das klassische OSD verschwendet schnelle Hardware. Sie haben sehr verschiedene Antworten gegeben.
Crimsons Antwort ist die der Community. Das OSD an Ort und Stelle neu schreiben, in Ceph, jeden alten Store und jedes alte Laufwerk am Laufen halten, während der neue Store reift, und jeden die Arbeit sehen lassen, während sie passiert. Das ist langsam, und das merkt man. In Umbrella fährt das Crimson-OSD mit Standardeinstellungen noch BlueStore über einen Thread-Pool, seine eigenen Pools sind von deinen abgezäunt, und um es einzuschalten, tippst du die Worte „unrecoverable data corrupting“. Aber es gehört jedem, der Ceph betreibt, und niemand kann es dir wegnehmen.
FlashStores Antwort ist die eines Herstellers. Ein engeres Ziel wählen, NVMe mit Power-Loss-Protection, alles rauswerfen, was es nur für andere Hardware gab, und einen Store ausliefern, der in die Pools einsteigt, die du schon hast. Das ist schneller, und das merkt man auch. Aber es kommt von einer Firma, bis zum ersten Produktiv-Release als schreibgeschützte Snapshots, und auf einem Standard-Cluster kommt es hinein, indem es dem Monitor erzählt, es sei BlueStore.
Ich arbeite für diese Firma, also gewichte das Folgende entsprechend. croit hat für All-Flash-Cluster die richtige technische Wette gemacht. Crimson hat die richtige Wette für Ceph als Projekt gemacht. Das ist nicht dasselbe. Ein Projekt, das allen dient, kann HDDs nicht fallen lassen. Ein Hersteller kann das, und sollte es auch, wenn es das ist, was seine Kunden kaufen.
Was ich nicht tun würde: zwischen beiden anhand eines Benchmark-Diagramms von irgendeiner Seite wählen. Crimsons Zahlen hängen davon ab, welcher seiner drei Stores lief; FlashStores kommen aus croits eigenem Labor. Beide Projekte veröffentlichen ihre Design-Dokumente. Lies sie, stell dann beide auf die Laufwerke, die du tatsächlich einsetzen würdest, und fahr deine eigene Last. Das, was immer noch tut, was seine Dokumente sagen, wenn es um deine Daten geht, ist das, auf das sich das Warten lohnt.
Ceph Umbrella, Crimson (Tech Preview) — „the next generation
ceph-osd“, „not suitable for production use“, die nötigen Flags,crimson_cpu_num, native und nicht-native Backends, SeaStore „not the default“,--method rawnicht unterstützt. Quelle:doc/crimson/crimson.rstat v21.2.0. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎croit ceph-rust, README at snapshot 48f9014 — Drop-in-Behauptung, Preview seit 9. November 2026, GA Q1 2027, „not yet recommended for production data“, „no issue tracker, no contribution workflow“. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Seastar — das C++-Framework, auf dem Crimson gebaut ist. ↩︎ ↩︎
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 abgelehnt wegen „C++, complexity, LGPL“. ↩︎ ↩︎ ↩︎
ceph-rust ADR 0164, licences — datiert 2026-10-17; Daemon
LGPL-3.0-only. ↩︎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“. ↩︎ ↩︎
CISA and FBI: Product Security Bad Practices, v2.0 (January 2025) — neue Produktlinien für kritische Infrastruktur „in a memory-unsafe language (e.g., C or C++) where readily available alternative memory-safe languages could be used is dangerous“. ↩︎
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 und DPDK über FFI. ↩︎ ↩︎ ↩︎Ceph v21.2.0,
crimson/osd/shard_services.cc— „ignoring pgid {}, pool lacks crimson flag“. ↩︎ ↩︎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’“. ↩︎Ceph v21.2.0,
OSDMonitor.cc, crimsonpg_numchanges — „pg merging is not yet supported in Crimson“. ↩︎Ceph v21.2.0,
crimson_allow_pg_split— „Allow Crimson pools to increase their PG count (split)“, Standard true. ↩︎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“. ↩︎ ↩︎ceph-rust docs, erasure-coded pools — Legacy- und optimiertes EC standardmäßig bedient; nicht unterstützte Pools vom OSD abgelehnt. ↩︎
Ceph v21.2.0,
MonCommands.h,osd pool create—name=crimson,type=CephBool,req=false, die einzige Stelle, an der das Flag angenommen wird. ↩︎Ceph v21.2.0,
MonCommands.h,osd pool set— die setzbaren Variablen;crimsonist nicht darunter. ↩︎Ceph Umbrella, RBD image live-migration — „RBD images can be live-migrated between different pools“. ↩︎
ceph-rust docs, migrate from classic — Laufwerk hinzufügen oder freimachen, FlashStore vorbereiten, Backfill die Daten bewegen lassen. ↩︎
Ceph v21.2.0,
crimson/osd/osd.cc—m->metadata["osd_type"] = "crimson". ↩︎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“. ↩︎ceph-rust ADR 0019, report
osd_objectstore=bluestore— keinosd_type-Key, die BlueStore-Feature-Gates des Monitors. ↩︎ ↩︎ ↩︎Ceph v21.2.0,
crimson.yaml.in—crimson_reactor_idle_poll_time_us200,crimson_poll_mode„at the expense of 100% cpu usage“ Standard false,crimson_bluestore_num_threads. ↩︎ ↩︎Ceph v21.2.0,
seastore_require_partition_count_match_reactor_count— „disable osd shards changes upon restart“, Standard true. ↩︎ceph-rust ADR 0006, thread-per-core runtime — ein gepinnter, busy-pollender Thread pro Kern, PGs gehören einem Kern. ↩︎
ceph-rust ADR 0004, storage I/O — SPDK und die io_uring-Stufe, gerätegetakteter Leerlauf. ↩︎
ceph-rust docs, configuration reference —
flashstore_coresStandard 8,flashstore_lcores,flashstore_store_shardsbeim Prepare festgelegt. ↩︎Ceph Umbrella, SeaStore developer documentation — Wurzel pro Reaktor, Onode-, OMAP-, LBA- und Backref-Bäume, ein Byte „clean“ pro geschriebenem Byte, die Reihenfolge der Journal-Einträge, das RBM-Backend. Quelle:
doc/dev/crimson/seastore.rstat v21.2.0. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ceph-rust ADR 0021, storage engine — ein COW-B+-Baum pro Shard, paralleler Commit, Checkpoints, Hintergrundwartung, verworfene Alternativen, darunter Log-Structured und „Per-object omap subtree/root“. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Ceph v21.2.0,
crimson/os/seastore/cached_extent.h— „Returns crc32c of buffer“. ↩︎Ceph v21.2.0,
seastore_main_device_type— „The main device type seastore uses (SSD or RANDOM_BLOCK_SSD)“, StandardSSD. ↩︎ ↩︎Ceph v21.2.0,
seastore_segment_size— Standard 64 MiB. ↩︎Ceph v21.2.0,
crimson/net/SocketMessenger.cc— „ProtocolV1 is no longer supported“. ↩︎ceph-rust ADR 0168, out of scope — msgr1 raus, nur v2. ↩︎
ceph-rust docs, hardware and host requirements — PLP Pflicht, ganze Namespaces. ↩︎