Troubleshooting Applications on Kubernetes
John Harris
This guide lists common commands and approaches to troubleshoot applications on Kubernetes. In this guide we assume that:
- You are familiar with
kubectl
, the Kubernetes command-line client. - You have access to the Kubernetes cluster you want to troubleshoot
- You are familiar with the common Kubernetes resources, such as Deployments, Services, Pods, etc.
Below is a list covering some common issues and how to troubleshoot them in a Kubernetes environment.
Pods showing ‘CrashLoopBackOff’ status
This usually indicates an issue with the application. Use the kubectl logs
command to get logs from the pod.
If the pod has multiple containers, you first have to find the container that is crashing.
Use the kubectl describe
command on the pod to figure out which container is
crashing. The following example shows the list of containers in the kubectl describe
output. Notice how the bad
container’s last state is Terminated
.
This is the container that keeps crashing.
Containers:
bad:
Container ID: containerd://dd42e41890e04253915445...
Image: busybox
Image ID: docker.io/library/busybox@sha256:83...
Port: <none>
Host Port: <none>
Args:
sleep
1
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Completed
Exit Code: 0
Started: Mon, 18 May 2020 10:47:03 -0400
Finished: Mon, 18 May 2020 10:47:04 -0400
Ready: False
Restart Count: 3
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from
default-token-dfl9d (ro)
good:
Container ID: containerd://8a8ce59842cce4d8c98f...
Image: nginx
Image ID: docker.io/library/nginx@sha256:30...
Port: <none>
Host Port: <none>
State: Running
Started: Mon, 18 May 2020 10:46:14 -0400
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from
default-token-dfl9d (ro)
Services are unreachable or not available
As a sanity check, it is always useful to verify that the service has endpoints.
Use the kubectl get endpoints
command to verify that a service has at least
one endpoint:
$ kubectl get endpoints example
NAME ENDPOINTS AGE
example 10.244.0.21:80,10.244.0.22:80 27s
If the service does not have endpoints, verify the following:
- The service’s pod selector matches the labels on the desired pods.
- The pods backing the service are passing their readiness probe.
For more in depth troubleshooting, you can utilize a dnsutil pod described here
Pods showing ‘Pending’ status
If the pod is stuck in Pending state, this means that the pod cannot be scheduled to a node. The most common cause of this issue is that there is no node with enough resources to satisfy the pod’s resource requests.
To diagnose this issue, use kubectl describe
and look at the events at the
bottom of the output. The following is an example that shows what to look for:
$ kubectl describe pod example
### Output truncated for brevity
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 17s (x2 over 17s) default-scheduler 0/1 nodes are available: 1 Insufficient memory.
Pods showing ‘ContainerCreating’ status
The most common causes for this issue are:
- Missing configmaps referenced in volume mounts
- Missing secrets referenced in volume mounts
To diagnose this issue, use kubectl describe
on the pod and look at the events
at the bottom of the output. The following is an example that shows what to look
for:
$ kubectl describe pod example
### Output truncated for brevity
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 10s default-scheduler Successfully assigned kube-system/example-796885bff7-cf7nc to kind-control-plane
Warning FailedMount 3s (x5 over 10s) kubelet, kind-control-plane MountVolume.SetUp failed for volume "foo" : secret "foo" not found
Pods showing ‘ErrImagePull’ Pod status
The ErrImagePull
condition means that the node is unable to pull the container
image from the container image registry (e.g. Harbor). Some potential causes of
this issue:
- The registry is unavailable or inaccessible from the node
- The container image does not exist in the registry
- The container image specified in the deployment manifest is incorrect
Use the kubectl describe
command on the pod to troubleshoot this issue. The
events section at the bottom of the output should have useful context. The
following example shows what to look for:
$ kubectl describe pod example
### Output truncated for brevity
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 11s default-scheduler Successfully assigned kube-system/example-7cc7c59cbb-4h6cv to kind-control-plane
Normal Pulling 11s kubelet, kind-control-plane Pulling image "non-existent"
Warning Failed 10s kubelet, kind-control-plane Failed to pull image "non-existent": rpc error: code = Unknown desc = failed to pull and unpack image "docker.io/library/non-existent:latest": failed to resolve reference "docker.io/library/non-existent:latest": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
Warning Failed 10s kubelet, kind-control-plane Error: ErrImagePull
Normal BackOff 10s kubelet, kind-control-plane Back-off pulling image "non-existent"
Useful Commands
This section lists commands that are useful in day-to-day interactions with Kubernetes:
Listing resources
Use the kubectl get
command to list resources of one or more types:
kubectl get deployments,pods
Specify the wide
output format for additional information:
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cassandra-0 0/1 ContainerCreating 0 47s <none> kind-control-plane <none> <none>
redis-5c7c978f78-wlbkn 1/1 Running 0 27s 10.244.0.6 kind-control-plane <none> <none>
Use the --show-labels
to display the labels of resources
kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
cassandra-0 0/1 ContainerCreating 0 98s app=cassandra,chart=cassandra-5.4.2,controller-revision-hash=cassandra-6d7b4575f6,heritage=Helm,release=cassandra,statefulset.kubernetes.io/pod-name=cassandra-0
redis-5c7c978f78-wlbkn 1/1 Running 0 78s pod-template-hash=5c7c978f78,run=redis
Use the yaml
output format if you want to get the entire YAML definition of a
resource:
kubectl -n bow get deployment vendor-abstraction -o yaml
Getting application logs
Use the kubectl logs
command to get application logs.
kubectl -n bow logs <pod name>
To specify the container within the pod using the -c
flag:
kubectl -n bow logs vendor-abstraction -c tag-blink-servce
Use the -f
or --follow
flag to follow/tail the logs.
Forward local ports into a Pod
You can open forward local ports into the pod’s network using kubectl port-forward
. With this command, you essentially open a network tunnel into the
pod.
For example, if you have a pod that listens on port 9090, you can forward your local machines 8080 into the pod’s port 9090 using the following command:
kubectl -n bow port-forward zuul-gateway 8080:9090
Once this command is running, you can access the pod’s 9090 port via
localhost:8080
.
Exec into a running Pod
You can run commands within the context of your pod using kubectl exec
. Do
not use this to configure or modify application behavior at run time.
For example, to run ps -ef
in a container, you would run:
kubectl exec -it example-pod -- ps -ef
Note: Keep in mind that the container must have the binary you are trying to execute
(ps
in the above example). Otherwise, you will get an error.
Use Ephemeral Containers (alpha) if the binary is not available.
Get the documentation of a specific resource kind
You can get the documentation of a specific resource kind (e.g. Deployment
or
Pod
) using kubectl explain
. This command will fetch the API documentation of
the resource and display it in the terminal.
For example, to get the Pod
documentation:
kubectl explain pod
You can drill into specific fields within the resource. For example, to the get
pod’s spec
field documentation:
kubectl explain pod.spec