Skip to main content

User guide: Machine storage

How to boot a Machine's disk from a PersistentVolumeClaim instead of a hand-placed image file on the node, and what today's real limits are.

The two ways to give a Machine a disk​

FieldWhat it meansNode-placement requirement
spec.image.path (default)A plain file path already present on the node the Machine is scheduled toAn operator/image pipeline has to put the file there first, and it must live under --image-root if the node enforces one
spec.volumes[0]The Machine boots from a file named disk.img inside the directory a Bound PersistentVolumeClaim resolves toThe bound PersistentVolume must already be a real, attach-ready directory on that node -- see limits below

spec.volumes[0] takes priority when set; spec.image.path is only used as a fallback when spec.volumes is empty. Both are creation-time-only, same as spec.resources/spec.network.forwards — changing them on an existing Machine has no effect.

apiVersion: kairon.zyvor.dev/v1alpha1
kind: Machine
metadata:
name: db
spec:
volumes:
- name: root
claimName: db-root-pvc
resources: {cpu: "2", memory: "4Gi"}
runtime: {backend: qemu}
powerState: Running

kairon-node resolves db-root-pvc → its status.phase == Bound check → spec.volumeName → the matching PersistentVolume → that PV's real host directory, and boots from <directory>/disk.img. If you're hand-provisioning storage for a test, that means placing (or copying) your qcow2/raw image at exactly <PersistentVolume path>/disk.img before the Machine reconciles.

Real limits today​

  • Boot volume: spec.volumes[0] is the boot disk (disk.img inside the PVC directory), same as before.
  • Additional volumes (spec.volumes[1+]): mapped as FluxVM virtiofs shared folders (QEMU only). Default guest mount is /mnt/<name> (override with guestPath). FluxVM has no multi-block-disk create API yet; this is the supported first cut — not a raw virtio-blk data disk.
  • Block-mode boot volumes. A Filesystem-mode PV boots from disk.img inside it; a Block-mode PV boots from the raw device itself (FluxVM opens it as the base image, format detected with qemu-img). For hostPath/local PVs the PV path must name the device (for example /dev/disk/by-id/...). For third-party CSI drivers kairon-node requests a Block volume capability and boots from the published device node. Kairon's own iSCSI driver serves Filesystem volumes only, and spec.volumes[1+] (virtiofs shares) still require Filesystem mode.
  • hostPath, local, or Kairon's own CSI-backed volume sources. hostPath/local already name a real, present-today directory on a specific node, resolved directly, no attach/mount step. A csi-backed PV is also resolvable now, but only when it names Kairon's own first-cut network-block (iSCSI) driver (csi.kairon.zyvor.dev) — see docs/guides/machine-storage-csi.md for setup, and note this needs csiNode.enabled in the Helm chart plus kairon-node's own --csi-socket flag pointed at it, neither of which is on by default. A PV naming any other CSI driver is still refused — Kairon only ever attaches/mounts network storage through its own driver, never an arbitrary third-party one (unless listed in node.thirdPartyCSIDrivers).
  • The PVC must already be Bound. A Pending claim fails reconcile with a clear "not Bound yet" error rather than retrying silently forever — check kubectl get pvc if a Machine referencing one gets stuck.
  • The PVC-resolved path is exempt from --image-root. That allowlist exists to fence an arbitrary string in spec.image.path; a PVC name has already gone through a stronger gate (the claim had to exist and be bound by the cluster's own storage machinery), so the same node-local directory restriction doesn't apply to it.
apiVersion: kairon.zyvor.dev/v1alpha1
kind: Machine
metadata:
name: db
spec:
volumes:
- name: root
claimName: db-root-pvc
- name: data
claimName: db-data-pvc
guestPath: /var/lib/postgresql/data # virtiofs inside guest
resources: {cpu: "2", memory: "4Gi"}
runtime: {backend: qemu}
powerState: Running

What this unlocks vs. what's still missing​

This closes the gap between "Machines only boot from files an operator manually placed on a specific node" and "Machines can boot from Kubernetes storage" — for local/directory-backed storage classes (e.g. Rancher's local-path-provisioner) directly, and for real network-block storage via Kairon's own first-cut iSCSI CSI driver — see docs/guides/machine-storage-csi.md. It does not yet provide: snapshot restore or clone-from-snapshot into a new Machine (MachineSnapshot is still create-only — see architecture.md), CPU/memory hotplug via this path, or support for any network-block backend other than iSCSI (Ceph RBD/EBS/etc. would each need their own driver backend, not just config).