The CSI controller plugin — Create, Delete, Attach, Snapshot, Expand
What you'll learn
- Describe the controller plugin's responsibilities in detail
- Identify the gRPC operations: CreateVolume, DeleteVolume, ControllerPublishVolume, CreateSnapshot, ControllerExpandVolume
- Explain the deployment topology (Deployment with leader election)
- Apply the production pattern for controller plugin HA
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
The CSI controller plugin is the cluster-wide operator that creates, deletes, attaches, snapshots, and expands volumes. This lesson walks the operations, the deployment topology, and the production discipline.
Controller plugin responsibilities
The controller plugin implements the CSI Controller Service:
| Operation | Purpose | When called |
|---|---|---|
| CreateVolume | Create a volume on the backend | When a PVC is bound (dynamic provisioning) |
| DeleteVolume | Delete a volume on the backend | When a PV is reclaimed (Delete policy) |
| ControllerPublishVolume | Attach a volume to a node | When a Pod is scheduled to a node |
| ControllerUnpublishVolume | Detach a volume from a node | When a Pod is removed from a node |
| CreateSnapshot | Create a snapshot | When a VolumeSnapshot is created |
| DeleteSnapshot | Delete a snapshot | When a VolumeSnapshot is deleted |
| ControllerExpandVolume | Expand a volume | When a PVC’s capacity request is increased |
| ValidateVolumeCapabilities | Check if a volume supports the requested capabilities | When the kubelet queries |
sequenceDiagram
participant CM as Controller manager
participant CP as Controller plugin
participant BE as Backend
Note over CM,CP: Provisioning
CM->>CP: CreateVolume (name, capacity, params)
CP->>BE: create volume
BE-->>CP: volumeHandle
CP-->>CM: PV created
Note over CM,CP: Attaching
CM->>CP: ControllerPublishVolume (volumeHandle, nodeId)
CP->>BE: attach volume to node
BE-->>CP: attached
CP-->>CM: publishInfo (devicePath)
Note over CM,CP: Snapshotting
CM->>CP: CreateSnapshot (volumeHandle, snapshotId)
CP->>BE: create snapshot
BE-->>CP: snapshotId
CP-->>CM: snapshot created
Note over CM,CP: Expanding
CM->>CP: ControllerExpandVolume (volumeHandle, newSize)
CP->>BE: expand volume
BE-->>CP: expanded
CP-->>CM: expansion confirmed
The CreateVolume operation
CreateVolume is the operation that creates a volume on the backend. The request includes:
message CreateVolumeRequest {
string name = 1; // PVC name (used for idempotency)
CapacityRange capacity_range = 2; // min and max capacity
map<string, string> parameters = 3; // StorageClass parameters
VolumeCapabilities volume_capabilities = 4; // access mode, fsType
map<string, string> secrets = 5; // credentials
Topology topology_requirement = 6; // topology constraints
}
The controller plugin:
- Validates the parameters against the backend’s capabilities.
- Calls the backend’s API to create the volume (e.g., EBS CreateVolume, Ceph RBD create).
- Returns the
volumeHandle(a backend-specific identifier) to the kube-controller-manager.
The operation is idempotent: calling CreateVolume with the same name returns the same volumeHandle.
The ControllerPublishVolume operation
ControllerPublishVolume attaches the volume to a node (for cloud-block storage). The request includes:
message ControllerPublishVolumeRequest {
string volume_handle = 1;
string node_id = 2;
VolumeCapability volume_capability = 3;
bool readonly = 4;
map<string, string> secrets = 5;
}
The controller plugin calls the backend to attach the volume to the node:
- EBS:
ec2:AttachVolumeAPI call. - GCE PD:
disks.attachAPI call. - Ceph RBD: map the RBD image to the node.
The operation returns a publishInfo (the device path
on the node) that the kubelet uses for mount.
The CreateSnapshot operation
CreateSnapshot creates a snapshot of an existing volume. The request includes:
message CreateSnapshotRequest {
string name = 1; // VolumeSnapshot name (idempotency)
string source_volume_handle = 2;
map<string, string> parameters = 3;
map<string, string> secrets = 4;
}
The controller plugin calls the backend to create the snapshot:
- EBS:
ec2:CreateSnapshotAPI call. - Ceph RBD:
rbd snap createcommand. - NFS: depends on the implementation (not all NFS backends support snapshots).
The operation is idempotent: calling CreateSnapshot with the same name returns the same snapshot.
The ControllerExpandVolume operation
ControllerExpandVolume expands a volume’s capacity. The request includes:
message ControllerExpandVolumeRequest {
string volume_handle = 1;
int64 capacity_range = 2;
string node_id = 3; // for online resize coordination
}
The controller plugin calls the backend to expand the volume. After the backend confirms the expansion, the kubelet resizes the filesystem.
Deployment topology
The controller plugin is a Deployment with leader election:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ebs-csi-controller
namespace: kube-system
spec:
replicas: 2 # HA: one active, one standby
template:
spec:
containers:
- name: ebs-csi-controller
image: amazon/aws-ebs-csi-driver:latest
args:
- --leader-election=true
- --leader-election-namespace=kube-system
With leader election:
- One replica is the leader; it processes all CSI operations.
- Other replicas are standby; they watch for leader health.
- If the leader fails, a standby takes over.
The external sidecar pattern
For CSI drivers, the controller-manager-side operations (CreatVolume, etc.) are typically implemented in a sidecar container that runs alongside the actual driver:
flowchart LR
A[kube-controller-manager] -->|gRPC| B[External sidecar<br/>csi-provisioner]
B -->|gRPC| C[CSI driver container]
C --> D[Storage backend]
The external sidecar (e.g., csi-provisioner from the
Kubernetes CSI external-provisioner project) handles the
watching of PVCs and the calling of the CSI driver. The
driver container implements the CSI specification.
This pattern is widely used because it separates concerns: the sidecar handles Kubernetes-specific watching logic; the driver implements the CSI spec.
Quiz
Knowledge check · 4 questions
Q1. Which CSI operation is responsible for creating a snapshot of a volume?
Q2. The CSI controller plugin should be deployed with at least 2 replicas with leader election for HA.
Q3. Your team observes that CreateSnapshot operations are failing with `DeadlineExceeded`. Walk through the diagnostic.
VolumeSnapshot creation has been failing for 30 minutes. The CSI controller plugin is running. Existing volumes are functioning. The error is `DeadlineExceeded` (gRPC code 4).
Q4. Explain why the CSI controller plugin is deployed with leader election and what the HA pattern is.
Passing score: 75%. Answers are checked in this browser.
Production discipline
- At least 2 controller plugin replicas with leader election. A single replica is a SPOF.
- Monitor controller plugin latency and error rate. The controller is on the critical path for PVC provisioning.
- Test every CSI operation the workload uses. Provision, attach, mount, snapshot, expand, delete.
- Configure appropriate rate limits. Some CSI drivers have internal rate limits to avoid backend throttling.
- Document the controller’s deployment in the cluster bootstrap. HA, scaling, monitoring.