Understanding Kubernetes: Events
In the last article of my Kubernetes series, we looked at debugging broken workloads. We saw that Kubernetes Events are often one of the first places to look when something doesn’t behave as expected. But what exactly are Events? Where do they come from? And what can they actually tell us? Let’s take a closer look.
What are Kubernetes Events?
Kubernetes Events are objects that record something that happened in the cluster. They are generated by different Kubernetes components when they observe a particular situation or take an action. A typical Event could look like this:
Normal Scheduled
Successfully assigned default/my-app-7f8c6d9f7b-x2k9m to node-2
Or:
Warning FailedScheduling
0/3 nodes are available: 3 Insufficient memory.
Events usually contain information such as a type, a reason, a message, and information about the object the Event relates to.
The two Event types we’ll encounter most often are:
Normal— something happened that is generally expected or informationalWarning— something happened that may indicate a problem
A Warning Event doesn’t necessarily mean that the workload is completely broken, though. But it’s a signal that something happened we might want to look into.
Where do Events come from?
One useful thing to understand is that Events don’t come from a single central component. Different parts of Kubernetes can create them. For example:
- the scheduler reports scheduling decisions and scheduling failures
- the kubelet reports things happening on a node, such as container starts, image pulls or probe failures
- controllers report changes and failures related to the resources they manage
- other Kubernetes components and controllers, as well as custom controllers and operators, can create Events for their own actions
This is why Events can give us a useful view into what Kubernetes itself is doing.
For example, when creating a Pod, we might see:
Normal Scheduled
Successfully assigned default/web-6f7d9c8b6f-4xk2m to node-2
Normal Pulling
Pulling image "nginx:1.29"
Normal Pulled
Successfully pulled image "nginx:1.29"
Normal Created
Created container: nginx
Normal Started
Started container nginx
Reading these Events in order gives us a rough idea of what happened: The Pod was scheduled, the image was pulled, the container was created and then started. If something goes wrong somewhere along the way, the Events can help us see where the process stopped.
Looking at Events
We’ve already seen Events as part of kubectl describe. For example:
kubectl describe pod my-app
will give us the Events section at the bottom of the output. But we can also query Events directly via
kubectl get events
or sort them by the time they occurred:
kubectl get events --sort-by=.lastTimestamp
This can be particularly useful when we’re trying to understand what happened across several objects and not just one Pod. For example
LAST SEEN TYPE REASON OBJECT MESSAGE
2m Normal Scheduled pod/web-... Successfully assigned...
2m Normal Pulling pod/web-... Pulling image...
2m Normal Pulled pod/web-... Successfully pulled...
2m Normal Created pod/web-... Created container...
2m Normal Started pod/web-... Started container...
30s Warning Unhealthy pod/web-... Readiness probe failed...
gives us a rough timeline of what Kubernetes observed within our cluster.
In a very busy cluster, we can also narrow down events to either a particular object
kubectl get events -n my-namespace --field-selector involvedObject.name=my-app
or a particular namespace:
kubectl get events -n my-namespace
A real-world example: FailedScheduling
Let’s say we create a Deployment and notice that its Pods never leave Pending:
kubectl get pods
NAME READY STATUS RESTARTS AGE
my-app-7f8c6d9f7b-x2k9m 0/1 Pending 0 2m
The Pod isn’t running, but that doesn’t tell us why.
So we check the Events
kubectl get events --sort-by=.lastTimestamp
and find:
Warning FailedScheduling
0/3 nodes are available: 3 Insufficient memory.
We can see that the problem isn’t the application container - it hasn’t even started yet. Instead, the scheduler couldn’t find a node where the Pod could be placed. This is a good example of why Events are useful: they can tell us what Kubernetes tried to do before the workload ever got to the point where application logs exist.
Another example: image pulling
Events can also help when a container can’t start because Kubernetes can’t pull its image. For exampl, we might see events like:
Normal Pulling
Pulling image "my-registry.example.com/my-app:v42"
Warning Failed
Failed to pull image "my-registry.example.com/my-app:v42"
Warning Failed
Error: ImagePullBackOff
This Event points us towards the image itself - maybe the image name or tag is incorrect or there are authentication issues with the registry. Or something completely different. While the Event itself doesn’t necessarily tell us the complete root cause, it still gives us the next place to investigate.
Events can tell a story
One of the things I find most useful about Events is that they can help us reconstruct what Kubernetes was doing. Imagine we have a Pod that isn’t serving traffic.
The Events might show:
Normal Scheduled
Successfully assigned default/web-... to node-2
Normal Pulled
Successfully pulled image "my-app:v1"
Normal Created
Created container: web
Normal Started
Started container web
Warning Unhealthy
Readiness probe failed: HTTP probe failed with statuscode: 503
This tells us quite a lot: The Pod was scheduled successfully. The image was pulled. The container started. But the readiness probe is failing. That means we want to look at the application, its configuration, or the readiness probe itself.
But Events are not logs - and don’t stick around forever
It’s important not to confuse Events with application logs. Events are short, high-level records of things Kubernetes noticed or did. They aren’t intended to contain the complete history of everything that happened, but they will give us clues where to check first.
There is another important limitation: Events are not a permanent audit log. Kubernetes Events have a limited lifetime and can be removed after a certain amount of time. The exact retention behaviour depends on the Kubernetes setup and configuration.
Which also means: Events are primarily useful for understanding recent activity. If something happened several days ago, we shouldn’t expect to be able to query the cluster and reconstruct the entire history from Events. This is one reason why Events shouldn’t replace proper logging, monitoring or auditing.
Not every Warning Event means our application is broken
Kubernetes is constantly reconciling the desired state with the current state. During that process, things can temporarily fail and then recover. For example, we might see a warning because a probe failed once, followed shortly afterwards by a successful probe. Or a controller might temporarily encounter a problem and recover on its next reconciliation loop.
That also means not every Warning needs immediate action. What is important is to put it into context:
- What object generated the Event?
- What is the reason?
- When did it happen?
- Is it happening repeatedly?
- Did something happen afterwards that resolved the problem?
- Does the current state of the object still indicate a problem?
Summing up
Kubernetes Events are one of those small pieces of Kubernetes that become really useful once we know what we’re looking at. They can show us what Kubernetes components noticed, what actions they took, and where something started to go wrong. They can be especially useful when a workload hasn’t even reached the point where application logs are available.
But Events are clues, not a complete history. They have limited retention, don’t replace logs or metrics, and often won’t tell us the full root cause. We could hence think about them like this: Events help us understand what Kubernetes saw happening. And when something goes wrong, that can be exactly the piece of the puzzle we need. :)
header image created by buddy ChatGPT
