Share:

CSI-driver

Native Kubernetes Storage on CloudStack: Inside the CSI Driver

Apache CloudStack has quietly become a serious Kubernetes host via CKS (CloudStack Kubernetes Service) and CAPC (Cluster API Provider CloudStack). But a Kubernetes cluster without persistent storage is a stateless toy: databases, message queues, and anything that needs to survive a pod restart need real, attachable, resizable disks.

That’s the gap the cloudstack-csi-driver closes. It is the plugin that lets Kubernetes talk to CloudStack’s storage layer using the standard Container Storage Interface (CSI), regardless of how the cluster itself was provisioned.

The driver’s only real requirements are CloudStack API credentials and a way to match Kubernetes node names to CloudStack VMs, either by name or via cloud-init/ignition instance metadata.

That’s why it works identically whether the cluster came from CKS, from CAPC, or was bootstrapped by hand. The Helm chart or manifest simply needs to be applied and pointed at a cloud-config secret. CKS happens to be the one place that performs this bootstrap automatically.
 

Where It Fits: CKS’s “Enable CSI Integration” Toggle

Starting in CloudStack 4.22.0, CKS includes native CSI integration, allowing CKS clusters to dynamically provision CloudStack volumes for Kubernetes pods without requiring a manual driver installation.

If you are using CAPC, you get the same driver and the same features, but you install the Helm chart yourself rather than having it configured automatically during cluster creation.

A few things are worth knowing about how the CKS path is wired up:

  • It’s baked into the data ISO: The CSI manifests and images ship inside the CKS Kubernetes data ISO itself. If you are running your own ISOs, you need to rebuild them with create-kubernetes-binaries-iso.sh to include the CSI manifests. Older ISOs will not contain them.
  • Pre-built ISOs are available: CloudStack publishes ready-to-use Kubernetes data ISOs with CSI already included at https://download.cloudstack.org/cks/, so in most cases there is no ISO-building step.
  • It’s an opt-in checkbox: In the Kubernetes cluster creation form, under Advanced Settings, there is an Enable CSI Integration checkbox. Enabling it triggers the CSI bootstrap during cluster creation.

When enabled, CloudStack injects a cloud-config secret containing the required API credentials and rolls out the full CSI stack onto the new cluster.

This includes:

  • A controller Deployment with two leader-elected replicas. It communicates with the CloudStack API to create, delete, attach, detach, expand, and snapshot volumes.
  • A node DaemonSet running on every worker node, responsible for formatting, mounting, and resizing disks on the host where the pod actually runs.

That is the entire “day 0” story for CKS.

From that point on, the driver is simply there, registered with kubelet and watching for PersistentVolumeClaims. Everything after that — which disk offerings to expose, which storage classes to define, and whether to enable snapshots — is controlled by the cluster operator, regardless of how the cluster was created.
 

The Shape of the Driver

Under the hood, this is a fairly textbook CSI plugin. The same Go binary runs in two modes — controller and node — or in all mode for a combined single-binary deployment.

  • Controller plugin (pkg/driver/controller.go): implements CreateVolume, DeleteVolume, ControllerPublishVolume/Unpublish, ControllerExpandVolume, and the snapshot RPCs. It is the only component that directly calls CloudStack operations such as createVolume, attachVolume, and createSnapshot.
  • Node plugin (pkg/driver/node.go): implements NodeStageVolume, NodePublishVolume, NodeExpandVolume, and NodeGetVolumeStats. This is where the block device is actually formatted and bind-mounted into the pod’s filesystem.

Both components are wired up behind the standard CSI sidecar containers, including:

  • external-provisioner
  • external-attacher
  • external-resizer
  • external-snapshotter
  • node-driver-registrar
  • livenessprobe

These components can be deployed through the Helm chart or manually.
 

Features That Actually Matter to a CloudStack Admin

 

Disk-Offering-Driven Storage Classes

A Kubernetes StorageClass maps directly to a CloudStack disk offering through the csi.cloudstack.apache.org/disk-offering-id parameter.

This means the performance tiers you have already defined in CloudStack — such as SSD-backed storage or custom IOPS offerings — become first-class Kubernetes storage classes.

You do not need to recreate your storage catalogue for Kubernetes. You expose the catalogue you already have.

One catch: the disk offering must be custom-sized and of type shared. This allows the driver to request the exact size specified by a PVC rather than relying on a fixed disk size.
 

Automatic Storage-Class Sync

Rather than manually writing a StorageClass YAML definition for every CloudStack disk offering, the bundled cloudstack-csi-sc-syncer can handle the process automatically.

The syncer can run as a Helm-managed Job or CronJob. It scans CloudStack disk offerings, filters them to compatible custom/shared offerings, and creates or removes matching Kubernetes storage classes.

In practical terms:

New disk offering in CloudStack → new storage class in Kubernetes.

No manual YAML update is required.
 

Zone-Aware, “Wait for the Pod” Provisioning

Storage classes use:

volumeBindingMode: WaitForFirstConsumer

This means a PersistentVolumeClaim is not bound to a disk until a pod has actually been scheduled.

The driver reports CSI topology segments based on the CloudStack zone ID, ensuring that the volume is created in the same zone where the pod is running.
 

Full Attach/Detach Lifecycle

CloudStack data disks can only be attached to one VM at a time, and the CSI driver models that behaviour correctly.

It advertises only the SINGLE_NODE_WRITER access mode.

The ControllerPublishVolume and ControllerUnpublishVolume operations are idempotent and also handle edge cases such as:

  • A volume already being attached to the requested node
  • A VM that no longer exists
  • A volume that has disappeared from CloudStack

Instead of leaking these situations into Kubernetes as persistent errors, the driver returns CSI-spec-compliant responses.
 

Online Volume Expansion

A PVC can be expanded by increasing its spec.resources.requests.storage value.

The CSI driver then handles the expansion in two stages:

  1. ControllerExpandVolume resizes the CloudStack volume.
  2. NodeExpandVolume grows the filesystem in place.

Supported filesystems include:

  • ext2
  • ext3
  • ext4
  • xfs

There is no pod restart required. For raw block volumes, the filesystem expansion step is skipped.
 

Volume Snapshots and Restore

With kvm.snapshot.enabled enabled in CloudStack KVM zones, the driver supports the full Kubernetes VolumeSnapshotClass and VolumeSnapshot workflow through the external snapshotter.

Supported operations include:

  • CreateSnapshot
  • ListSnapshots with pagination
  • DeleteSnapshot
  • Creating a new PVC directly from an existing snapshot

A restored volume is not attached until a pod actually claims it. This keeps the snapshot → restore → attach process lazy and topology-aware, just like fresh volume provisioning.
 

Configurable Reclaim Behaviour

Storage classes support both common Kubernetes reclaim policies:

  • Delete: the default behaviour. Deleting the PVC, or tearing down the CKS cluster, also removes the underlying CloudStack disk.
  • Retain: the underlying volume survives PVC or cluster deletion and can be recovered manually.

 

Multi-Tenant CloudStack Awareness

The driver configuration supports CloudStack:

  • Projects
  • Domains
  • Accounts

It uses the same cloud-config format as the CloudStack Kubernetes Provider.

If you are already running the CloudStack cloud-controller-manager, the same secret can therefore be reused.
 

Production-Grade Helm Defaults

The Helm deployment includes several production-focused defaults.

  • Controller pods use anti-affinity so they are spread across nodes.
  • Controllers are preferentially placed on control-plane nodes.
  • Sidecars use leader election.
  • Components use hardened securityContext settings including non-root execution, read-only root filesystems, and RuntimeDefault seccomp profiles.
  • The node DaemonSet runs with privileged: true because it needs to bind mount into the kubelet directory.
  • An optional Prometheus PodMonitor provides observability.

 

Cross-Hypervisor Ambition

KVM is currently the most tested path, particularly for snapshot functionality.

However, the driver has been designed to work across:

  • KVM
  • VMware
  • XenServer / XCP-ng

The implementation builds on the Apalia → Leaseweb → CloudStack community lineage and has been expanded to cover domains, projects, CKS, and CAPC.
 

The Division of Labour, Concretely

CKS (“Enable CSI Integration”) Does You Do After That
Creates the cloudstack-secret with API credentials Decide which disk offerings should be Kubernetes-visible
Deploys the CSI controller Deployment and node DaemonSet from the data ISO’s bundled manifests Create StorageClasses, or let the syncer create them
Registers the driver with kubelet on every node Set reclaimPolicy per class: Delete or Retain
Handles node ↔ VM identity matching using names or cloud-init/ignition metadata Apply VolumeSnapshotClass and related CRDs if you want snapshots
Runs the CSI sidecars, including provisioner, attacher, resizer, and registrar Write PVCs and use nodeSelector/nodeAffinity rather than nodeName, so Kubernetes remains in control of topology-aware scheduling

On CAPC, there is no automatic bootstrap step.

You install the chart yourself using helm install, or apply the necessary configuration with kubectl, and create the cloudstack-secret manually.

Everything after that works in the same way.
 

Why This Matters

Before CSI drivers such as this existed, persistent storage on CloudStack Kubernetes generally meant either NFS-backed volumes with no complete snapshot or resize workflow, or hand-written scripts calling the CloudStack API outside Kubernetes’ control loop.

The CSI driver changes that.

Combined with CKS’s one-click Enable CSI Integration bootstrap starting with CloudStack 4.22.0, or a self-service Helm installation on CAPC, the experience becomes much more seamless.

Operators can:

  • Declare a PersistentVolumeClaim and automatically receive a CloudStack disk
  • Resize volumes live
  • Create snapshots
  • Restore new volumes from snapshots
  • Control whether storage is deleted or retained when claims disappear

For CloudStack operators, this means the primary storage tiers already available in the environment can become a self-service Kubernetes storage catalogue with very little additional operational overhead.

And that remains true regardless of whether the Kubernetes cluster was created using CKS, CAPC, or another provisioning workflow.
 

Conclusion

The CloudStack CSI driver brings Kubernetes-native persistent storage management directly into the CloudStack ecosystem.

With dynamic provisioning, topology awareness, online expansion, snapshot support, automatic storage-class synchronisation, and integration with CloudStack’s existing disk offerings, Kubernetes workloads can consume CloudStack storage without requiring a separate storage management model.

For CKS users, much of the initial integration can now be enabled directly during cluster creation.

For CAPC and manually provisioned Kubernetes environments, the same CSI capabilities are available through the Helm deployment.

The result is a more integrated storage experience in which Kubernetes manages storage through its standard CSI workflows while CloudStack continues to provide the underlying infrastructure.

Share:

Related Posts:

ShapeBlue