Guide

Deployment Guide

Deploying to production (Docker, Kubernetes, serverless)


Overview

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.


Prerequisites

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 kubectl access to your cluster.
  • kubectl CLI — Configured to communicate with your target cluster (kubectl version should 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 PodSecurityPolicy or equivalent admission configuration.
  • make and a Go toolchain — Only required if you are building the hostpathplugin binary from source using the provided Makefile. Pre-built images do not require this.

Installation

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.


Configuration

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 VariableDefaultValid ValuesEffect
(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.

Usage

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:

  1. Create a StorageClass that references the CSI Hostpath Driver as the provisioner. This tells Kubernetes to route PersistentVolumeClaim requests to the driver.

  2. Submit a PersistentVolumeClaim (PVC) referencing that StorageClass. Kubernetes calls the driver's CreateVolume CSI endpoint internally, and the driver provisions a directory on the node.

  3. Mount the PVC in a Pod. When the pod is scheduled, Kubernetes calls the driver's NodePublishVolume endpoint, which bind-mounts the provisioned directory into the container.

  4. 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.


Examples

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!

Troubleshooting

Use the consistent format below: Symptom → Likely cause → Fix.


PVC stays in Pending state indefinitely

  • Symptom: kubectl get pvc shows STATUS: Pending after several minutes.
  • Likely cause: The CSI driver pods are not running, or the StorageClass provisioner name does not match the driver's registered identity.
  • Fix: Run kubectl get pods -n kube-system -l app=csi-hostpathplugin and check for crash loops or scheduling failures. Confirm the provisioner field in your StorageClass exactly matches the name the driver registers with Kubernetes.

Driver pod is in CrashLoopBackOff

  • Symptom: kubectl get pods shows the csi-hostpathplugin pod 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 your DaemonSet manifest 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 like MountVolume.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 all step was skipped or failed silently.
  • Fix: Run make all from the repository root before running docker build. Ensure your Go toolchain is installed and that $GOPATH is 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 the kubectl apply command accordingly.