volume node affinity conflict": pod stuck Pending with local volumes
Resolves volume node affinity conflicts for pods using local storage. Use when pods stay Pending with affinity conflict messages, when local PVs pin pods to specific nodes, or when designing local storage. Not for network storage issues.
TL;DR
Local volumes live on one specific node, and the PV's node affinity requires the pod to schedule there. The conflict arises when the pod's other constraints (affinity, taints, resources) rule out that exact node: the volume says "must run on node A" while everything else says "cannot run on node A". Fix it by aligning the constraints or by not using local storage for portable workloads.
The query
"volume node affinity conflict": pod stuck Pending with local volumesUse this when
- Pods stay Pending with volume node affinity conflict
- Using local persistent volumes
- Pods need to move but volumes pin them
- Designing storage for stateful workloads
Not for when
- Network storage (EBS, NFS, Ceph) scheduling
- Generic FailedScheduling without volume involvement
- Storage performance issues
Steps
Step 1: Read which node the volume requires
Inspect the PV's node affinity to find the required node. Local PVs are bound to the node where the disk lives; this is the immovable constraint in the conflict. Expected output: the required node named.
Step 2: List what rules out that node for the pod
Check the pod's node affinity, tolerations, and resource requests against the required node. The conflict is always specific: a taint on that node, an anti-affinity rule, or insufficient resources there. Expected output: the exact constraint conflicting with the volume's node requirement.
Step 3: Decide which constraint yields
If the pod must stay portable, the local volume is the wrong storage: move to network storage. If the pod can live on that node, relax the conflicting constraint (add the toleration, adjust affinity). One of the two requirements has to give. Expected output: a deliberate choice: pod moves to the volume's node, or storage changes.
Step 4: For StatefulSets, check volume claim templates
StatefulSet pods are sticky to their volumes by design. If a pod was deleted and its replacement cannot schedule where the volume lives, the conflict is structural; the fix is node capacity or constraint alignment, not pod deletion loops. Expected output: the StatefulSet's volume binding understood as intentional stickiness.
Step 5: Avoid local volumes for portable workloads
Reserve local PVs for workloads that genuinely need local disk performance and can tolerate node stickiness. Everything else belongs on network storage, where scheduling stays flexible. Expected output: local storage used deliberately, not by default.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_VlVwe5cYXibKM6mWdTeKZQ
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.