Skip to main content
Every Proxmox VE cluster Ankra builds ships with a CSI driver, so a PersistentVolumeClaim gets a real virtual disk on your Proxmox storage. That disk is attached to the VM that runs the pod. There is no extra install and no extra credential: the driver uses the same Proxmox API token the cluster was built with. That token needs Datastore.Audit on top of what provisioning uses - see Proxmox VE Credentials.

What Ankra installs

The proxmox-csi Stack on each cluster holds: When the cluster’s disks span more than one Proxmox storage, each further storage gets its own class, named proxmox-csi-<storage>. The driver reaches the Proxmox API from inside the cluster at the credential’s API URL. If that address is not reachable from the cluster’s VMs, for example on a routed SDN where guest traffic is SNATed, create the credential through the API with internal_api_url set to an address the VMs can reach. The driver then uses that address and Ankra keeps using api_url.

Use a volume

An unqualified claim lands on the default class:
Ship it as a manifest in one of the cluster’s Stacks, like any other resource. See Stacks. The claim stays Pending until a pod uses it, because the class binds with WaitForFirstConsumer: a Proxmox disk is created on one host, so Kubernetes first picks the node, then the driver creates the disk on that node’s host. Volumes are ReadWriteOnce disks attached to one VM at a time, as an extra SCSI disk on the VM (scsi1, scsi2, …). On directory storage such as local each volume is a raw image file; on LVM-thin, ZFS or Ceph it is a volume of that storage.

How volumes follow Proxmox hosts

Ankra labels every node with:
  • topology.kubernetes.io/region: proxmox, the name the driver uses for the Proxmox installation
  • topology.kubernetes.io/zone: <proxmox host>, the host the VM runs on
It also registers each node with the providerID proxmox://proxmox/<vmid>, which is how the driver finds the VM to attach a disk to. On a single-host cluster this is invisible. On a host-spread cluster a volume on local storage belongs to one host, so a pod that uses it can only run on a node on that host. Kubernetes enforces this through the zone label. Use shared storage (Ceph RBD, for example) when a stateful pod must be able to move between hosts.

Clusters created before the fix

Before 30 October 2026, Ankra set neither the topology labels nor the providerID on nodes of kubeadm Proxmox clusters, and pointed the driver at the bare API address instead of /api2/json. On those clusters the node plugin restarts endlessly, and every claim stays Pending:
To repair such a cluster:
  1. Add Datastore.Audit to the role of the cluster’s Proxmox token (pveum role modify <role> --append 1 --privs Datastore.Audit on the Proxmox host).
  2. Let Ankra correct the API address in the proxmox-csi-plugin-config Secret. It does so on the next reconcile, and restarts the controller when the Secret changes.
  3. Replace the worker nodes. A node’s providerID cannot change once it has registered, so existing nodes cannot be repaired in place, and new nodes get the labels and the providerID:
Control-plane nodes carry the control-plane taint, which the node plugin does not tolerate, so no node plugin runs there and they can stay as they are. If you removed that taint to run workloads on them, recreate the cluster instead.

Troubleshooting