✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Kubernetes Storage Architecture

Kubernetes Storage Architecture explains how storage systems integrate with Kubernetes to provide persistent, scalable, and secure storage for containerized apps.

Kubernetes Storage Architecture is the internal structure of how a Container Storage Interface (CSI) driver is actually deployed and coordinated across a cluster: a split between a controller plugin, running centrally and responsible for provisioning and attaching volumes, and a node plugin, running on every node and responsible for mounting already-attached volumes into individual Pods, together with the standard set of sidecar containers that bridge each plugin to the Kubernetes API. Where storage abstractions describe PersistentVolumes and PersistentVolumeClaims as API objects, storage architecture describes the running processes and coordination that make those objects actually result in mounted, usable filesystems.


Controller Plugin

Central, Cluster-Scoped Responsibility

The CSI controller plugin formally runs as a small number of replicas, typically as a Deployment or StatefulSet, and is responsible for cluster-scoped storage operations that do not need to run on every node: provisioning new volumes, deleting volumes, and attaching or detaching volumes from a node at the storage backend's API level.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: codartium-csi-controller
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: csi-provisioner
        - name: csi-attacher
        - name: codartium-csi-driver
controller plugin : provision, delete, attach, detach

Sidecar Containers

The controller plugin's Pod formally bundles the driver's own container alongside a set of standardized, community-maintained sidecar containers, external-provisioner, which watches PersistentVolumeClaims and calls the driver's CreateVolume RPC; external-attacher, which watches VolumeAttachment objects and calls the driver's ControllerPublishVolume RPC; and external-snapshotter, for snapshot support where implemented.


Node Plugin

Per-Node Responsibility

The CSI node plugin formally runs as a DaemonSet, ensuring exactly one instance per node, responsible for the node-local operations that must happen on the specific machine where a Pod is scheduled: staging a volume (making it available on the node) and publishing it (bind-mounting it into a specific Pod's location).

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: codartium-csi-node
spec:
  template:
    spec:
      containers:
        - name: csi-node-driver-registrar
        - name: codartium-csi-driver
node plugin : stage, publish, unpublish, unstage

Driver Registration

The node plugin's node-driver-registrar sidecar formally registers the driver with the kubelet on that node via the kubelet's plugin registration mechanism, informing the kubelet which Unix domain socket to use when issuing CSI RPCs for volumes handled by this driver.

ls /var/lib/kubelet/plugins_registry/

The Volume Lifecycle Across Components

Provisioning to Attachment

A volume's formal lifecycle begins when a PersistentVolumeClaim triggers the external-provisioner sidecar to call the driver's CreateVolume RPC, resulting in a new PersistentVolume object; once a Pod referencing that claim is scheduled, the external-attacher sidecar calls ControllerPublishVolume to attach the volume to the target node at the infrastructure level.

PVC CreateVolume PV ControllerPublishVolume attached to node

Staging to Publishing

Once attached, the kubelet on the target node formally calls the node plugin's NodeStageVolume RPC, making the volume available at a staging path on the node, followed by NodePublishVolume, bind-mounting it into the specific path the Pod's container expects, completing the chain from claim to mounted filesystem.

attached NodeStageVolume NodePublishVolume mounted in pod
kubectl get volumeattachments
kubectl describe pv codartium-data-pv

VolumeAttachment as the Coordination Object

An Intermediate API Object

A VolumeAttachment object formally represents the intent and result of attaching a specific volume to a specific node, serving as the coordination point between the controller plugin's attacher sidecar and the eventual node-level operations, itself observable and inspectable through the standard API like any other object.

apiVersion: storage.k8s.io/v1
kind: VolumeAttachment
metadata:
  name: csi-abc123
spec:
  attacher: codartium.io/csi-driver
  nodeName: worker-node-3
  source:
    persistentVolumeName: codartium-data-pv

Why Storage Is Architecturally Split This Way

Separating controller and node responsibilities into distinct, independently scaled components, one centralized, one distributed per node, mirrors the natural division in the underlying operations themselves: provisioning and attachment are cluster-wide, infrastructure-level actions best handled centrally, while staging and mounting are inherently node-local actions that must happen on the specific machine where a Pod actually runs, and this architecture lets each responsibility be implemented, scaled, and reasoned about according to its own actual scope.