Files

2.4 KiB

Storage certification

Why a certification is per-volume

Atomic rename, same-file-store guarantees, and symlink refusal are properties of a specific filesystem behind a specific mount — not of "Kubernetes" or "a PVC". Change the CSI driver, the StorageClass, the access mode, the backend, or the mount options and any of them can differ. A certification that does not name all five is not transferable.

What is certified

Property Why it matters
Same file store for staging and content A rename across stores is a copy, so publication stops being atomic.
Atomic rename The publish path's default strategy.
Atomic create (O_EXCL) Makes a publish create-only rather than a silent overwrite.
Symlink refusal Stops a replaced parent from redirecting a write outside the root.
Ranged read The download contract depends on it.

Running the certification

kubectl apply -f infra/fileserver/kubernetes/pvc-certification-job.yaml
kubectl logs job/fileserver-pvc-certification

The job writes a machine-readable result to the claim itself, carrying the full tuple:

{
  "kubernetesVersion": "...",
  "csiDriver": "...",
  "storageClass": "...",
  "accessMode": "ReadWriteOnce",
  "backend": "ext2/ext3",
  "mountOptions": "rw,relatime",
  "atomicMove": true,
  "sameFileStore": true,
  "atomicCreate": true
}

The job fails closed: a volume whose staging and content areas are on different stores is not certified, because its publish would silently degrade to a copy.

Network filesystems

docker compose -f infra/fileserver/nfs/compose.yml up -d
FILESERVER_NFS_TESTS=true ./gradlew :adapter:outbound:fileserver:test

The mount is hard, deliberately. A soft mount converts a slow server into a short write, which is exactly the corruption this design refuses to accept.

Startup enforcement

FileserverStartupValidator re-runs the probe at boot and refuses to accept traffic when a required capability is missing — ATOMIC_MOVE_REQUIRED on a filesystem that cannot prove an atomic move fails closed rather than degrading silently.

Adding a new store

Extend ContentStoreContract and pass it. A prose claim of compatibility is not accepted; the contract is executable precisely so a future object-storage adapter has to demonstrate the same offset, digest, and create-only behaviour the local store does.