Deployment Guide
Deploying to production (Docker, Kubernetes, serverless)
This guide walks you through deploying the CSI Hostpath Driver to a Kubernetes cluster so you can provision local hostpath volumes and test CSI-based persistent storage workflows. The driver runs as a lightweight plugin built on Alpine Linux, exposing a CSI-compatible API that Kubernetes uses to create, attach, and manage volumes on a node. By the end of this guide, your cluster will have a functioning CSI driver ready to serve PersistentVolumeClaim requests. This is the recommended starting point before integrating the driver into any application-level storage workflow.
Before you begin, make sure you have the following in place:
- A running Kubernetes cluster — The CSI Hostpath Driver is deployed as a Kubernetes workload; you need
kubectlaccess to your cluster. kubectlCLI — Configured to communicate with your target cluster (kubectl versionshould return both client and server versions).- Docker or a compatible container runtime — Required if you intend to build the driver image locally from the
Dockerfile. - Sufficient node permissions — The driver mounts paths on the host node, so your cluster nodes must allow hostpath volume access. In most managed clusters this requires a permissive
PodSecurityPolicyor equivalent admission configuration. makeand a Go toolchain — Only required if you are building thehostpathpluginbinary from source using the providedMakefile. Pre-built images do not require this.
Step 1 — Build the driver binary (source builds only)
If you are using a pre-built container image, skip to Step 2.
From the root of the repository, run:
make all
This compiles the hostpathplugin binary and places it in the ./bin/ directory.
Step 2 — Build the container image
The Dockerfile copies the compiled binary into an Alpine-based image and sets it as the container entrypoint.
docker build -t csi-hostpathplugin:latest .
Verify the image was created:
docker images | grep csi-hostpathplugin
Expected output:
csi-hostpathplugin latest <image-id> <timestamp> <size>
Step 3 — Push the image to a registry accessible by your cluster
Tag the image for your registry and push it:
docker tag csi-hostpathplugin:latest <your-registry>/csi-hostpathplugin:latest
docker push <your-registry>/csi-hostpathplugin:latest
Replace <your-registry> with your actual container registry host (for example, registry.example.com/myproject).
Step 4 — Deploy the driver to Kubernetes
Apply the Kubernetes manifests that define the CSI driver DaemonSet, ServiceAccount, RBAC rules, and CSIDriver object. If you are using the manifests bundled with the repository:
kubectl apply -f deploy/kubernetes/
Step 5 — Confirm the driver pods are running
kubectl get pods -n kube-system -l app=csi-hostpathplugin
All pods should show Running status before you proceed.
The hostpathplugin binary is launched via the container ENTRYPOINT defined in the Dockerfile. You pass configuration to the driver through command-line flags or environment variables when you define the container spec in your Kubernetes manifests.
| Flag / Environment Variable | Default | Valid Values | Effect |
|---|---|---|---|
| (flag name) | (default) | (accepted values) | (what it controls) |
General guidance:
- Node ID — Typically required so the driver can register itself with the Kubernetes CSI node registrar. Set this to a value that uniquely identifies the node.
- Endpoint — The Unix domain socket path over which Kubernetes communicates with the CSI driver. This is passed in the container spec and must match the socket path used by the node-driver-registrar sidecar.
- Root directory — The host path under which the driver creates volume directories. Changing this affects where data is physically stored on the node.
Once the driver is deployed and its pods are running, you interact with it through the standard Kubernetes storage API — you do not call the driver's CSI gRPC endpoints directly. The common workflow is:
-
Create a
StorageClassthat references the CSI Hostpath Driver as the provisioner. This tells Kubernetes to routePersistentVolumeClaimrequests to the driver. -
Submit a
PersistentVolumeClaim(PVC) referencing thatStorageClass. Kubernetes calls the driver'sCreateVolumeCSI endpoint internally, and the driver provisions a directory on the node. -
Mount the PVC in a
Pod. When the pod is scheduled, Kubernetes calls the driver'sNodePublishVolumeendpoint, which bind-mounts the provisioned directory into the container. -
Verify the volume by writing and reading data inside the running container.
All of these steps use standard kubectl commands and Kubernetes manifest files — no driver-specific CLI tooling is required after deployment.
Example 1 — Create a StorageClass backed by the CSI Hostpath Driver
Save the following as storageclass.yaml and apply it:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-hostpath-sc
provisioner: hostpath.csi.k8s.io
reclaimPolicy: Delete
volumeBindingMode: Immediate
kubectl apply -f storageclass.yaml
Expected output:
storageclass.storage.k8s.io/csi-hostpath-sc created
Example 2 — Provision a PersistentVolumeClaim
Save the following as pvc.yaml:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-hostpath-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: csi-hostpath-sc
resources:
requests:
storage: 1Gi
kubectl apply -f pvc.yaml
Confirm the PVC is bound:
kubectl get pvc csi-hostpath-pvc
Expected output:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
csi-hostpath-pvc Bound pvc-<uid> 1Gi RWO csi-hostpath-sc 10s
Example 3 — Mount the volume in a Pod and verify it
Save the following as pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: csi-hostpath-demo
spec:
containers:
- name: demo
image: busybox
command: ["sh", "-c", "echo 'CSI Hostpath works!' > /data/test.txt && sleep 3600"]
volumeMounts:
- mountPath: /data
name: hostpath-vol
volumes:
- name: hostpath-vol
persistentVolumeClaim:
claimName: csi-hostpath-pvc
kubectl apply -f pod.yaml
kubectl wait --for=condition=Ready pod/csi-hostpath-demo --timeout=60s
kubectl exec csi-hostpath-demo -- cat /data/test.txt
Expected output:
CSI Hostpath works!
Use the consistent format below: Symptom → Likely cause → Fix.
PVC stays in Pending state indefinitely
- Symptom:
kubectl get pvcshowsSTATUS: Pendingafter several minutes. - Likely cause: The CSI driver pods are not running, or the
StorageClassprovisioner name does not match the driver's registered identity. - Fix: Run
kubectl get pods -n kube-system -l app=csi-hostpathpluginand check for crash loops or scheduling failures. Confirm theprovisionerfield in yourStorageClassexactly matches the name the driver registers with Kubernetes.
Driver pod is in CrashLoopBackOff
- Symptom:
kubectl get podsshows thecsi-hostpathpluginpod repeatedly restarting. - Likely cause: A required command-line flag is missing, the socket path is incorrect, or the container image is inaccessible from the node.
- Fix: Inspect logs with
kubectl logs <pod-name> -n kube-system. Verify the image reference in yourDaemonSetmanifest matches the image you pushed, and that nodes can pull from your registry.
Pod using the PVC fails to start with a MountVolume error
- Symptom:
kubectl describe pod <pod-name>shows an event likeMountVolume.SetUp failed. - Likely cause: The hostpath directory on the node does not exist, or the driver does not have permission to create it.
- Fix: Confirm the node's root directory used by the driver exists and is writable by the driver process. Check whether a
PodSecurityPolicy,PodSecurityAdmission, or SELinux/AppArmor policy is blocking hostpath mounts on the node.
docker build fails with no such file or directory: ./bin/hostpathplugin
- Symptom: Building the Docker image fails because the binary is missing.
- Likely cause: The
make allstep was skipped or failed silently. - Fix: Run
make allfrom the repository root before runningdocker build. Ensure your Go toolchain is installed and that$GOPATHis configured correctly.
kubectl apply -f deploy/kubernetes/ reports no objects passed to apply
- Symptom: The deploy command produces no output or an error about missing objects.
- Likely cause: The manifest directory path is incorrect for your local checkout.
- Fix: Verify the path to the manifest files with
ls deploy/kubernetes/and adjust the path in thekubectl applycommand accordingly.