Pending pod: attributing a scheduling failure
A pod stuck in Pending never had a container start, so container logs won't help. The evidence lives in scheduler events and cluster capacity — which is exactly what OpsKit reads first.
Run it
/k8s-triage batch-job-4x2kd has been Pending for 20 minutes
Causes OpsKit checks for, in order of how often they're the actual reason
- Insufficient allocatable CPU/memory across nodes for the pod's requests
- Taints on available nodes with no matching toleration on the pod
- Node selector or affinity rules that no current node satisfies
- An unbound PersistentVolumeClaim the pod depends on
- Admission policy rejection — OpsKit attributes drift against the policies actually configured on the cluster rather than assuming a generic cause
- On 1.36, an unsatisfiable Dynamic Resource Allocation claim — a newer scheduling constraint most general-purpose tools don't know to check
What it reads
The pod spec, node capacity and allocatable resources cluster-wide, the scheduler's FailedScheduling event reasons, and PVC/PV binding status. The scheduler event message is usually the single most direct piece of evidence — OpsKit treats it as primary rather than re-deriving the cause from scratch.
The fix
If the cause is a manifest issue — requests set too high, a toleration missing, an affinity rule too strict — k8s-fixer opens a GitOps PR adjusting it. If the cause is a genuine capacity shortfall, OpsKit reports that as an infrastructure constraint rather than proposing a manifest change that wouldn't fix anything.
Limitations
OpsKit can't add nodes, resize a node pool, or provision capacity — it has no write access to infrastructure. When the root cause is "the cluster doesn't have room," the output is a clear attribution for a human to act on, not a resolution.
Ready to point it at your cluster?
Get OpsKit — $19