Migrating from LINSTOR
Blockstor can take over a LINSTOR cluster that runs on Kubernetes. The linstor-migrate tool converts LINSTOR’s database into blockstor resources, and blockstor then adopts the volumes and DRBD metadata that are already on disk. No data is copied or resynced, and replica placement does not change.
Do this in a maintenance window, after a full rehearsal on a staging cluster.
What moves and what does not
Converted:
- nodes, storage pools, resource groups, resource definitions with their volumes, replicas, and successful snapshots;
- controller-wide DRBD options;
- DRBD minor numbers, node IDs and the shared secret, unchanged;
- DRBD ports, if you capture them from the running nodes (step 3 below).
Not converted, and listed in the tool’s report:
- LUKS passphrases. Encrypted volumes convert with their layers intact, but blockstor cannot open them until you set up the passphrase by hand.
- Backup shipping remotes, and replicas or snapshots that LINSTOR marked as deleted or failed.
- Snapshots of definitions with more than one volume are adopted with their first volume only.
Before you start
Check that the cluster is healthy.
linstor resource list --faultyis empty, every replica with data isUpToDate, and no node is offline. A degraded replica is adopted as it is and stays degraded.Dump the LINSTOR database. LINSTOR on Kubernetes keeps it in custom resources:
mkdir dump && cd dump kubectl get crds | grep -o ".*.internal.linstor.linbit.com" \ | xargs -I{} sh -c 'kubectl get {} -ojson > {}.json' cd ..Capture the DRBD ports. LINSTOR 1.33 does not store them in its database. Without them, blockstor would assign new ports, and every replica would reconnect under load. Collect them from the satellites:
for pod in $(kubectl -n cozy-linstor get pods -l app.kubernetes.io/component=linstor-satellite \ -o jsonpath='{.items[*].metadata.name}'); do kubectl -n cozy-linstor exec "$pod" -- sh -c ' for f in /var/lib/linstor.d/*.res; do rd=$(basename "$f" .res) port=$(grep -oE "address[^;]*:[0-9]+" "$f" | grep -oE "[0-9]+$" | head -1) [ -n "$port" ] && echo "$rd $port" done' done | sort -u > drbd-ports.txtChange the namespace and label to match your installation. Every replica of a volume shares one port. If one volume shows two different ports, stop and find out why.
Take pool snapshots. A recursive
zfs snapshotof every pool gives you a rollback point that does not depend on either control plane.Check the volume names on disk. Blockstor finds existing volumes by name:
<pool>/<definition name, lowercase>_<volume number, five digits>, for exampledata/pvc-1234_00000. If the name does not match exactly, blockstor creates a new empty volume next to the real one. Replicated volumes would heal from their peers, but a volume with a single replica and no DRBD would come up empty. On every node, compare the list of volumes with the names the converted manifests expect:zfs list -H -o name -t volume | sort zfs list -H -o name -t snapshot | sortSnapshots are found as
<pool>/<definition>_00000@<snapshot>. Do not continue while any single-replica volume is missing under its expected name.Rehearse on staging. Run the whole procedure on a copy of the pools. Check that every pool registers, every replica reaches
UpToDatewithout a resync, and no new empty volumes appear.
Convert
cmd/linstor-migrate is in no release up to v0.1.17. It ships in the release after that, so pick that one or a newer one for <VERSION>. Build the tool from the blockstor release you are installing and run it on the dump:
go install github.com/cozystack/blockstor/cmd/linstor-migrate@v<VERSION>
linstor-migrate -in ./dump -drbd-ports ./drbd-ports.txt -out ./blockstor-manifests.yaml
Read the whole report it prints. Each warning: line is something the tool refused to guess. Resolve every one of these before you go on:
LUKS passphrase NOT migrated.no DRBD port.skipped with its replicas. The definition’s replicas cannot be adopted under one layer stack: they were built two ways, a diskful replica has no layer chain in the dump, or a replica was built otherwise than the stack the definition names. The reason in the line says which. An unreadablelayer_stackcolumn counts as no stack, and the line names its value. Adopted as it is, such a replica would come up under a stack it was not built with, which for a LUKS volume writes DRBD metadata over its ciphertext. Settle the stack in LINSTOR and convert again.unreadable layer_stack. The definition’slayer_stackcolumn is not a list the converter can read. When its replicas agree, it takes the stack they were built with and the line names it; check that this is the stack you expect. With no diskful replica the stack is left unset and the controller pins one; see How the stack is pinned.
A definition with no layer stack whose replicas all agree takes their stack without a warning.
Cut over
Stop new volumes. Scale the CSI provisioner and attacher to zero.
Stop the LINSTOR controller. Scale
deploy/linstor-controllerto zero. Leave the LINSTOR satellites and the DRBD devices running: they keep serving I/O.Install blockstor as described in Installation, with satellites on the same nodes and pools. Check the image versions before you start them.
Apply the converted manifests. They are already in dependency order:
kubectl apply -f ./blockstor-manifests.yamlWait for adoption. Every replica should report
UpToDatewithout starting a resync,blockstor resource list --faultyshould be empty, and every pool should report its real free space.Point CSI at blockstor, as in Provisioning volumes with CSI, and scale the provisioner and attacher back up. Create a test PVC, and check that an existing PVC still mounts read-write.
Check before you call it done
- The number of nodes, pools, groups, definitions and replicas matches the counts in the converter’s report.
- For at least five volumes, the size,
/dev/drbd<minor>, node IDs and port match the values from before the migration. A changed minor or node ID is a reason to stop and roll back. - No replica is unexpectedly syncing.
- Encrypted volumes stay closed until you set up their passphrase. Keep their consumers stopped until then.
Roll back
Until CSI has been pointed at blockstor and checked, rolling back means: scale blockstor to zero, scale linstor-controller back up, and point CSI at LINSTOR again. Blockstor did not touch the data on disk or the running DRBD devices, so this undoes only the control plane. The pool snapshots from step 4 are the last-resort rollback for the data itself.