Kubernetes Application Troubleshooting

A systematic, layer-by-layer guide to diagnosing why applications fail in Kubernetes — from image pull errors to rollout stalls. This is the single most tested skill in the Troubleshooting domain (~30%) of the CKA exam. Synthesized from CKA Day 37 — Application Failure Troubleshooting.

The Debugging Mindset

Kubernetes failures are rarely mysterious — they are usually the result of a misconfiguration that Kubernetes reports clearly. The key is knowing where to look and in what order. The CKA exam rewards methodical inspection over intuition.

Golden Rule: Events First. kubectl describe pod Events are ordered chronologically and contain human-readable explanations of failures. Read them before diving into logs or interactive shells. Source: CKA Day 37


The Standard Debugging Chain

Step 1: kubectl get pods -o wide
        └─→ Check STATUS, RESTARTS, NODE, AGE

Step 2: kubectl describe pod <name>
        └─→ Read Events (bottom of output)

Step 3: kubectl logs <name> [--previous] [-c <container>]
        └─→ See what the app actually output

Step 4: kubectl exec -it <name> -- sh
        └─→ Interactive inspection inside the container

Step 5: kubectl get events --sort-by='.lastTimestamp'
        └─→ Cluster-wide context if the Pod keeps disappearing

Failure Mode Catalog

1. Image Pull Failures (ImagePullBackOff)

The kubelet cannot download the container image. The Pod status shows ImagePullBackOff with exponential backoff retries.

CauseHow to DetectFix
Wrong image name/tagkubectl describe pod → “Failed to pull image”kubectl set image deployment/<name> <container>=<correct>:<tag>
Private registry, no credentialskubectl describe pod → “unauthorized”Add imagePullSecrets to Pod or ServiceAccount
Registry unreachablekubectl describe pod → network timeoutCheck DNS, NetworkPolicy, or node internet access
# Fast image correction
kubectl set image deployment/nginx nginx=nginx:1.25-alpine
 
# Verify the pull spec
kubectl get pod <name> -o jsonpath='{.spec.containers[0].image}'

2. Crash Loops (CrashLoopBackOff)

The container starts, crashes, and is restarted repeatedly. The RESTARTS count climbs in kubectl get pod.

CauseHow to DetectFix
Missing env varkubectl logs --previous → “DATABASE_URL not set”Add env to Pod spec or ConfigMap
Bad command/argskubectl logs --previous → command not foundFix command/args in container spec
Missing ConfigMap/Secretkubectl describe pod → “configmap not found”Create the referenced object
Aggressive liveness probekubectl describe pod → liveness probe failedAdd initialDelaySeconds or a startup probe
OOM on startupkubectl describe podLast State: OOMKilledRaise memory limit or fix memory leak
# The three crash-loop diagnostics
kubectl get pod <name>                    # Check RESTARTS
kubectl describe pod <name>             # Check Events and Last State
kubectl logs <name> --previous          # Read the crash output

3. Pods Stuck Pending

The scheduler cannot place the Pod on any node. The Pod is accepted by the API server but never starts running.

CauseHow to DetectFix
Insufficient CPU/memorykubectl describe pod → “Insufficient cpu” or “Insufficient memory”Lower requests or add nodes
No matching node for taintskubectl describe pod → taint toleration mismatchAdd tolerations or remove taints
PVC not boundkubectl describe pod → “unbound immediate PersistentVolumeClaim”Check PVC status and StorageClass
Node selector mismatchkubectl describe pod → “0/3 nodes are available”Verify node labels match selector

4. ContainerCannotRun / Volume Mount Failures

The container cannot start because a required volume or mount is missing or misconfigured.

CauseHow to DetectFix
ConfigMap/Secret missingkubectl describe pod → “MountVolume.SetUp failed”Create the ConfigMap/Secret
Wrong mount pathContainer starts but app can’t find filesVerify mountPath matches app expectations
Permission deniedkubectl describe pod → permission errorsCheck fsGroup, runAsUser, or volume permissions

5. Service Not Routing Traffic

Pods are Running but clients get connection refused, timeouts, or 502 errors.

CauseHow to DetectFix
Selector mismatchkubectl get endpoints <svc> shows no IPsEnsure Service selector matches Pod labels exactly
Readiness probe failingkubectl get endpoints → target IPs missingFix readiness probe or application startup
Port mismatchkubectl describe svc vs kubectl get podEnsure targetPort matches container containerPort
NetworkPolicy blockingTraffic times outAdd ingress rule allowing client to backend
DNS failurenslookup <svc> failsCheck CoreDNS logs and Service name/namespace
# The service diagnosis chain
kubectl get svc <name> -o yaml | grep selector     # Verify selector
kubectl get endpoints <name>                       # Verify backend IPs
kubectl describe pod <backend-pod>                 # Check readiness state
kubectl exec -it client-pod -- nslookup <svc>      # Verify DNS

6. Deployment Rollout Stuck

A rolling update makes no progress — old Pods keep running, new Pods never become ready.

CauseHow to DetectFix
Readiness probe never passeskubectl rollout status hangsFix app or probe configuration
Resource quota exhaustedkubectl describe pod → “Forbidden: exceeded quota”Raise Namespace ResourceQuota or reduce replicas
ImagePullBackOff on new PodsNew Pods show ImagePullBackOffCorrect image name in Deployment
MaxSurge / MaxUnavailable conflictNo Pods can be created or terminatedAdjust Deployment strategy
# Rollout diagnostics
kubectl rollout status deployment/<name>
kubectl rollout history deployment/<name>
kubectl get rs -l app=<name>                       # See ReplicaSet generations
kubectl get pod -l app=<name>                      # Check new Pod status

7. Init Container Failures (Init:Error / Init:CrashLoopBackOff)

An init container exits non-zero, blocking the main containers from ever starting.

CauseHow to DetectFix
Database not readykubectl logs <pod> -c <init> → connection refusedAdd retry logic or fix database connectivity
Missing permissionInit container can’t write to shared volumeCheck volume permissions and securityContext
Wrong commandkubectl logs <pod> -c <init> → command not foundFix init container command/args
# Init container diagnostics
kubectl get pod <name>                             # Status shows "Init:Error"
kubectl describe pod <name>                      # Which init container failed
kubectl logs <name> -c <init-container>          # Read the failure output

Events: The Cluster-Wide Audit Trail

Events are the most underutilized debugging resource. They persist for a limited time (default ~1 hour) and capture everything Kubernetes does:

# All events, newest last
kubectl get events --sort-by='.lastTimestamp'
 
# Events for a specific object
kubectl get events --field-selector involvedObject.name=<pod-name>
 
# Only warnings (failures)
kubectl get events --field-selector type=Warning
 
# Events for a namespace
kubectl get events -n <namespace>

Common Event Messages and Their Meaning:

Event MessageMeaningAction
Failed to pull imageImage name/tag/registry issueCorrect the image spec
Back-off pulling imageSame as above, after retriesSame fix
FailedMountVolume could not attach or mountCheck PVC, node, or CSI driver
FailedSchedulingNo node matches the PodCheck requests, taints, selectors
UnhealthyLiveness probe failedFix probe or app
KillingPod is being terminatedNormal, or due to eviction/node drain
Created containerContainer started successfullyGood sign
Started containerContainer process is runningGood sign

The Layered Failure Model

When an application is failing, work through the stack from bottom to top:

Layer 1: Node          ──► Is the node Ready? kubelet healthy? (journalctl -u kubelet)
Layer 2: Pod Schedule  ──► Is the Pod Running? Or Pending? (kubectl get pod)
Layer 3: Container     ──► Is the container alive? (kubectl describe → Events)
Layer 4: Application   ──► Is the app logic healthy? (kubectl logs, kubectl exec)
Layer 5: Service       ──► Can clients reach it? (kubectl get endpoints, nslookup)
Layer 6: Ingress       ──► Is external traffic routing? (kubectl get ingress, controller logs)

CKA Exam Strategy: The exam presents broken applications and asks you to fix them. You won’t have time to guess. Use this chain: get → describe → logs → fix → verify.


CKA Exam Speed Patterns

# 1. Quick status check
kubectl get pods -o wide -n <namespace>
 
# 2. Read the story in Events
kubectl describe pod <name> | grep -A 20 Events
 
# 3. Crash analysis
kubectl logs <name> --previous
 
# 4. Multi-container crash
kubectl logs <name> -c <container> --previous
 
# 5. Interactive debugging
kubectl exec -it <name> -- env | grep <VAR>
kubectl exec -it <name> -- cat /etc/config/app.yaml
 
# 6. Service routing
kubectl get svc <name> -o yaml | grep -A 3 selector
kubectl get endpoints <name>
 
# 7. Rollout status
kubectl rollout status deployment/<name>
kubectl rollout undo deployment/<name>  # Emergency rollback
 
# 8. Events stream
kubectl get events --sort-by='.lastTimestamp' | tail -20

Production Best Practices

PracticeRationale
Always check Events firstThey contain the exact error from the controller or kubelet
Use --previous for crashesThe current container may not have logged the failure
Validate selectors match labelsA single typo (app: ngnix vs app: nginx) breaks Service routing
Test readiness before livenessAn app that is alive but not ready should not receive traffic
Set resource requests AND limitsMissing limits cause OOMKilled; missing requests cause scheduling issues
Use kubectl apply --dry-run=clientCatch YAML errors before they create broken Pods
Monitor Events centrallyTools like kubectl get events or cluster event exporters surface patterns

Practical Practice

Exam-style hands-on tasks for this topic. Complete each task before reviewing the solution. Time yourself — CKA tasks average 5–7 minutes.

Task 1: Fix ImagePullBackOff A Pod web-1 is in ImagePullBackOff — identify the wrong image tag and fix it. Requirements: Use only imperative commands. Do not delete the Pod. Verification: kubectl get pod web-1 Solution:

kubectl describe pod web-1 | grep -i "Failed to pull image"
kubectl set image pod/web-1 web=nginx:1.25-alpine
kubectl get pod web-1

Task 2: Unstick a Deployment Rollout A Deployment rollout is stuck — inspect the ReplicaSet events and fix the resource limit typo (limtslimits). Requirements: Edit the live Deployment. Verify the new ReplicaSet scales up. Verification: kubectl rollout status deployment/<name> Solution:

kubectl get rs -l app=<name>
kubectl describe rs <new-rs> | grep -i "limts"
kubectl edit deployment <name>  # fix limts -> limits
kubectl rollout status deployment/<name>

Task 3: Fix Service targetPort Mismatch A Service returns connection refused — the Pod is listening on port 8080 but the Service targets 80; fix the targetPort. Requirements: Patch the Service without recreating it. Verification: kubectl get svc <svc> -o yaml | grep targetPort Solution:

kubectl get svc <svc> -o yaml | grep targetPort
kubectl patch svc <svc> --type='json' -p='[{"op": "replace", "path": "/spec/ports/0/targetPort", "value":8080}]'
kubectl get endpoints <svc>

Task 4: Diagnose CrashLoopBackOff A Pod is CrashLoopBackOff — read the previous container logs and fix the missing environment variable. Requirements: Add the missing env var to the Pod spec. Use --dry-run=client -o yaml if regenerating YAML. Verification: kubectl get pod <pod> Solution:

kubectl logs <pod> --previous
kubectl get pod <pod> -o yaml > pod.yaml
# edit pod.yaml to add the missing env var
kubectl apply -f pod.yaml --dry-run=client
kubectl delete pod <pod> && kubectl apply -f pod.yaml


Tags: kubernetes troubleshooting application-failure cka devops diagnostics events crashloopbackoff imagepullbackoff rollout