kubernetes-troubleshooting
Skill0 starsChanged 2 months agoApache-2.0View on GitHub
Diagnose unhealthy Kubernetes workloads from symptom to root cause - CrashLoopBackOff, Pending, ImagePullBackOff, OOMKilled, Init:Error, readiness probe failures, pods stuck Terminating, and rollouts that never complete. Use whenever a pod, deployment, job or statefulset is not running as expected and the cause is not yet known, before changing any manifest.
3 other projects use a version of this.
Adopted by
Most recently taken up by
- kcns008/cluster-skillstheir own version, first seen Nov 8, 2026
- ngaxavi/skillstheir own version, first seen Oct 20, 2026
- inspektor-gadget/inspektor-gadgettheir own version, first seen Oct 8, 2026
Other versions3 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 3
- inspektor-gadget/inspektor-gadget★ 3ksame name
- kcns008/cluster-skills★ 4same name
- ngaxavi/skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository26 other files it gives its agents.
- AGENTS.mdAGENTS.md
- aws-production-debuggingSkill
- github-actions-debuggingSkill
- postgresql-troubleshootingSkill
- container-image-reviewSkill
- docker-debuggingSkill
- incident-triageSkill
- postmortem-analysisSkill
- production-debuggingSkill
- kubernetes-networkingSkill
- kubernetes-production-readinessSkill
- kubernetes-resource-debuggingSkill
- linux-network-debuggingSkill
- linux-performanceSkill
- linux-troubleshootingSkill
- dns-troubleshootingSkill
- http-debuggingSkill
- tls-debuggingSkill
- observability-debuggingSkill
- prometheus-troubleshootingSkill
- slo-designSkill
- secrets-management-reviewSkill
- technology-jobSkill
- terraform-reviewSkill
- terraform-safe-changesSkill
- terraform-troubleshootingSkill
The file
We split this skill into the rules it gives an agent
8 rules. 0 are common, 6 are distinctive, and 2 are very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
6
Distinctive
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 58
Correlate with change: Check the rollout history and recent deploys.
- Distinctive: line 60
Form one hypothesis and test it: Prefer a test that eliminates a class of causes: exec into a healthy pod, describe a node, or pull the …
- Distinctive: line 68
Unverified: If the namespace, image tag or cluster is unknown, run a command or ask — do not infer it from the repository.
- Distinctive: line 107
Read from the bottom. In order of signal:
- Very specific: line 155
Run the probe yourself from inside the cluster.
- Very specific: line 261
Better: Check container_cpu_cfs_throttled_seconds_total before assuming throttling.
- Distinctive: line 265
Bad: Delete the pod to make the error go away.
- Distinctive: line 274
Better: Check whether the error is a symptom of a dependency — a database connection refused in the logs usually means the database, DNS, …
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Kubernetes Troubleshooting
Take a workload from "it is not working" to a named root cause, using the pod lifecycle as the search order.
Purpose
Use this when:
- A pod is in
CrashLoopBackOff,Pending,ImagePullBackOff,ErrImagePull,Init:Error,CreateContainerConfigError,Evicted, or stuckTerminating. - A
kubectl rollout statusnever completes. - A workload reports
RunningbutREADY 0/1.
Do not use this when:
- Pods are healthy and the problem is traffic not reaching them — use
kubernetes-networking. - The question is "is this workload production-ready?" — use
kubernetes-production-readiness. - The cluster itself is degraded (API server unreachable, all nodes
NotReady) — that is a cluster incident; start withincident-triage.
What this skill assumes: a working kubeconfig with at least read access to the namespace, and
kubectl on the path.
Operating Procedure
- Establish context. Confirm which cluster and namespace you are in before running anything else. Getting this wrong is the single most common cause of a wasted investigation — and of changing the wrong environment.
- Classify the phase. Pod status maps to a layer:
Pendingis the scheduler,ImagePull*is the kubelet or registry,CrashLoopBackOffis the container,Running 0/1is the probe or the application. Search only that layer first. - Read events before logs. Events explain why Kubernetes did or did not do something. Logs explain what the application did. Most non-crash problems are answered by events alone.
- Correlate with change. Check the rollout history and recent deploys. Most workload failures follow a change to the image, the config, the resource requests, or the cluster.
- Form one hypothesis and test it. Prefer a test that eliminates a class of causes: exec into a healthy pod, describe a node, or pull the image locally.
- Apply the smallest safe change. Fix the manifest or the config, not the running pod.
Changes made with
kubectl editon a live object are erased by the next deploy. - Verify. See Verification.
- Record the symptom, the root cause, the change and the rollback command.
Label every statement as Observed (from command output), Assumed, Recommended, or Unverified. If the namespace, image tag or cluster is unknown, run a command or ask — do not infer it from the repository.
Investigation
Step 1 - context and blast radius
kubectl config current-context
kubectl version --output=json | jq -r '.serverVersion.gitVersion'
kubectl get pods -n <namespace> -o widecurrent-context tells you which cluster you are about to affect. The server version matters
because API deprecations and probe fields differ across minor releases. -o wide gives you the
node name and pod IP in one shot — if every failing pod is on one node, the problem is the node,
not the workload.
Step 2 - the whole-cluster sweep
kubectl get pods -A --field-selector=status.phase!=Running
kubectl get events -A --sort-by=.lastTimestamp | tail -40The first command shows whether this is one workload or many. Many workloads failing at once means a shared dependency: a node, the registry, DNS, a webhook, or a storage backend.
Events are cluster-wide and time-ordered. FailedScheduling points at the scheduler,
FailedMount at storage or the CSI driver, Failed to pull image at the registry,
FailedCreatePodSandBox at the CNI. Note that events are garbage collected after one hour by
default — an empty event list on an old problem is not evidence of health.
Step 3 - describe the pod
kubectl describe pod <pod> -n <namespace>Read from the bottom. In order of signal:
| Field | Value | Meaning |
Events: FailedScheduling | Insufficient cpu/memory | No node has room for the requests. Cluster capacity or an oversized request. |
Events: FailedScheduling | node(s) had untolerated taint | Taint/toleration or nodeSelector mismatch. |
Events: Failed to pull image | unauthorized | Missing or wrong imagePullSecrets. |
Events: Failed to pull image | manifest unknown | The tag does not exist. Check the build. |
Last State: Terminated | Reason: OOMKilled, exit 137 | Container exceeded its memory limit. |
Last State: Terminated | Reason: Error, exit 1 | The application exited. Go to logs. |
Last State: Terminated | Reason: Error, exit 143 | SIGTERM — it was asked to stop. Usually eviction or a rollout, not a bug. |
State: Waiting | CreateContainerConfigError | A referenced ConfigMap or Secret key does not exist. |
Ready: False with restarts 0 | — | The probe is failing, the process is not crashing. |
Step 4 - logs, including the previous container
kubectl logs <pod> -n <namespace> --tail=200
kubectl logs <pod> -n <namespace> --previous --tail=200
kubectl logs <pod> -n <namespace> -c <init-container>For a crash loop the live container is usually too young to have logged anything useful.
--previous returns the logs of the instance that actually died; it is the highest-value command
in this entire skill. If it errors with previous terminated container not found, the container
has not restarted yet — the pod is failing before the container starts, so go back to events.
Step 5 - correlate with recent change
kubectl rollout history deployment/<name> -n <namespace>
kubectl get deployment <name> -n <namespace> -o jsonpath='{.spec.template.spec.containers[*].image}{"\n"}'
kubectl get replicaset -n <namespace> --sort-by=.metadata.creationTimestamp | tail -5A new ReplicaSet created minutes before the symptom began is your prime suspect. The image path
tells you whether the tag is mutable (:latest, :main) — a mutable tag means the running code
may differ from the last deploy even though nothing in Git changed.
Step 6 - probe and dependency checks
kubectl get pod <pod> -n <namespace> \
-o jsonpath='{range .spec.containers[*]}{.name}{"\t"}{.readinessProbe}{"\n"}{end}'
kubectl exec -it <healthy-pod> -n <namespace> -- curl -sS -m 5 -o /dev/null -w '%{http_code}\n' \
http://<pod-ip>:<port>/healthzRun the probe yourself from inside the cluster. A readiness endpoint that takes longer than
timeoutSeconds, or that checks a downstream dependency, will flap the pod out of the Service
endpoints without the application ever crashing. This is the most commonly misdiagnosed Kubernetes
failure: the application is fine and the probe is wrong, or the probe is honest and the dependency
is down.
Decision Tree
Pod is not healthy
├── Pending
│ ├── "Insufficient cpu/memory" → capacity or oversized requests → kubernetes-resource-debugging
│ ├── "untolerated taint" / nodeSelector → placement constraints
│ ├── "pod has unbound PersistentVolumeClaim" → storage class / PV provisioner
│ └── no events at all → scheduler down, or the pod is gated
├── ImagePullBackOff / ErrImagePull
│ ├── "unauthorized" → imagePullSecrets
│ ├── "manifest unknown" → tag does not exist
│ └── i/o timeout → node egress or registry reachability
├── Init:Error / Init:CrashLoopBackOff → logs of the init container, not the main one
├── CreateContainerConfigError → missing ConfigMap/Secret key
├── CrashLoopBackOff
│ ├── exit 137 / OOMKilled → memory limit → kubernetes-resource-debugging
│ ├── exit 1 / 2 → application error → --previous logs
│ ├── exit 127 → command or entrypoint not found → container-image-review
│ └── exit 0 in a Deployment → the process is not long-running; wrong entrypoint
├── Running but 0/1 Ready
│ ├── probe times out → probe config, slow start, or saturated container
│ └── probe returns 5xx → the application's own dependency check is failing
└── Terminating and stuck
├── finalizers present → a controller is not releasing the object
└── node NotReady → the kubelet cannot confirm deletionCommon Causes
| Cause | Signal | Fix | Risk |
| Memory limit too low | exit 137, OOMKilled | Raise limits.memory after measuring actual usage | mutating |
| Readiness probe too aggressive | Ready: False, 0 restarts, app logs healthy | Raise initialDelaySeconds/timeoutSeconds | mutating |
| Mutable image tag | Same tag, different behaviour | Pin by digest | mutating |
| Missing secret key | CreateContainerConfigError | Create the key, then let the kubelet retry | mutating |
| Node pressure | Evicted, DiskPressure on the node | Free disk on the node or rebalance | disruptive |
| Insufficient capacity | FailedScheduling | Scale the node pool or lower requests | mutating |
Safety
Read-only
Everything in Investigation except kubectl exec. get, describe, logs,
events, and rollout history cannot change cluster state. Run them freely.
kubectl exec is read-only only if the command you run is. curl against a health endpoint is
fine; a shell in a production container is an audited action in most organisations and can change
container state.
Potentially disruptive
Each of these needs a stated reason and a rollback before you run it.
kubectl rollout restart deployment/<name>— recreates every pod in the deployment under the configuredmaxUnavailable. Blast radius: all replicas. Rollback: none needed, but in-flight requests are dropped if the app does not handle SIGTERM.kubectl rollout undo deployment/<name>— returns to the previous ReplicaSet. This is the correct first action when a deploy caused the symptom. Rollback:kubectl rollout undoagain.kubectl scale deployment/<name> --replicas=N— changes capacity. Rollback: scale back. Note that an HPA will fight a manual scale.kubectl delete pod <pod>— the controller recreates it. Destroys the evidence you need. Do this only after capturingdescribeand--previouslogs, never as a first step.kubectl cordon <node>/kubectl drain <node>— moves every pod off a node. Drain respects PodDisruptionBudgets and will hang if one cannot be satisfied; that hang is a correct signal, not a problem to force past.
Destructive
This skill proposes no destructive operations. Deleting PersistentVolumeClaims, namespaces or StatefulSets is out of scope here on purpose — those operations destroy data and belong to a deliberate, separately-reviewed change.
Verification
A pod reaching Running is not verification. Verify the workload, at two layers:
Before: 3/8 pods Ready, restart count climbing, 12% 5xx at the ingress
After: 8/8 pods Ready for >10 min, restart count flat, <0.1% 5xx at the ingresskubectl rollout status deployment/<name> -n <namespace> --timeout=5m
kubectl get pods -n <namespace> -l app=<label> \
-o custom-columns=NAME:.metadata.name,READY:.status.containerStatuses[*].ready,RESTARTS:.status.containerStatuses[*].restartCountThen wait. A CrashLoopBackOff fix that has been up for 30 seconds has not been verified — the
backoff interval alone reaches 5 minutes. Confirm the restart count is still flat several minutes
later, and confirm the user-visible symptom (error rate, latency, queue depth) has recovered in
your monitoring, not just in kubectl.
Anti-Patterns
Bad: Restart everything and see if it helps. Better: Identify the failing layer first. A restart destroys the evidence and, if the cause is a bad image or a missing secret, changes nothing except your ability to diagnose it.
Bad: Raise the CPU limit because the pod looks slow.
Better: Check container_cpu_cfs_throttled_seconds_total before assuming throttling. CPU
limits do not cause OOMKills, and raising a limit that was never being hit only reduces how many
pods fit on a node.
Bad: Delete the pod to make the error go away.
Better: Understand why it is unhealthy. A pod recreated into the same broken state has cost you
the --previous logs and taught you nothing.
Bad: kubectl edit the live Deployment to fix it.
Better: Change the manifest in Git and deploy. A live edit is silently reverted by the next
sync and produces a failure that nobody can reproduce.
Bad: Conclude "the app is broken" because the container logs an error. Better: Check whether the error is a symptom of a dependency — a database connection refused in the logs usually means the database, DNS, or a NetworkPolicy is the actual fault.
Composition
kubernetes-networking— pods are healthy but traffic is not reaching them.kubernetes-resource-debugging— OOMKills, throttling, requests and limits, capacity.container-image-review— exit 127, missing entrypoints, image bloat, wrong base image.linux-troubleshooting— node-level disk, memory or process problems.production-debugging— the workload is a symptom of a wider outage.
References
references/pod-status-matrix.md— exhaustive status/reason/exit-code lookup table.- Kubernetes: Debug Pods — upstream reference for pod phases and conditions.
- Kubernetes: Pod Lifecycle — authoritative definition of phases, conditions and restart policy.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

