Skip to content

Container Storage Interface (CSI)

How does Kubernetes talk to my specific storage vendor?

Historically, Kubernetes integrated storage solutions by building them directly into the core codebase. These "in-tree" volume plugins meant that adding support for a new storage vendor (or fixing a bug in an existing one) required checking code directly into the Kubernetes repository and waiting for the next official Kubernetes release cycle.

To solve this scaling bottleneck, Kubernetes adopted the Container Storage Interface (CSI). CSI defines a standard, out-of-tree interface for container orchestrators to expose arbitrary storage systems to their workloads. This extensibility model allows storage vendors—such as AWS (ebs.csi.aws.com), Azure (disk.csi.azure.com), and Portworx (pxd.portworx.com)—to develop, release, and install their plugins entirely independently of the core Kubernetes binaries.

Here is how the Kubernetes control plane communicates with these independent storage vendors without knowing any of their underlying APIs.

The CSI Architecture and gRPC

Kubernetes does not communicate with the storage vendor's proprietary API directly. Instead, the storage vendor provides a CSI driver, which is typically deployed into the Kubernetes cluster as a combination of Deployment (or StatefulSet) for control-plane tasks and a DaemonSet for node-level tasks.

The CSI driver exposes a standardized set of gRPC endpoints. The Kubernetes system interacts with the driver by making gRPC calls to these endpoints (such as ControllerPublishVolume or NodePublishVolume).

The Sidecar Pattern: Bridging the Kubernetes API and CSI

To keep the core Kubernetes control plane lightweight and unaware of CSI-specifics, the communication between the Kubernetes API server and the vendor's CSI driver is brokered by a set of standardized, community-managed sidecar containers.

These sidecars run in the same Pod as the vendor's CSI driver. They actively watch the Kubernetes API for specific object changes and translate those declarative API objects into imperative gRPC commands sent to the vendor's driver over a local UNIX domain socket.

1. The external-provisioner Sidecar

When a user creates a PersistentVolumeClaim (PVC) requesting dynamically provisioned storage, the Kubernetes API simply stores the object. The external-provisioner sidecar watches the API for new PVCs.

  • How it works: When it sees a PVC that references a StorageClass belonging to its associated CSI driver, the external-provisioner intercepts the request. It extracts the parameters from the StorageClass and makes a gRPC CreateVolume call to the vendor's CSI driver.
  • Once the vendor driver successfully creates the physical storage (e.g., provisions an EBS volume in AWS), the external-provisioner creates the corresponding PersistentVolume (PV) object in the Kubernetes API to bind with the PVC.

2. The external-attacher Sidecar

Creating a volume is different from attaching it to a specific virtual machine or physical node. When the Kubernetes scheduler places a Pod onto a Node, the core Kubernetes attach/detach controller recognizes that a volume must be attached to that specific Node. However, it does not talk to the storage vendor directly. Instead, it creates a VolumeAttachment object in the Kubernetes API.

  • How it works: The external-attacher sidecar continuously watches for new VolumeAttachment objects.
  • When it detects one, it makes a gRPC ControllerPublishVolume call to the vendor's CSI driver, instructing it to attach the physical volume to the underlying infrastructure node.
  • Once the vendor's driver confirms the operation is complete, the external-attacher updates the VolumeAttachment status in Kubernetes to attached: true. Only then does the kubelet proceed to mount the volume into the Pod.

Other Critical CSI Sidecars

The CSI extensibility model utilizes several other specialized sidecars following this exact same pattern:

  • external-resizer: Watches for modifications to PVC capacity or VolumeAttributesClass objects and makes gRPC calls to expand or modify the physical volume dynamically.
  • csi-snapshotter: Watches for VolumeSnapshot and VolumeSnapshotContent objects created by users and triggers CreateSnapshot or DeleteSnapshot gRPC operations against the vendor's CSI endpoint.
  • node-driver-registrar: Runs on every worker node alongside the node-level CSI driver, automatically populating the CSINode object in the Kubernetes API to inform the kubelet that the CSI driver is successfully installed and available on that specific host.

Based on Kubernetes v1.35 (Timbernetes). Changelog.