CSI addon bundle hardcodes the reference-instance driver/StorageClass name — provisioning silently never happens on other instances

Symptom (hit live on a try.whitesky.cloud cluster)

CSI driver installs fine (controller + node pods Running, StorageClasses present), but every PVC stays Pending forever — no CreateVolume, no error anywhere, pod stuck Pending. Extremely hard to diagnose because nothing logs a failure.

Root cause — driver-name mismatch

The shipped bundle (config/addons/csi/csi-driver.yaml) hardcodes StorageClasses and the CSIDriver object to the reference instance's name be.cloudbuilders.csi:

$ kubectl get storageclass
be.cloudbuilders.csi (default)         be.cloudbuilders.csi   ...
be.cloudbuilders.csi-physical          be.cloudbuilders.csi   ...
be.cloudbuilders.csi-encrypted-vault   be.cloudbuilders.csi   ...

But the actual driver on this instance advertises itself as cloud.whitesky.csi:

CSINode driver:        cloud.whitesky.csi  (topologyKeys=[cloud.whitesky/location])
provisioner sidecar:   "Detected CSI driver cloud.whitesky.csi"
attacher/node:         cloud.whitesky.csi
CSIDriver object:      be.cloudbuilders.csi  (cloud.whitesky.csi → NOT FOUND)

The external-provisioner only acts on StorageClasses whose provisioner == its driver name (cloud.whitesky.csi). The shipped classes say be.cloudbuilders.csi, so it silently ignores every PVC → never provisions, never errors.

The storage guide even acknowledges this — "the driver and class names are derived from your instance domain … yours will match your portal" — but the bundle hardcodes the reference name and substitutes nothing (unlike VCO_CSI_IMAGE, which is substituted). So the classes match the driver on exactly one instance (the reference one) and silently break on every other.

Worse, the name isn't guessable: be.cloudbuilders → be.cloudbuilders.csi, but try.whitesky.cloud → cloud.whitesky.csi (not try.whitesky.csi). An operator can't derive it — they have to read it out of CSINode.

Confirmed workaround

Create a StorageClass whose provisioner matches the real driver, and point PVCs at it:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata: {name: whitesky-csi}
provisioner: cloud.whitesky.csi
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true

(The reference StorageClass has no parameters, so a minimal class with the right provisioner name is sufficient.)

Fix (options, roughly in order of preference)

  1. Driver-side: have the CSI driver ship/create its own CSIDriver object + StorageClasses matching the name it actually advertises, and remove the static ones from our bundle. Then they always match, on any instance.
  2. Substitute the name in the bundle like VCO_CSI_IMAGE — e.g. a ${VCO_CSI_DRIVER_NAME} placeholder the operator sets. Weak, because the operator can't easily know the value (must read CSINode after install).
  3. Docs interim: storage guide must tell operators to read their driver name (kubectl get csinode -o jsonpath='{.items[0].spec.drivers[*].name}') and create a matching StorageClass — and warn that the shipped classes won't work off the reference instance.

Acceptance

Applying the CSI addon on any instance yields StorageClasses whose provisioner matches the running driver, so a PVC binds with no manual StorageClass surgery — and if it can't, it fails loudly rather than sitting Pending in silence.

Related: #13 (closed) (hardcoded instance-specific values), #20 (closed) (the PV walkthrough that surfaced this), #17 (closed)/#18 (closed) (e2e would catch a never-binding PVC).