The scheduler found a node but refuses to use it: the node carries a taint your pod doesn't tolerate. Read which taint, then decide: tolerate it, remove it, or add the right node.
Control-plane nodes carry node-role.kubernetes.io/control-plane:NoSchedule — correct isolation on shared nodes, but on single-node clusters it blocks everything.
Teams taint GPU/memory nodes so only labeled workloads land there. Your pod needs a matching toleration (and often nodeSelector/affinity to land on the right node).
node.kubernetes.io/unschedulable or a drain taint that was never removed after maintenance. kubectl describe node shows current taints.
kubectl get pods -o wide | head ; kubectl describe node <n> | grep -A5 Taints
# spec.template.spec.tolerations: [{ key: "node-role.kubernetes.io/control-plane", operator: "Exists", effect: "NoSchedule" }]
kubectl taint nodes <n> node.kubernetes.io/unschedulable- # trailing '-' removes
# tolerations + nodeSelector: { disktype: gpu } # tolerate AND target the node deliberately
Single-node/k3s homelab clusters: tolerating the control-plane taint is normal and safe; multi-node clusters should keep control-plane isolation. Taints and tolerations allow; nodeSelector/affinity chooses. Isolation usually needs both directions.
Taints repel pods without matching tolerations; selectors attract pods to labeled nodes. To dedicate a node you typically do both — taint it (repel everyone else) and select it in your pod spec (attract yours).
On single-node clusters, yes — there's nothing else to protect. On clusters with dedicated workers, keep control-plane isolation: your workload competes with etcd/apiserver for resources.
Kustomize base with probes, PDBs, and zero-downtime rollouts already wired.
Kubernetes Production Blueprints — $27 →One-time. Yours to modify. Instant download from the NinjaOps template store.