Skip to content

feat(driver): add validation for RWX block volume attachments - #403

Merged
WanzenBug merged 2 commits into
masterfrom
feat/rwx-block-validation
Jan 13, 2026
Merged

WanzenBug merged 2 commits into
masterfrom
feat/rwx-block-validation

Conversation

@kvaps

@kvaps kvaps commented Jan 7, 2026 •

Copy link
Copy Markdown
Member

Summary

Add controller-side validation to prevent misuse of allow-two-primaries for RWX block volumes:

  • Validates that all pods using the volume belong to the same VM
  • Support for KubeVirt hotplug disks (via ownerReferences resolution)

Note: This validation applies ONLY to RWX block volumes (volumeMode: Block). Filesystem RWX volumes (including NFS) are not affected.

Implementation Details

Controller-Side Validation (ControllerPublishVolume)

When attaching a RWX block volume:

  1. Query Kubernetes API for all pods using the target PVC
  2. Filter out non-active pods (Succeeded/Failed status)
  3. Extract VM names from pods:
    • Direct: read vm.kubevirt.io/name label from virt-launcher pods
    • Hotplug: follow ownerReferences from hotplug-disk pods to virt-launcher pod
  4. Validate that all pods belong to the same VM
  5. Reject if pods from different VMs are found

Error example:

Warning  FailedAttachVolume  attachdetach-controller  
AttachVolume.Attach failed for volume "pvc-xxx" : rpc error: code = FailedPrecondition 
desc = ControllerPublishVolume failed for pvc-xxx: RWX block volume tenant-ns/vm-pvc 
is being used by pods from different VMs (vm1 and vm2); this is not supported - 
RWX block volumes with allow-two-primaries are only for live migration of a single VM

Why Controller-Only Validation?

Node-side validation was considered but rejected because:

  • CSI node pods have no Kubernetes API access (by design)
  • Passing VM name via publish_context doesn't work for existing VolumeAttachments
  • Filesystem-based tracking creates issues with stale directories

Controller validation is sufficient because:

  • ControllerPublishVolume is called for each new VolumeAttachment
  • It has full access to Kubernetes API to verify pod ownership
  • It blocks before the volume is attached, providing clear error messages

Known Limitations

No Node-Level Validation

Node-side validation is not implemented. This means the driver does not protect against multi-attach of RWX block volumes to different VMs on the same node when VolumeAttachment already exists.

However, this implementation does protect against misuse of allow-two-primaries in DRBD - the controller validation ensures that the DRBD option is only enabled when all pods belong to the same VM (live migration scenario).

Migration Blocked by Failed Pods

If VM2 attempts to start but is blocked by controller validation (because VM1 is using the volume), VM2 will remain in Pending state with FailedAttachVolume. If VM1 then attempts to migrate to the same node as VM2, the migration will also be blocked because:

  1. VM2 pod is in Pending with nodeName set (already scheduled)
  2. Controller validation sees both VM1 and VM2 pods using the PVC
  3. Migration is rejected with the same error

Workaround: Delete the blocked VM2 pod before migrating VM1.

Test plan

  • Run unit tests: go test ./pkg/driver/... --run TestValidateRWX -v
  • Test different VMs on different nodes - blocked correctly
  • Test live migration scenario with KubeVirt VM
  • Test hotplug disk attachment/detachment

@kvaps
kvaps force-pushed the feat/rwx-block-validation branch from 3c201f2 to 52ab015 Compare January 7, 2026 15:58
@kvaps
kvaps marked this pull request as ready for review January 7, 2026 20:03
kvaps added a commit to cozystack/cozystack that referenced this pull request Jan 7, 2026
Add custom linstor-csi image build to packages/system/linstor:

- Add Dockerfile based on upstream linstor-csi
- Import patch from upstream PR #403 for RWX block volume validation
  (prevents misuse of allow-two-primaries in KubeVirt live migration)
- Update Makefile to build both piraeus-server and linstor-csi images
- Configure LinstorCluster CR to use custom linstor-csi image in
  CSI controller and node pods

The RWX validation patch ensures that RWX block volumes with
allow-two-primaries are only used by pods belonging to the same
KubeVirt VM during live migration.

Upstream PR: piraeusdatastore/linstor-csi#403

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Andrei Kvapil <[email protected]>
@kvaps
kvaps requested a review from WanzenBug January 7, 2026 20:12
@kvaps
kvaps force-pushed the feat/rwx-block-validation branch 5 times, most recently from d3d1393 to 991a9da Compare January 7, 2026 20:37
kvaps added a commit to cozystack/cozystack that referenced this pull request Jan 7, 2026
Add custom linstor-csi image build to packages/system/linstor:

- Add Dockerfile based on upstream linstor-csi
- Import patch from upstream PR #403 for RWX block volume validation
  (prevents misuse of allow-two-primaries in KubeVirt live migration)
- Update Makefile to build both piraeus-server and linstor-csi images
- Configure LinstorCluster CR to use custom linstor-csi image in
  CSI controller and node pods

The RWX validation patch ensures that RWX block volumes with
allow-two-primaries are only used by pods belonging to the same
KubeVirt VM during live migration.

Upstream PR: piraeusdatastore/linstor-csi#403

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Andrei Kvapil <[email protected]>
kvaps added a commit to cozystack/cozystack that referenced this pull request Jan 7, 2026
Add custom linstor-csi image build to packages/system/linstor:

- Add Dockerfile based on upstream linstor-csi
- Import patch from upstream PR #403 for RWX block volume validation
  (prevents misuse of allow-two-primaries in KubeVirt live migration)
- Update Makefile to build both piraeus-server and linstor-csi images
- Configure LinstorCluster CR to use custom linstor-csi image in
  CSI controller and node pods

The RWX validation patch ensures that RWX block volumes with
allow-two-primaries are only used by pods belonging to the same
KubeVirt VM during live migration.

Upstream PR: piraeusdatastore/linstor-csi#403

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Andrei Kvapil <[email protected]>
kvaps added a commit to cozystack/cozystack that referenced this pull request Jan 9, 2026
Add custom linstor-csi image build to packages/system/linstor:

- Add Dockerfile based on upstream linstor-csi
- Import patch from upstream PR #403 for RWX block volume validation
  (prevents misuse of allow-two-primaries in KubeVirt live migration)
- Update Makefile to build both piraeus-server and linstor-csi images
- Configure LinstorCluster CR to use custom linstor-csi image in
  CSI controller and node pods

The RWX validation patch ensures that RWX block volumes with
allow-two-primaries are only used by pods belonging to the same
KubeVirt VM during live migration.

Upstream PR: piraeusdatastore/linstor-csi#403

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Andrei Kvapil <[email protected]>
kvaps added a commit to cozystack/cozystack that referenced this pull request Jan 9, 2026
Add custom linstor-csi image build to packages/system/linstor:

- Add Dockerfile based on upstream linstor-csi
- Import patch from upstream PR #403 for RWX block volume validation
  (prevents misuse of allow-two-primaries in KubeVirt live migration)
- Update Makefile to build both piraeus-server and linstor-csi images
- Configure LinstorCluster CR to use custom linstor-csi image in
  CSI controller and node pods

The RWX validation patch ensures that RWX block volumes with
allow-two-primaries are only used by pods belonging to the same
KubeVirt VM during live migration.

Upstream PR: piraeusdatastore/linstor-csi#403

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Andrei Kvapil <[email protected]>
kvaps added a commit to cozystack/cozystack that referenced this pull request Jan 9, 2026
## What this PR does

This PR adds custom linstor-csi image build to the linstor package with
an important upstream patch for RWX block volume validation.

**Changes:**
- Add linstor-csi Dockerfile based on upstream linstor-csi master
- Import patch from upstream PR piraeusdatastore/linstor-csi#403 for RWX
block volume validation
- Update Makefile to build both piraeus-server and linstor-csi images
- Configure LinstorCluster CR to use custom linstor-csi image in CSI
controller and node pods

**RWX Validation Patch:**
The imported patch prevents misuse of DRBD allow-two-primaries by
ensuring RWX block volumes are only used by pods belonging to the same
KubeVirt VM during live migration. This prevents data corruption when
multiple non-related pods attempt to use the same RWX block volume.

**Upstream PR:**
piraeusdatastore/linstor-csi#403

### Release note

```release-note
[linstor] Add custom linstor-csi image build with RWX block volume validation patch that prevents data corruption during KubeVirt live migration
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Integrated LINSTOR CSI with deployable CSI components and node init
helpers; packaged as a production-ready image.

* **Updates**
* Added build/publish flow for Piraeus server and LINSTOR CSI images;
chart values updated with new image references and tags.

* **Behavior changes**
* Node-side RWX block-volume pre-validation to prevent conflicting
multi-node/multi-writer access.

* **Tests**
* Comprehensive RWX validation tests covering multi-pod and VM
scenarios.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
kvaps added a commit to cozystack/cozystack that referenced this pull request Jan 9, 2026
## What this PR does

This PR adds custom linstor-csi image build to the linstor package with
an important upstream patch for RWX block volume validation.

**Changes:**
- Add linstor-csi Dockerfile based on upstream linstor-csi master
- Import patch from upstream PR piraeusdatastore/linstor-csi#403 for RWX
block volume validation
- Update Makefile to build both piraeus-server and linstor-csi images
- Configure LinstorCluster CR to use custom linstor-csi image in CSI
controller and node pods

**RWX Validation Patch:**
The imported patch prevents misuse of DRBD allow-two-primaries by
ensuring RWX block volumes are only used by pods belonging to the same
KubeVirt VM during live migration. This prevents data corruption when
multiple non-related pods attempt to use the same RWX block volume.

**Upstream PR:**
piraeusdatastore/linstor-csi#403

### Release note

```release-note
[linstor] Add custom linstor-csi image build with RWX block volume validation patch that prevents data corruption during KubeVirt live migration
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Integrated LINSTOR CSI with deployable CSI components and node init
helpers; packaged as a production-ready image.

* **Updates**
* Added build/publish flow for Piraeus server and LINSTOR CSI images;
chart values updated with new image references and tags.

* **Behavior changes**
* Node-side RWX block-volume pre-validation to prevent conflicting
multi-node/multi-writer access.

* **Tests**
* Comprehensive RWX validation tests covering multi-pod and VM
scenarios.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@kvaps
kvaps force-pushed the feat/rwx-block-validation branch from 00fd08c to a514193 Compare January 12, 2026 21:12
Add controller-side validation to prevent misuse of allow-two-primaries
for RWX block volumes.

Controller-side validation (ControllerPublishVolume):
- Query K8s API for all pods using the target PVC
- Extract VM names from virt-launcher pods or via ownerReferences for hotplug disks
- Validate all pods belong to the same VM
- Block attachment if pods from different VMs are found

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Andrei Kvapil <[email protected]>
@kvaps
kvaps force-pushed the feat/rwx-block-validation branch from a514193 to acf1719 Compare January 12, 2026 21:59
@kvaps

kvaps commented Jan 12, 2026 •

Copy link
Copy Markdown
Member Author

Hey @WanzenBug I decided to remove node-level validation because it is blocking KubeVirt logic for hotplug volumes, at least this patch protects from misuse of allow-to-primaries

PR description updated

Comment thread pkg/driver/driver.go Outdated
}

// Get PV to find PVC reference (volumeID == PV name in CSI)
pv, err := d.kubeClient.Resource(pvGVR).Get(ctx, volumeID, metav1.GetOptions{})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strictly speaking, this is not always true. You need to check spec.csi.volumeHandle instead. I guess its not really worth to fully check for that, but we should at least check the PV that it has the correct volumeHandle.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thanks

Comment thread pkg/driver/driver.go Outdated
continue
}

claimName, _, _ := unstructured.NestedString(pvc, "claimName")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can combine this with the line above, no need to unpack the pvc part?

Comment thread pkg/driver/driver.go

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps move the added validation to a seperate package/file? There is already a pkg/utils, where we could have a free-standing function ValidateRWXBlockAttachment(), which takes the necessary kube client, logs etc...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RWX Block validation moved to pkg/utils/rwx_validation.go

Comment thread pkg/driver/driver.go Outdated
rwxBlock := req.VolumeCapability.AccessMode.GetMode() == csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER && req.VolumeCapability.GetBlock() != nil

// Validate RWX block attachment to prevent misuse of allow-two-primaries
if rwxBlock {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a switch/option that disables this check? I don't think there would be any valid use cases outside of kubevirt, but perhaps there is some obscure custom virtualization-on-k8s platform that would be stopped by this patch.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added new flag --disable-rwx-block-validation=false

kvaps added a commit to cozystack/cozystack that referenced this pull request Jan 13, 2026
Add custom linstor-csi image build to packages/system/linstor:

- Add Dockerfile based on upstream linstor-csi
- Import patch from upstream PR #403 for RWX block volume validation
  (prevents misuse of allow-two-primaries in KubeVirt live migration)
- Update Makefile to build both piraeus-server and linstor-csi images
- Configure LinstorCluster CR to use custom linstor-csi image in
  CSI controller and node pods

The RWX validation patch ensures that RWX block volumes with
allow-two-primaries are only used by pods belonging to the same
KubeVirt VM during live migration.

Upstream PR: piraeusdatastore/linstor-csi#403

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Andrei Kvapil <[email protected]>
@kvaps
kvaps force-pushed the feat/rwx-block-validation branch 2 times, most recently from b42eada to 4a6e0c6 Compare January 13, 2026 12:20
…able RWX block validation

Move RWX block validation logic to a separate package as requested
in code review. Also addressed other review comments:
- Add volumeHandle check to verify PV matches the requested volumeID
- Simplify claimName extraction by combining nested calls

Add --disable-rwx-block-validation CLI flag and DisableRWXBlockValidation()
driver option. This allows administrators to disable the KubeVirt VM
ownership validation for RWX block volumes in environments where the
validation causes issues or when using RWX block volumes outside of
KubeVirt.

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Andrei Kvapil <[email protected]>
@kvaps
kvaps force-pushed the feat/rwx-block-validation branch from 4a6e0c6 to 28d809e Compare January 13, 2026 12:23
@kvaps
kvaps requested a review from WanzenBug January 13, 2026 12:24
kvaps added a commit to cozystack/cozystack that referenced this pull request Jan 13, 2026
<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does

upstream PR piraeusdatastore/linstor-csi#403

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[linstor] Refactor node-level RWX validation
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a command-line option to disable strict RWX block volume
validation for specialized deployments.
  * Centralized RWX validation into a shared utility used by the driver.

* **Improvements**
* Improved VM identification and pod/PV handling for RWX block
attachments, including hotplug scenarios.

* **Tests**
* Added comprehensive unit tests covering RWX validation and related
pod/PV scenarios.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@WanzenBug
WanzenBug merged commit ea2cb50 into master Jan 13, 2026
5 of 6 checks passed
@WanzenBug
WanzenBug deleted the feat/rwx-block-validation branch January 13, 2026 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants