| title | Node Max Volume Count Exceeded | |||||
|---|---|---|---|---|---|---|
| error_message | node(s) exceed max volume count | |||||
| category | nodes | |||||
| severity | Medium | |||||
| recovery_time | 10–30 min | |||||
| k8s_versions | 1.20+ | |||||
| tags |
|
|||||
| related |
|
Severity: Medium · Typical recovery time: 10–30 min · Affected versions: 1.20+
Cloud providers and CSI drivers cap how many persistent volumes can be attached
to a single node (for example, AWS EBS limits attachments per instance type).
The scheduler enforces this limit; when every candidate node already has its
maximum number of volumes attached, a pod that needs a PVC stays Pending with
node(s) exceed max volume count in its scheduling events.
This is a scheduling constraint, not a node fault — the affected nodes are otherwise healthy. It typically appears when stateful workloads scale up, when volumes are slow to detach after pod moves, or on instance types with low attachment limits.
0/6 nodes are available: 3 node(s) exceed max volume count,
3 node(s) didn't match Pod's node affinity/selector.
Applies to 1.20+. The CSI VolumeAttachLimit (reported by the driver via
CSINode) governs the per-node count. Older in-tree volume limits were set by
provider-specific predicates; modern clusters use CSI-reported limits.
- Instance type with a low per-node attachment limit, fully consumed
- Volumes not detaching promptly after pods rescheduled (stuck VolumeAttachment)
- Too many stateful replicas pinned to a small node pool
- CSI driver under-reporting available attach slots
flowchart TD
A[Pod Pending: exceed max volume count] --> B{All eligible nodes at limit?}
B -- No --> C[Check affinity/selectors instead]
B -- Yes --> D{Stuck VolumeAttachments?}
D -- Yes --> E[Clear orphaned attachments]
D -- No --> F[Add nodes or use higher-limit instance type]
Confirm the per-node attach limit and how many volumes are currently attached.
kubectl get pod <pod> -n <ns> -o wide
kubectl describe pod <pod> -n <ns> | grep -A3 Events
kubectl get csinode <node> -o yaml | grep -A4 allocatable
kubectl get volumeattachments | grep <node>
kubectl get pvc -A | grep -i pending
kubectl describe node <node> | grep -i "Attached"$ kubectl describe pod web-0 -n data | grep -A2 Events
Warning FailedScheduling default-scheduler
0/6 nodes are available: 3 node(s) exceed max volume count, ...
$ kubectl get csinode node-1 -o yaml | grep -A2 allocatable
allocatable:
count: 25
- Add nodes (or scale the node pool) so volumes spread across more nodes.
- Use an instance type with a higher attachment limit for stateful pools.
- Clear stuck
VolumeAttachmentobjects so detached volumes free their slots.
- Scale out the relevant node pool so the scheduler has nodes with free slots.
- Resolve orphaned
VolumeAttachments (verify the volume is truly detached at the cloud layer before removing) — blast radius: storage-control-plane only. - If volumes are clustered on one node, drain/cordon to redistribute stateful pods — blast radius: those pods restart and reattach elsewhere; ensure capacity and quorum (e.g. for databases) first.
The Pending pod schedules and its PVC binds and mounts. kubectl get volumeattachments shows attachments spread under each node's allocatable count.
- Right-size node pools / instance types for your stateful volume density.
- Spread stateful replicas with topology constraints across nodes.
- Alert on per-node attachment count approaching the CSI limit.