Volume Expansion¶
MeshStor supports online volume expansion — you can grow a PVC while the pod is running, with no downtime. The driver grows each partition on every node, then expands the MD RAID array and XFS filesystem in place.
How It Works¶
sequenceDiagram
participant U as User
participant C as Controller
participant R as Remote Node
participant N as Consumer Node
U->>C: Patch PVC with larger size
C->>C: Update CR spec.capacityBytes, set phase=Expanding
C-->>N: NodeExpandVolume called by kubelet
N->>N: Grow local partition in-place
R->>R: Reconciler: grow remote partition in-place
R->>C: Update partition SizeBytes in CR
N->>N: Verify all partitions expanded
N->>N: mdadm --grow (expand MD array)
N->>N: xfs_growfs (expand filesystem)
N->>C: Set phase=Synced
- You patch the PVC with a larger storage request.
- The controller validates the request, updates
spec.capacityBytes, and sets the volume phase toExpanding. - The consumer node (where the MD device lives) grows its local partition.
- Each remote node grows its partition independently via the reconciler.
- Once all partitions are at the new size, the consumer node runs
mdadm --growandxfs_growfsto expand the MD array and filesystem. - The volume phase returns to
Synced.
In-Place Growth vs Replacement¶
MeshStor first tries to grow each partition in place by extending it into adjacent free space on the same drive. This is fast and requires no data sync.
If a drive lacks adjacent free space, MeshStor creates a replacement partition on a drive with enough room, swaps it into the MD array via mdadm --replace, and removes the old partition. This path is slower because the replacement must sync all data from the other members.
Prerequisites¶
- StorageClass must have
allowVolumeExpansion: true. All default examples except RAID10 have this enabled. drivesPerCopymust be1. Expansion is not supported for striped volumes (drivesPerCopy > 1).- Sufficient free space on the drives hosting partitions. Each partition must be able to grow by the requested delta, either in place or on another drive.
Expanding a Volume¶
Edit the PVC to request a larger size:
Or use kubectl edit:
Note
The actual allocated size may be slightly larger than requested due to 1 MiB alignment.
Observing Expansion¶
Watch Volume Phases¶
Typical output during expansion:
NAME PHASE MDSTATE TOTAL ACTIVE SYNC
my-volume Expanding active 2 2 100%
my-volume Synced active 2 2 100%
If replacement partitions are needed (no adjacent free space), you will see a sync phase:
NAME PHASE MDSTATE TOTAL ACTIVE SYNC
my-volume Expanding active 2 2 100%
my-volume Expanding recovering 2 1 12.5%
my-volume Expanding recovering 2 1 67.3%
my-volume Expanding active 2 2 100%
my-volume Synced active 2 2 100%
Check Partition Sizes¶
Verify that all partitions have been expanded:
kubectl get msvol my-volume -o jsonpath='{range .status.partitions[*]}{.nodeID}{"\t"}{.sizeBytes}{"\t"}{.state}{"\n"}{end}'
Verify Filesystem Size¶
From inside the pod:
The filesystem size should reflect the new capacity (minus a small overhead for XFS metadata).
Constraints and Limitations¶
| Constraint | Detail |
|---|---|
drivesPerCopy > 1 |
Expansion is not supported for striped (RAID10) volumes. Set allowVolumeExpansion: false in the StorageClass. |
| Shrinking | Volume shrinking is not supported. Requests for a smaller size are rejected. |
| Concurrent expansion | Only one expansion at a time per volume. A new expansion request while one is in progress is rejected. |
| Replacement sync time | If in-place growth fails on any partition, the replacement path requires a full data sync. Duration depends on volume size and network throughput. |
Troubleshooting¶
Expansion Stuck in Expanding Phase¶
The volume stays in Expanding and never transitions to Synced.
Check partition sizes in the CR:
Look at status.partitions[*].sizeBytes. If any partition still shows the old size, that node has not completed its expansion.
Check the node logs for the lagging partition:
# Find which node has the undersized partition, then check its logs:
kubectl logs -n meshstor daemonset/meshstor-csi-node --selector=... | grep -i expand
Common causes:
- No free space on the drive. The partition cannot grow in place and no other drive has enough room for a replacement. Check available capacity with
kubectl get msnd. - Node is down. The remote node's reconciler cannot run. Verify the DaemonSet pod is healthy on that node.
- NVMe-oF connectivity issue. The consumer node cannot reach the remote node to import the replacement partition. Check network connectivity on TCP port 4420 (or RDMA port 4421).
Expansion Rejected¶
The kubectl patch command returns an error.
allowVolumeExpansionnot set: The StorageClass must haveallowVolumeExpansion: true.drivesPerCopy > 1: Expansion is only supported fordrivesPerCopy=1.- Size not larger: The requested size must be strictly larger than the current size.
Filesystem Size Does Not Match¶
After expansion completes (phase=Synced), df inside the pod shows a smaller size than expected.
- XFS metadata overhead accounts for a small percentage of the raw capacity. This is normal.
- If the difference is large (>10%), check that
xfs_growfssucceeded by inspecting the consumer node logs for errors.
What's Next¶
- Replication — how copies and striping affect fault tolerance
- Volume Relocation — how volumes migrate during node drain
- StorageClass Parameters — complete parameter reference
- Monitoring — observability and alerting for MeshStor volumes