Debugging Kubernetes

Recently I’ve been setting up a k8s cluster in EKS and deploying vendor provided helm charts into it. We’ve often had to debug issues and I’ve learnt a number of useful commands to help with this along the way

Helpful Setup

Autocomplete

Consider using the fish shell for the great auto completion experience it provides. Completions are not just for commands, but for names of items within the cluster too. This helps with easily TAB to complete the randomly generated suffixes of pod names from their source name (the prefix beginning the deployment or daemonset name etc)

Details on setting up kubectl completions

Details on setting up helm completions

Both tools also support completions on bash, zsh and powershell if you use those

Context

It can become a pain constantly needing to specify -n <your namespace> with every command

Set the context to the namespace you need to interact with most

kubectl config set-context --current --namespace=my-namespace
kubectl config view | grep namespace:

If you need to revert it

kubectl config set-context --current --namespace=""

High level overviews

To get the initial context, check through the common resource to see if anything is flagging up as odd

kubectl get <pods/deployments/ds/rs/services/jobs> # or any other kind of resources

You can comma separate to get multiple at once

kubectl get ds,deployments,rs,statefulsets

Sometimes it’s helpful to output the results as yaml to inspect it or edit and redeploy to test things

kubectl get deployment <your-deployment> -o yaml > deployment-to-play-with.yaml

This can also pair well with the yq CLI for querying specific contents from large yaml docs

kubectl get deployment <your-deployment> -o yaml | yq '.spec.template.spec.containers'

Often useful additional info is found with the wide output:

  • Pods: the node they are running on
  • Service: the exposed hostname (can be pending if there are issues with the cloud load balancer integration)
kubectl get <object> -o wide

Other useful flags

-o json
-o jsonpath='{.path.to.json.object}'  # Another way to query  
-A                                    # All namespaces

Cluster Resource Utilisation

CPU and memory usage

kubectl top node

Digging Deeper

Describe

If your objects are having trouble getting set up by k8s, you’ll often find useful info in the events section of describe

kubectl describe <Kind> 
Logs

If kubectl get pods shows crash looping then it’s likely the application code within a pod/container that’s erroring, so check the logs

kubectl logs <your pod>

kubectl logs <your pod> -c <your container within the pod>

If you’re not sure of the name of the container in the pod, just kubectl logs <your pod> and it will show you the names of the other logs in the pod if they exist before it outputs the logs from the main container

Because k8s will try to restart the pod, it’s often helpful to review the logs from the previous run, before the restart, so that you get the full logs

kubectl logs <your pod> --previous  # short flag -p

Other useful flags

-f, --follow  # tail the log
--tail <int>  # number of previous lines, defaults to all logs (-1)
Port forwarding

To check if an application is working correctly or the networking to it is the issue, you can short cut the cluster networking at many places and directly connect to it from your local machine.

# kubectl port-forward <object>/<object name> <local port>:<remote port>

kubectl port-forward pods/<your pod> 8080:80  # pods/ is implicit so not needed
kubectl port-forward deployment/<your deployment> 8080:80
kubectl port-forward service/<your service> 8080:80
Secrets

Checking the values of secrets requires base64 decoding them

kubectl get secret <your secret> -o jsonpath='{.data.<path.to.secret.value>}' | base64 -d
Accessing a running container

Sometimes you just need to poke around inside a container to see what’s going on

kubectl exec --stdin --tty <your pod> -- /bin/bash # or /bin/sh