docs: add the Blockstor storage backend and its migration guide - #667
Open
Andrei Kvapil (kvaps) wants to merge 8 commits into
Open
docs: add the Blockstor storage backend and its migration guide#667Andrei Kvapil (kvaps) wants to merge 8 commits into
Andrei Kvapil (kvaps) wants to merge 8 commits into
Conversation
Cozystack is gaining a second storage control plane, so the platform install page now presents the choice as tabs rather than assuming LINSTOR. LINSTOR stays the default and is the first tab; Blockstor carries an experimental warning. Adds a migration guide for moving an existing cluster across. It is written from a run against a live cluster, so it leads with the parts that are easy to get wrong: the adoption happens after the switch, not before, because the resources have nowhere to live until the CRDs exist; the controller has to be stopped while the converted resources are applied, or it auto-places replicas on freshly allocated ports and the real ones are then refused; the live DRBD ports have to be read from the kernel because LINSTOR does not keep them in its custom resources; and a cluster coming from LINSTOR hits a Service ownership collision a fresh install never sees. The guide also states the version requirement plainly: a Blockstor build that cannot read a pool name from StorDriver/StorPoolName adopts nothing, which is every release up to and including v0.1.17. Assisted-By: Claude Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
✅ Deploy Preview for cozystack ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Contributor
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
linstor-csi keeps reconciling while the control plane is being replaced, and a volume it cannot find is a volume it re-provisions: it creates a fresh resource definition through the LINSTOR-compatible API, carrying newly allocated DRBD minors and ports and a different node ID, for a volume that already exists and holds data. Those definitions also lack spec.initialized, so the satellite treats them as new. Observed on a live migration, where two already-migrated volumes were re-provisioned this way during the switch window. Assisted-By: Claude Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
Two things claim space during adoption, and both surfaced on a live migration only after the switch had started. Blockstor's thick provider reserves the full size of every volume it adopts. LINSTOR allows a pool declared thick to hold sparse volumes via StorDriver/ZfscreateOptions, so a comfortably oversubscribed pool can fill up mid-migration and leave the last volumes unadoptable. Blockstor also reconciles replica count against the resource group's placeCount continuously, where LINSTOR only places on request, so every under-replicated volume is topped up as soon as the controller starts. Assisted-By: Claude Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
Andrei Kvapil (kvaps)
marked this pull request as ready for review
August 26, 2026 11:14
Andrei Kvapil (kvaps)
requested review from
Timofei Larkin (lllamnyp),
myasnikovdaniil and
Timur Tukaev (tym83)
as code owners
August 26, 2026 11:14
The runbook stopped only the CSI provisioner, and only at the switch. Two writers were left running through the backup and the dump. piraeus-operator owns the linstor-controller Deployment and the satellite DaemonSets, so scaling the controller down while the operator runs achieves nothing — it puts it straight back. And the controller itself keeps writing to its database, so a backup taken underneath it does not match the dump taken a moment later, and the converted manifest then describes a cluster that no longer exists. The stop moves to its own first step, in dependency order, ahead of the backup. The CSI scale-down moves there with it; step 6 now explains the window rather than repeating the command. Two prerequisites corrected while here. The Blockstor version is not the operator's to choose — it arrives pinned inside the Cozystack release, so the check is a Cozystack version check and the remedy is an upgrade, not an image swap. And the thick-pool capacity warning is gone: the converter now carries a sparse ZFS pool over as thin, so adoption no longer reserves the full size of volumes LINSTOR created sparse. What remains of that prerequisite is the placeCount top-up, which is real. Assisted-By: Claude Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
A {{% %}} shortcode renders its body as Markdown, so an alert nested
inside a tab runs its body through twice: the inner shortcode receives
the HTML the outer already produced, and escapes it. The notice came out
as a literal <strong> inside a code block.
It lives outside the tabs now, which also means the reader sees it
whichever tab is open.
Assisted-By: Claude
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
Step 2.3 lets the operator choose Blockstor, and then step 3 walked them into commands that cannot work there. Every command in 3.1 and 3.2 runs through `kubectl exec deploy/linstor-controller`, and on backend: blockstor the control plane runs in external mode — that Deployment is never created, so each one fails with NotFound. 3.1 and 3.2 now say which backend they are for, and 3.4 covers the same ground for Blockstor: list the nodes, create the ZFS pool through the satellite (which carries the tooling), register it as a StoragePool custom resource, check the result. It is kubectl throughout, because Blockstor keeps its state in custom resources rather than behind a controller pod — there is nothing to exec into. Storage classes are backend-independent, so 3.3 is shared and both paths lead into it. Assisted-By: Claude Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
The first version of 3.4 configured storage by applying custom resources by hand, on the reasoning that Blockstor keeps its state in CRDs. That missed the point: Blockstor ships a client that speaks the same command grammar as LINSTOR, short forms included, so the steps mirror 3.1 and 3.2 one for one and an operator moving between backends types almost the same thing. What actually differs is the client. `blockstor` is a standalone binary that talks to the Kubernetes API directly — no controller pod to exec into, no alias to set, it reads the kubeconfig the way kubectl does. Assisted-By: Claude Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
The backend choice was a tab set in 2.3, and the steps that act on it were a separate section further down. An operator picking Blockstor had to remember that and navigate to a different heading. The `tabs` shortcode gains an opt-in `sync` group. Tab sets sharing a group switch together and the choice is remembered, so picking a backend anywhere on the page switches every command that follows. Tab sets without the parameter behave exactly as before — nothing else on the site changes. Storage now reads as one flow: 3.1 and 3.2 are backend tabs in that group, and the separate Blockstor section is gone. ZFS/LVM inside 3.2 became plain headings rather than an inner tab set: the shortcode collects tabs through a page Scratch, so a nested set absorbs content from beyond its own boundary — the inner tabs came out carrying labels lifted from later paragraphs. Assisted-By: Claude Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Documents Blockstor as a second, selectable storage control plane, and how to move an existing cluster onto it.
Goes to
content/en/docs/next/because Blockstor is unreleased.What changes
The platform install page presented LINSTOR as the only option. It now presents the choice as tabs under a new 2.3. Choose a Storage Backend — LINSTOR first and marked as the default, Blockstor second and marked experimental. Subsequent sections are renumbered.
The storage section index said these guides describe "the LINSTOR storage system"; it now names both backends, links to the choice and the migration, and states that unless a page says otherwise it describes LINSTOR.
Adds Migrating from LINSTOR to Blockstor.
About the migration guide
It is written from an actual run against a live cluster rather than from the design, so it leads with the parts that are easy to get wrong and that only a real migration surfaces:
drbdsetup showincantation, including the detail that the port sits inside the connection'spathblock rather than on anaddressline.StorDriver/StorPoolNamelogsunknown storage pooland adopts nothing — that is every release up to and including v0.1.17.Status of the procedure
The steps up to and including the backend switch were executed against a live 3-node cluster with 41 volumes: the control plane was replaced with no data loss and no service disruption, DRBD kept serving throughout, and all peers stayed UpToDate.
Adoption itself was not completed, because no published Blockstor release contains the storage-pool fix above. The guide reflects what the run established, and its ordering and controller-stop steps are written precisely because the failure modes were observed. It should be re-verified end to end once a release with that fix exists — and this PR should not merge ahead of the platform change it documents, cozystack/cozystack#2942.
Testing
hugo --gc --environment developmentbuilds clean. The tabs render as real tab controls with both labels, the migration page renders, and the cross-link anchor#23-choose-a-storage-backendexists on the target page.