Start with the same three commands every time
Most Kubernetes problems show up in a pod's status, and nearly all of the explanation is in two places: the events at the bottom of the describe output, and the container logs. Learn this routine and you can solve most failures without guessing.
kubectl get pods -A
kubectl -n demo describe pod POD_NAME
kubectl -n demo logs POD_NAME
kubectl -n demo get events --sort-by=.lastTimestamp | tail -n 20Pending: the pod was never scheduled
A Pending pod has been accepted by the cluster but not placed on a node. The describe events say why. The common reasons are not enough CPU or memory on any node ("Insufficient memory"), a PersistentVolumeClaim that cannot bind, a taint or node selector that no node satisfies, or a missing image pull secret in some setups.
kubectl -n demo describe pod POD_NAME | sed -n '/Events:/,$p'
kubectl describe node | grep -A8 "Allocated resources"
kubectl top nodes
kubectl -n demo get pvcPending because of resources
Kubernetes schedules by what a pod requests, not what it uses. If the requests of all pods add up to more than the node offers, new pods wait. On a small server, lower requests that are bigger than needed, remove pods you do not need, or move to a larger plan. Setting very high requests "to be safe" is a common cause.
kubectl get pods -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,CPU:.spec.containers[*].resources.requests.cpu,MEM:.spec.containers[*].resources.requests.memory
kubectl -n demo set resources deployment/site --requests=cpu=50m,memory=64MiPending because of storage
A claim stays Pending when no volume can satisfy it: a wrong storage class name, a size that is not available, or a class that waits for the first pod to use it. K3s's local-path class intentionally waits, so a claim shows Pending until a pod mounts it. If both the pod and the claim stay Pending, read the claim's events.
kubectl get storageclass
kubectl -n demo describe pvc site-data | sed -n '/Events:/,$p'ImagePullBackOff and ErrImagePull
The node could not download the image. The event message names the reason: the image name or tag does not exist, the registry needs a login, a rate limit was hit, or the node cannot reach the registry. Check the exact image string for typos, check that the tag exists, and test the pull from the node itself.
kubectl -n demo describe pod POD_NAME | grep -i -E "image|pull|failed"
kubectl -n demo get pod POD_NAME -o jsonpath='{.spec.containers[*].image}'; echo
sudo k3s crictl pull nginx:stable
curl -sI https://registry-1.docker.io/v2/ | head -n 1
getent hosts registry-1.docker.io Reason: ErrImagePull
Warning Failed 1s kubelet spec.containers{nginx}: Failed to pull image "nginx:glws-invalid-tag-validation": rpc error: code = NotFound desc = failed to pull and unpack image "docker.io/library/nginx:glws-invalid-tag-validation": failed to resolve reference "docker.io/library/nginx:glws-invalid-tag-validation": docker.io/library/nginx:glws-invalid-tag-validation: not found
Warning Failed 1s kubelet spec.containers{nginx}: Error: ErrImagePull
Normal BackOff 0s kubelet spec.containers{nginx}: Back-off pulling image "nginx:glws-invalid-tag-validation"
Warning Failed 0s kubelet spec.containers{nginx}: Error: ImagePullBackOffPulling from a private registry
A private image needs credentials stored as a secret of type docker-registry, referenced from the pod or the service account. Create it without leaving the password in your shell history, and reference it as an image pull secret.
read -rsp "Registry password or token: " REGPASS; echo
kubectl -n demo create secret docker-registry regcred --docker-server=ghcr.io --docker-username=YOUR_USER --docker-password="$REGPASS"
unset REGPASS
kubectl -n demo patch serviceaccount default -p '{"imagePullSecrets":[{"name":"regcred"}]}'CrashLoopBackOff: the container keeps dying
The container starts, exits and is restarted with growing delays. The reason is in the container's own output, so read the logs of the previous run, because the current one may be empty. Then look at the exit code and the last state in describe.
kubectl -n demo logs POD_NAME --previous
kubectl -n demo describe pod POD_NAME | grep -A8 "Last State"
kubectl -n demo get pod POD_NAME -o jsonpath='{.status.containerStatuses[0].lastState}'; echoRead the exit code
Exit code 1 or another small number is the application failing, so the logs explain it: a missing setting, a wrong password, a port already in use or a failed migration. Exit code 137 with reason OOMKilled means the container went over its memory limit and was killed, so raise the limit or fix the leak. Code 139 is a crash such as a segmentation fault. A container that exits with 0 immediately has simply finished, which is wrong for a service, so check its command.
kubectl -n demo get pod POD_NAME -o jsonpath='{.status.containerStatuses[0].lastState.terminated.reason} {.status.containerStatuses[0].lastState.terminated.exitCode}'; echo
kubectl -n demo set resources deployment/site --limits=memory=512MiCrashes that come from probes and configuration
A liveness probe that fails restarts a healthy but slow application. Raise initialDelaySeconds or use a startup probe. Missing ConfigMaps and Secrets block a container from starting with a "CreateContainerConfigError" status, so check that every referenced object exists in the same namespace. Environment values and mounted files can be inspected inside a running container with exec.
kubectl -n demo get configmap,secret
kubectl -n demo describe pod POD_NAME | grep -i -E "liveness|readiness|probe"
kubectl -n demo exec -it POD_NAME -- sh
kubectl -n demo run debug --rm -it --image=busybox:stable --restart=Never -- shCheck the node and the control plane
If many pods misbehave at once, look at the node: memory or disk pressure evicts pods, and a full disk stops image pulls. On K3s, the service log shows cluster-level errors.
kubectl describe node | grep -A10 "Conditions:"
df -h /
free -h
sudo journalctl -u k3s --since "30 minutes ago" --no-pager | tail -n 30Official documentation
These upstream references provide more detail on the commands and workflows in this guide.