OpenEBS LVM LocalPV on Single Node OpenShift (vSphere 7)

OpenEBS LVM LocalPV on Single Node OpenShift (vSphere 7)

A guide to installing OpenEBS LVM LocalPV CSI on SNO with snapshot support, using a locally attached disk. Tested on OCP 4.21, OpenEBS LVM LocalPV Helm chart, vSphere 7.


Prerequisites

  • Single Node OpenShift (SNO) cluster
  • A second disk attached to the VM (in this guide: /dev/sdd, 200GB)
  • Helm installed on your jumpbox
  • oc CLI with cluster-admin access

Phase 0: Prepare the Disk

Open a debug shell on the SNO node and create a volume group:

oc debug node/<node-name>
chroot /host

pvcreate /dev/sdd
vgcreate lvmvg /dev/sdd

# Create a thin pool (use ~95% of VG capacity)
lvcreate -L 189G -T lvmvg/thinpool

# Verify
vgs
lvs

exit
exit
Note: OpenEBS will also auto-create its own thin pool (lvmvg_thinpool) when it first provisions a volume. Use the auto-created pool name in the StorageClass (see Phase 3).

Phase 1: Load the dm-snapshot Kernel Module

OpenEBS requires the dm-snapshot kernel module for snapshot support. Load it manually first to verify:

oc debug node/<node-name>
chroot /host
modprobe dm-snapshot
lsmod | grep dm_snapshot
exit
exit

Then make it persistent across reboots via a MachineConfig:

cat <<EOF | oc apply -f -
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
  labels:
    machineconfiguration.openshift.io/role: master
  name: 99-master-dm-snapshot
spec:
  config:
    ignition:
      version: 3.2.0
    systemd:
      units:
        - contents: |
            [Unit]
            Description=Load dm-snapshot module
            [Service]
            Type=oneshot
            ExecStart=/usr/sbin/modprobe dm-snapshot
            [Install]
            WantedBy=multi-user.target
          enabled: true
          name: dm-snapshot.service
EOF
Note: This will trigger a node reboot on SNO. Wait for the node to return to Ready before continuing.

Phase 2: Install OpenEBS LVM LocalPV via Helm

Create the namespace and add the Helm repo:

oc new-project openebs

helm repo add openebs-lvmlocalpv https://openebs.github.io/lvm-localpv
helm repo update

Install the chart. The snapshot CRD flag is required because OCP/Rook-Ceph already owns the snapshot CRDs:

helm install openebs-lvmlocalpv openebs-lvmlocalpv/lvm-localpv \
  --namespace openebs \
  --set openebs-crds.csi.volumeSnapshots.enabled=false \
  --set crds.csi.volumeSnapshots.enabled=false \
  --set lvmController.replicas=1 \
  --set lvmController.podAntiAffinity.enabled=false

Phase 3: Apply OpenShift SCCs

OpenEBS requires privileged access. Label the namespace and grant SCCs to the service accounts:

oc label namespace openebs \
  pod-security.kubernetes.io/enforce=privileged \
  pod-security.kubernetes.io/audit=privileged \
  pod-security.kubernetes.io/warn=privileged --overwrite

oc adm policy add-scc-to-user privileged \
  system:serviceaccount:openebs:openebs-lvm-node-sa

oc adm policy add-scc-to-user privileged \
  system:serviceaccount:openebs:openebs-lvm-controller-sa

Verify both pods are running:

oc get pods -n openebs

Expected output:

openebs-lvmlocalpv-lvm-localpv-controller-xxx   5/5   Running
openebs-lvmlocalpv-lvm-localpv-node-xxx         2/2   Running

Phase 4: Create StorageClass and VolumeSnapshotClass

After first provisioning a PVC, check which thin pool OpenEBS auto-created:

oc debug node/<node-name> -- chroot /host lvs -o lv_name,pool_lv lvmvg

Use that pool name (e.g. lvmvg_thinpool) in the StorageClass:

cat <<EOF | oc apply -f -
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: openebs-lvmpv
provisioner: local.csi.openebs.io
parameters:
  storage: "lvm"
  volgroup: "lvmvg"
  thinprovision: "yes"
  thinpoolname: "lvmvg_thinpool"
allowVolumeExpansion: true
volumeBindingMode: Immediate
EOF

Create the VolumeSnapshotClass:

cat <<EOF | oc apply -f -
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: openebs-lvmpv-snapclass
driver: local.csi.openebs.io
deletionPolicy: Delete
EOF

Phase 5: Patch the CDI StorageProfile (KubeVirt)

If running OpenShift Virtualization, patch the StorageProfile to prevent CDI warnings:

oc patch storageprofile openebs-lvmpv --type=merge -p '{
  "spec": {
    "claimPropertySets": [
      {
        "accessModes": ["ReadWriteOnce"],
        "volumeMode": "Filesystem"
      },
      {
        "accessModes": ["ReadWriteOnce"],
        "volumeMode": "Block"
      }
    ]
  }
}'

Verify:

oc get storageprofile openebs-lvmpv -o yaml | grep -A 10 status

You should see cloneStrategy: snapshot auto-selected.


Phase 6: Verify

Create a test PVC and pod:

cat <<EOF | oc apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: lvm-test-pvc
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: openebs-lvmpv
  resources:
    requests:
      storage: 1Gi
EOF

cat <<EOF | oc apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: lvm-test-pod
  namespace: default
spec:
  containers:
    - name: busybox
      image: busybox
      command: ["sh", "-c", "while true; do echo hello >> /data/test.txt; sleep 5; done"]
      volumeMounts:
        - mountPath: /data
          name: lvm-vol
  volumes:
    - name: lvm-vol
      persistentVolumeClaim:
        claimName: lvm-test-pvc
EOF

Test a snapshot:

cat <<EOF | oc apply -f -
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: lvm-test-snap
  namespace: default
spec:
  volumeSnapshotClassName: openebs-lvmpv-snapclass
  source:
    persistentVolumeClaimName: lvm-test-pvc
EOF

oc get volumesnapshot lvm-test-snap -n default

READYTOUSE: true confirms snapshots are working.


Gotchas

Issue Cause Fix
Helm install fails with snapshot CRD conflict Rook-Ceph/OCP owns snapshot CRDs Add --set openebs-crds.csi.volumeSnapshots.enabled=false --set crds.csi.volumeSnapshots.enabled=false
Node daemonset pod pending (SCC) Missing privileged SCC Grant SCC to openebs-lvm-node-sa and openebs-lvm-controller-sa
Snapshot stuck READYTOUSE: false dm-snapshot kernel module not loaded modprobe dm-snapshot on host + MachineConfig for persistence
CDI StorageProfile incomplete warning CDI doesn't know StorageClass capabilities Patch StorageProfile with claimPropertySets
OpenEBS uses wrong thin pool Auto-creates lvmvg_thinpool instead of manual pool Check lvs after first PVC and use auto-created pool name in StorageClass