CSI Architecture
Kubernetes core runs no storage vendor driver of its own, so how does an EBS or Ceph disk get mounted? A CSI driver typically ships in two halves: the controller plugin runs as a Deployment or StatefulSet whose sidecars each watch one kind of object and turn it into gRPC calls, and the node plugin is a DaemonSet that registers with Kubelet. Only the node plugin mounts a filesystem volume for a Pod, and the runtime just binds that mount into the container.
Play the animation 6 steps, animated, best on a wide screen
CSI Architecture, step by step
-
The control plane deals only in objects: a PVC, a PersistentVolume, a VolumeAttachment. It has no idea how any particular disk is made or attached. That deliberate ignorance is what lets one Kubernetes talk to dozens of storage backends it was never taught about.
Play from step 1 -
The controller plugin runs as a Deployment or a StatefulSet, with the sidecars its driver uses, optional but recommended. Each watches one kind of object: provisioner for claims, attacher for attachments, resizer for resizes, snapshotter for snapshots. All of them call one driver.
Play from step 2 -
Follow one sidecar. The external-provisioner picks up a Pending PVC whose storage-provisioner annotation, set by the binding controller, names its driver, and turns it into a gRPC call, CreateVolume. The driver, not the sidecar, speaks to the cloud API and asks it for a real disk.
Play from step 3 -
The other half is the node plugin, a DaemonSet, so a copy runs on every eligible Node. Its node-driver-registrar sidecar leaves a socket where Kubelet looks for plugins, and answers Kubelet with the driver name and socket path. Kubelet then sends mount requests for this driver to this plugin.
Play from step 4 -
Kubelet never mounts a vendor filesystem itself: it calls NodePublishVolume, after NodeStageVolume if the driver stages, and only the node plugin mounts it for a Pod. The runtime just binds that mount into the container. The controller makes no mount a Pod uses. The app writes through it.
Play from step 5 -
So on the controller side the sidecars are the bridge. The control plane writes plain objects and runs no vendor driver. The sidecars translate the objects into gRPC calls, the driver runs them, and the node plugin does the privileged work, like the mount. Swap the driver, keep the objects.
Play from step 6