Skip to main content
RunBook Academy

KubernetesLII · CSICSI

CSI overview — the Container Storage Interface standard and its lifecycle

Advanced⏱ ~17 minkubectl

What you'll learn

  • Describe the CSI standard and its gRPC-based interface
  • Distinguish the controller plugin from the node plugin
  • Trace the CSI operation lifecycle (Provision, Attach, Mount, Format, Snapshot)
  • Explain why CSI replaced the in-tree storage plugins

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

The Container Storage Interface (CSI) is the standard that lets any storage vendor implement a Kubernetes driver without modifying Kubernetes itself. This lesson walks the CSI architecture, the gRPC interface, and the lifecycle operations.

What CSI is

CSI is a specification for a gRPC-based interface between Kubernetes and storage drivers. Before CSI, storage drivers were compiled into Kubernetes (in-tree plugins: kubernetes.io/aws-ebs, kubernetes.io/gce-pd, etc.). With CSI, drivers are out-of-tree: they run as separate Pods in the cluster, communicating with Kubernetes via gRPC.

flowchart TB
    A[kubelet] -->|gRPC| B[CSI node plugin]
    C[kube-controller-manager] -->|gRPC| D[CSI controller plugin]
    B --> E[Storage backend]
    D --> E

The benefits of CSI over in-tree:

  • Independent driver evolution: vendors release drivers on their own schedule, not Kubernetes’s.
  • No Kubernetes recompilation: drivers are not part of the Kubernetes binary.
  • Standard interface: any vendor can implement CSI; any Kubernetes cluster can use any CSI driver.

The gRPC interface

CSI uses gRPC (Google Remote Procedure Call) for communication. The CSI specification defines three services:

  • Identity Service: returns the driver’s name, version, and capabilities.
  • Controller Service: cluster-wide operations (CreateVolume, DeleteVolume, ControllerPublishVolume, CreateSnapshot).
  • Node Service: per-node operations (NodeStageVolume, NodePublishVolume).
service Controller {
  rpc CreateVolume(CreateVolumeRequest) returns (CreateVolumeResponse);
  rpc DeleteVolume(DeleteVolumeRequest) returns (DeleteVolumeResponse);
  rpc ControllerPublishVolume(ControllerPublishVolumeRequest) returns (ControllerPublishVolumeResponse);
  rpc ControllerUnpublishVolume(ControllerUnpublishVolumeRequest) returns (ControllerUnpublishVolumeResponse);
  rpc ValidateVolumeCapabilities(ValidateVolumeCapabilitiesRequest) returns (ValidateVolumeCapabilitiesResponse);
  rpc ListVolumes(ListVolumesRequest) returns (ListVolumesResponse);
  rpc GetCapacity(GetCapacityRequest) returns (GetCapacityResponse);
  rpc CreateSnapshot(CreateSnapshotRequest) returns (CreateSnapshotResponse);
  rpc DeleteSnapshot(DeleteSnapshotRequest) returns (DeleteSnapshotResponse);
  rpc ListSnapshots(ListSnapshotsRequest) returns (ListSnapshotsResponse);
  rpc ControllerExpandVolume(ControllerExpandVolumeRequest) returns (ControllerExpandVolumeResponse);
  rpc ControllerGetVolume(ControllerGetVolumeRequest) returns (ControllerGetVolumeResponse);
}

service Node {
  rpc NodeStageVolume(NodeStageVolumeRequest) returns (NodeStageVolumeResponse);
  rpc NodeUnstageVolume(NodeUnstageVolumeRequest) returns (NodeUnstageVolumeResponse);
  rpc NodePublishVolume(NodePublishVolumeRequest) returns (NodePublishVolumeResponse);
  rpc NodeUnpublishVolume(NodeUnpublishVolumeRequest) returns (NodeUnpublishVolumeResponse);
  rpc NodeGetVolumeStats(NodeGetVolumeStatsRequest) returns (NodeGetVolumeStatsResponse);
  rpc NodeExpandVolume(NodeExpandVolumeRequest) returns (NodeExpandVolumeResponse);
  rpc NodeGetCapabilities(NodeGetCapabilitiesRequest) returns (NodeGetCapabilitiesResponse);
  rpc NodeGetInfo(NodeGetInfoRequest) returns (NodeGetInfoResponse);
}

Each RPC takes a request and returns a response. Errors are returned with gRPC status codes; the kubelet and the controller manager interpret the codes.

The controller plugin

The controller plugin runs the Controller Service. It is implemented as a Deployment or StatefulSet, typically in kube-system:

# The controller plugin for EBS CSI
kubectl -n kube-system get deploy ebs-csi-controller

The controller plugin is a singleton (one active replica, with standby replicas for HA). It runs the cluster-wide operations: create, delete, attach, snapshot, expand.

The node plugin

The node plugin runs the Node Service. It is implemented as a DaemonSet, one Pod per node:

# The node plugin for EBS CSI
kubectl -n kube-system get ds ebs-csi-node

The node plugin runs the per-node operations: stage, publish, unstage, unpublish, expand.

The lifecycle

A volume’s CSI lifecycle:

sequenceDiagram
    participant U as User
    participant API as API server
    participant CM as Controller manager
    participant CP as CSI controller plugin
    participant BE as Storage backend
    participant K as kubelet
    participant NP as CSI node plugin
    Note over U,API: Provisioning
    U->>API: submit PVC
    API->>CM: PVC needs PV
    CM->>CP: CreateVolume (name, capacity, params)
    CP->>BE: create backend storage
    BE-->>CP: volumeHandle
    CP-->>CM: PV created
    Note over K,NP: Attaching and mounting
    K->>NP: NodeStageVolume (volumeHandle, stagingPath)
    NP->>BE: format and mount to stagingPath
    K->>NP: NodePublishVolume (stagingPath, targetPath)
    NP-->>K: bind-mount to Pod
    Note over U,API: Deletion (reversed)
    U->>API: delete PVC
    API->>CM: PV to be reclaimed
    K->>NP: NodeUnpublishVolume
    K->>NP: NodeUnstageVolume
    CM->>CP: DeleteVolume
    CP->>BE: delete backend storage

The phases:

  1. Provisioning: CSI controller creates the volume (CreateVolume).
  2. Attaching: CSI controller attaches the volume to the node (ControllerPublishVolume, for cloud-block).
  3. Staging: CSI node plugin formats (if needed) and mounts to the staging path (NodeStageVolume).
  4. Publishing: CSI node plugin bind-mounts to the Pod (NodePublishVolume).
  5. Deletion (reversed): unpublish, unstage, detach, delete.

Quiz

Knowledge check · 4 questions

  1. Q1. What is the primary benefit of CSI over the legacy in-tree storage plugins?

  2. Q2. The CSI controller plugin and the CSI node plugin are separate because they have different scopes (cluster-wide vs per-node).

  3. Q3. Your team is evaluating a new CSI driver for a storage backend. Walk through the validation steps.

    Vendor provides a CSI driver for a new storage backend. The team needs to validate that the driver is functional, supports the required operations, and integrates with Kubernetes.

  4. Q4. Explain why the CSI controller plugin and the CSI node plugin are separate, and what each is responsible for.

Passing score: 75%. Answers are checked in this browser.

Production discipline

  • Every storage driver is CSI in Kubernetes 1.34. The in-tree plugins are removed.
  • The controller plugin is a SLO dependency. Its latency and reliability affect every PVC on its StorageClass.
  • The node plugin runs on every node. A node plugin failure blocks volume mounts on the affected node.
  • CSI drivers are validated via the conformance suite. Adopters run the suite; production validation tests every operation the workload uses.
  • gRPC is the wire protocol. Errors are gRPC status codes; kubelet and controller manager interpret them.