There are times when you need to quickly see what’s happening with your applications in Kubernetes. For this, reading the most recent log lines is the most immediate thought you might have. Well, a quick way to troubleshoot and explore logs is to use the kubectl logs command. With kubectl logs, you can even read logs as they’re generated and focus only on the most recent ones. You can also read logs from all containers in a pod or a deployment. In this post, I’ll show you different ways of reading logs from your application using the command line tool. I’m going to focus on teaching you how to tail the logs, or read the most recent log lines, with a few common scenarios. Before I dive into that, let me start by covering a few basic concepts.
What’s Kubectl?
kubectl is the Kubernetes command line tool you can use to interact with a cluster; it’s basically an interface to make the API calls in a simple way. With kubectl, you can do pretty much everything you need to operate a Kubernetes cluster. You can take a look at the most basic commands here. When you need to read logs from your application, you can use kubectl instead of having to access a server remotely. It’s very convenient, especially if you’re debugging your application locally or in a development environment. Notice that in a production environment, this command might not be of much use. Too many things happen in a live environment, and reading tons of logs this way won’t help.
Exploring the Kubectl Logs Command
Let’s explore the kubectl logs command. With this command, you can read the stderr (standard errors) and stdout (default output) logs a container is generating. There might be a chance where some information is not available through this command. The reason for that is because either the applications are not generating logs or something else happened and the container didn’t even start. You can get more information with the kubectl describe command and reading the events, but that’s a topic I won’t cover this time. The basic structure or list of options you can use with the kubectl logs command is the following:
kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER]
There are many other parameters you can use, but let’s explore a few:
- -f or –follow is how you get the logs to be streamed
- -p or –previous prints logs from a previous terminated container in a pod
- POD | TYPE/NAME is where you specify the pod name or a different object such as a Deployment object
- -c or –containeris how you read logs from a specific container if the pod has more than one
If you’d like to see what other options you have, go to the official Kubernetes docs.
What About the Tail Flag?
When you add the tail flag to the kubectl logs command, you can read the logs as soon as they’re generated. Additionally, you can specify the number of recent log lines you’d like to see. For instance, say you only want to keep an eye on the latest 30 log lines. The syntax of the command is the following:
kubectl logs --tail=[number] [POD | TYPE/NAME]
Let’s explore an example of how and when to use this flag. Create an NGINX deployment like this:
kubectl create deployment nginx --image=nginx
To get the most recent logs, or in other words, the latest 15 log lines from the bottom to the top, run this:
kubectl logs --tail=15 nginx-7854ff8877-j8f98
Then, you’ll get an output similar to this one:
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2024/02/04 06:29:36 [notice] 1#1: using the "epoll" event method
2024/02/04 06:29:36 [notice] 1#1: nginx/1.25.3
2024/02/04 06:29:36 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14)
2024/02/04 06:29:36 [notice] 1#1: OS: Linux 5.10.201-191.748.amzn2.x86_64
2024/02/04 06:29:36 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2024/02/04 06:29:36 [notice] 1#1: start worker processes
2024/02/04 06:29:36 [notice] 1#1: start worker process 29
2024/02/04 06:29:36 [notice] 1#1: start worker process 30
Notice that to get the NGINX logs, I had to specify the name of the pod. If you copy/paste that command, it won’t work. To get the name of a pod from a deployment, you need to query all pods from a deployment. This is because each pod gets an additional random suffix in the pod name. It’s not very convenient because when the pod I used before is terminated (due to a new deployment rollout), the command won’t work. Let’s see how we can fix that along with another set of useful commands.
Using Kubectl to Tail Logs
Let me share a few useful commands to get logs using the tail flag.
Getting Logs From a Deployment
It’s very common that your application is configured to run within a deployment. To get the most recent log lines from a deployment, you can do it this way:
kubectl logs --tail=15 deployment/nginx
Getting Logs From All Pods With a Certain Label
If the name of the deployment is hard to guess or changes constantly, you can also get the logs using a label selector. Following the same NGINX application we used before, you’d do it this way using the -l flag:
kubectl logs --tail=15 -l app=nginx
Getting Logs From a Specific Container Within a Pod
When there are multiple containers within a pod, you can get the logs from one specific container to reduce noise, like this using the -c flag:
kubectl logs --tail=15 nginx-7854ff8877-j8f98 -c nginx
Getting Logs From All Containers Within a Pod
There’s a flag called –all-containers you can use to get logs from all the containers from a pod, like this:
kubectl logs --tail=15 7854ff8877-j8f98 --all-containers
Getting the Most Recent Logs in Real Time
In case you want to see logs as they are generated, you can use the -f flag. However, as I said before, using this command might not be helpful when several logs are coming at the same time, something that usually happens in a distributed system getting production (live) traffic. But for non-production environments, where you can control the traffic, it’s useful. Here’s the command:
kubectl logs –tail=15 -l app=nginx –all-containers -f
Now you’ll see new logs coming as you send traffic to the NGINX pod. To stop reading logs, you can exit pressing Ctrl + C.
Getting Logs From the Latest X Minutes or Seconds
If you don’t want to get logs in a real-time manner, you can also get the most recent logs from a period of time. For example, you can get logs from the latest 30 seconds (30s), two minutes (2m), or even one hour (1h). To do so, you use the -since flag, like this:
kubectl logs --tail=15 -l app=nginx --all-containers -since=5m
Getting Logs From a Previous Container Restart
There are times when a container has been terminated and you’d like to get some logs for troubleshooting purposes. However, you’ll only get these logs if the pod is still there. To do so, you have the -p flag (or –previous) to see logs, including previous containers. The command looks like this:
kubectl logs --tail=15 -l app=nginx --all-containers -since=5m -p
Closing Words
As you can see, getting logs from your application in a Kubernetes ecosystem is straightforward. You can get logs in real time or only those from a recent period of time. And even if a container was terminated, you can still access that information (if the pod is still there). Troubleshooting in a local or dev environment using the above commands is very useful. However, when you need to do the same in a production environment where most likely you’ll be working in a more complex system, these commands might not be helpful. Therefore, in a production environment, I’d recommend you use a platform that covers the limitations I mentioned here, like getting logs from previous instances even if the pod doesn’t exist or getting context from other applications.
This post was written by David Snatch. David is a cloud architect focused on implementing secure continuous delivery pipelines using Terraform, Kubernetes, and any other awesome tech that helps customers deliver results.