Room 53
CSI DRIVER DEVELOPMENT
The Storage Architect
- The Container Storage Interface (CSI) is the standard for exposing storage to Kubernetes.
- Every PersistentVolume you use goes through a CSI driver. Now you’ll build one from scratch.
π Mission Briefing
- Understand the CSI architecture: Controller, Node, Identity services.
- Deploy the CSI hostpath driver components into your Kind cluster.
- Create a StorageClass that uses your CSI driver.
- Provision a PersistentVolumeClaim and mount it in a Pod.
- Write data to the volume and verify persistence across pod restarts.
- Inspect CSI driver registration and volume attachments.
- The password is revealed in the PV metadata annotation:
csi53vol.
Key Commands
| Command | Purpose |
|---|---|
kubectl get csidrivers |
List registered CSI drivers |
kubectl get csinodes |
CSI node info |
kubectl get sc |
List StorageClasses |
kubectl get pv,pvc |
List volumes and claims |
kubectl get volumeattachments |
Volume attachment status |
kubectl describe pvc <name> |
PVC provisioning details |
CSI Architecture Overview
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β Identity β β Controller β β Node β
β Service β β Service β β Service β
ββββββββββββββββ€ ββββββββββββββββ€ ββββββββββββββββ€
β GetPluginInfoβ β CreateVolume β β NodeStageVol β
β GetPluginCap β β DeleteVolume β β NodePublishV β
β Probe β β ControllerPubβ β NodeGetCap β
ββββββββββββββββ β ValidateVolCaβ β NodeGetInfo β
ββββββββββββββββ ββββββββββββββββ
Deploy the CSI HostPath Driver
# csi-hostpath-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-hostpath-sc
annotations:
password: "csi53vol"
provisioner: hostpath.csi.k8s.io
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true
# csi-hostpath-plugin.yaml - Simplified CSI HostPath DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: csi-hostpath-node
namespace: kube-system
spec:
selector:
matchLabels:
app: csi-hostpath
template:
metadata:
labels:
app: csi-hostpath
spec:
containers:
- name: node-driver-registrar
image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.9.0
args:
- "--csi-address=/csi/csi.sock"
- "--kubelet-registration-path=/var/lib/kubelet/plugins/hostpath.csi.k8s.io/csi.sock"
volumeMounts:
- name: plugin-dir
mountPath: /csi
- name: registration-dir
mountPath: /registration
- name: hostpath
image: registry.k8s.io/sig-storage/hostpathplugin:v1.12.0
args:
- "--v=5"
- "--endpoint=unix:///csi/csi.sock"
- "--nodeid=$(KUBE_NODE_NAME)"
env:
- name: KUBE_NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
securityContext:
privileged: true
volumeMounts:
- name: plugin-dir
mountPath: /csi
- name: pods-mount-dir
mountPath: /var/lib/kubelet/pods
mountPropagation: Bidirectional
volumes:
- name: plugin-dir
hostPath:
path: /var/lib/kubelet/plugins/hostpath.csi.k8s.io
type: DirectoryOrCreate
- name: pods-mount-dir
hostPath:
path: /var/lib/kubelet/pods
type: Directory
- name: registration-dir
hostPath:
path: /var/lib/kubelet/plugins_registry
type: Directory
Use the CSI Volume
# test-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: csi-hostpath-sc
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: csi-app
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "echo 'CSI works!' > /data/test.txt && cat /data/test.txt && sleep 3600"]
volumeMounts:
- name: my-volume
mountPath: /data
volumes:
- name: my-volume
persistentVolumeClaim:
claimName: csi-pvc
Inspect CSI Components
# Check CSI driver registration
kubectl get csidrivers
# NAME ATTACHREQUIRED PODINFOONMOUNT STORAGECAPACITY
# hostpath.csi.k8s.io true true false
# Check node plugin status
kubectl get csinodes -o yaml
# Check volume was provisioned
kubectl get pv
# NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM
# pvc-xxx 1Gi RWO Delete Bound default/csi-pvc
# See the StorageClass annotation for the password
kubectl get sc csi-hostpath-sc -o jsonpath='{.metadata.annotations.password}'
# Output: csi53vol
# Verify data persistence
kubectl delete pod csi-app
kubectl apply -f test-pvc.yaml # Re-create pod with same PVC
kubectl exec csi-app -- cat /data/test.txt
# Output: CSI works!
π‘ Hints
- CSI drivers have 3 gRPC services: Identity, Controller, and Node.
- The Controller service handles provisioning/deleting volumes at the cluster level.
- The Node service handles mounting/unmounting volumes on specific nodes.
volumeBindingMode: WaitForFirstConsumerdelays provisioning until a Pod needs the volume.- The password is in the StorageClass annotation - use
kubectl get sc -o yaml.
π Password
Check the StorageClass annotation:
kubectl get sc csi-hostpath-sc -o jsonpath='{.metadata.annotations.password}'