DataVolume Cloning, Shareable Disks, and Disk Error Policy

Duration: ~25 minutes

Overview

virt-04 locked devices and memory on the VM spec. Storage is the next isolation boundary: who can clone a DataVolume across namespaces, whether a disk is marked shareable, and whether I/O errors are ignore instead of stop or report.

Default CDI cloning stays inside one namespace unless a cluster admin creates a RoleBinding that grants datavolumes/source to a service account in another project. That binding is the control.

Why it matters

A clone across namespaces is a data copy the destination owners did not take from a signed registry; they took it from someone else’s PVC. Shareable disks without a clustered filesystem corrupt data. errorPolicy: ignore hides failed writes so the guest thinks the disk is fine.

What does it solve

  • Project A cloning Project B’s gold image (and whatever secrets landed on that volume)

  • Two VMs writing the same disk without SCSI reservations or a clustered FS (see also virt-01 persistentReservation)

  • Windows clustered FS needing report, vs a lab that set ignore to quiet logs

Your Mission

Find RoleBindings that grant DataVolume clone across namespaces, list VMs with shareable: true, and list VMs with errorPolicy: ignore. Expect empty on a fresh lab. Do not patch rhel-webserver.

Prerequisites

  • virt-04 complete

  • jq on the bastion

  • Permission to get RoleBindings, ClusterRoles, and VirtualMachines

Click each step only if you need a hint.

Control: Restrict access to cross-namespace DataVolume cloning

Level: 1

CDI allows a DataVolume in namespace D to clone from namespace S only when S contains a RoleBinding whose subject is a ServiceAccount in D and whose role includes datavolumes/source.

Pros: Namespace isolation holds for virtual disks, not only for pods. Data does not silently flow to another tenant.

Cons / impact: Self-service "copy this gold VM into my project" needs a platform-owned binding or a registry/PVC workflow inside the same namespace.

Default: Only cluster administrators can arrange cross-namespace clones. There is no such RoleBinding until someone creates it.

Audit clone RoleBindings

Look for ClusterRoles that mention datavolumes/source, then RoleBindings that use them.

oc get clusterrole -o json | jq -r '
  .items[]
  | select(.rules[]? | .resources[]? == "datavolumes/source")
  | .metadata.name
'
echo '--- rolebindings with a foreign-namespace SA subject ---'
oc get rolebinding -A -o json | jq -c '
  .items[]
  | select(.subjects[]? | .kind == "ServiceAccount" and .namespace != null and .namespace != .metadata.namespace)
  | {ns: .metadata.namespace, name: .metadata.name, role: .roleRef.name, subjects}
'
Zero ClusterRoles (or only ones you documented) plus no foreign-SA RoleBindings is a pass. A binding from src-ns to default in dst-ns with role datavolume-cloner is the textbook finding from the guide.
Inspect a known cloner ClusterRole (if it exists)
oc get clusterrole datavolume-cloner -o yaml 2>/dev/null || echo "No datavolume-cloner ClusterRole (typical on a default install)"
If the ClusterRole exists, its rules should be the clone API only, and RoleBindings that use it should be rare and named.
Remediation

Delete RoleBindings that grant unintended cross-namespace clone. Do not delete CDI operator Roles.

# oc delete rolebinding BINDING -n SOURCE_NAMESPACE
Re-run the foreign-SA jq. The extra binding should be gone. See OpenShift Virtualization DataVolume cloning for the supported grant procedure when clone is required.

Control: Disable shareable disks

Level: 1

shareable: true on a disk lets more than one VM attach it. That is valid only with a clustered filesystem or a distributed application that understands shared block.

Pros: No silent dual-write corruption. Each disk has one writer unless you opted into clustered I/O.

Cons / impact: You cannot use shared-block clustering without this flag (and often without persistentReservation from virt-01). Treat that as a named exception.

Default: Shareable is off. The VM list should be empty.

Audit shareable disks
oc get vm -A -o json | jq -r '
  .items[]
  | select([.spec.template.spec.domain.devices.disks[]? | select(.shareable == true)] | length > 0)
  | .metadata.namespace + "/" + .metadata.name
'
oc get vm rhel-webserver -n rhel-webserver -o json | jq '
  [.spec.template.spec.domain.devices.disks[]? | {name, shareable}]
'
First command empty. Second command: disks with shareable null or false.
Remediation

Remove the flag on disk index 0 of a VM you own (not rhel-webserver):

# oc patch vm VM_NAME -n NAMESPACE --type='json' -p='[
#   {"op": "remove", "path": "/spec/template/spec/domain/devices/disks/0/shareable"}
# ]'
Re-run the cluster jq. The VM should drop off the list.

Control: Make sure errorPolicy is not ignore

Level: 1

Disk errorPolicy decides what happens on a failed read/write. ignore continues as if the I/O succeeded. stop (default) pauses the VM. report surfaces the error to the guest (needed for some Windows clustered filesystems).

Pros: Failed writes become an incident, not silent corruption.

Cons / impact: Noisy storage may pause VMs (stop) instead of hiding errors. Maintenance windows that set ignore to reduce logs are a temporary exception, not a baseline.

Default: Unset, which means stop. The ignore-list should be empty.

Audit errorPolicy ignore
oc get vm -A -o json | jq -r '
  .items[]
  | select([.spec.template.spec.domain.devices.disks[]? | select(.errorPolicy == "ignore")] | length > 0)
  | .metadata.namespace + "/" + .metadata.name
'
oc get vm rhel-webserver -n rhel-webserver -o json | jq '
  [.spec.template.spec.domain.devices.disks[]? | {name, errorPolicy}]
'
First command empty. Second: errorPolicy null or stop/report, never ignore.
Remediation

Remove a bad policy (revert to default stop) or set report when Windows clustered FS needs it.

# oc patch vm VM_NAME -n NAMESPACE --type='json' -p='[
#   {"op": "remove", "path": "/spec/template/spec/domain/devices/disks/0/errorPolicy"}
# ]'
The VM should leave the ignore-list. Prefer report over ignore for clustered Windows disks; do not use ignore as the fleet default.

Debrief

Storage isolation is RBAC (clone), shared-writer flags, and honest I/O errors. Combined with virt-01 persistent reservations, you now have the clustered-disk story: off unless Windows shared FS is a documented exception.

What breaks without this:

  • Tenant B reading tenant A’s disk via clone

  • Dual-write corruption on a "shared" PVC

  • Guests that never see a failed write

Next is virt-06 — VLANs, MAC spoof filtering, and MultiNetworkPolicy.

Cleanup

Progress only. DataVolumes and rhel-webserver stay.

cd ~/ocp5-rhacs-showroom
bash setup/lab-cleanup.sh --module virt-05