Hello, I'm Zhang Jintao.
I wrote an article before More elegant Kubernetes cluster event measurement scheme , Jaeger uses tracing to collect and display events in Kubernetes cluster. The final effect is as follows:
When I wrote that article, I set up a flag to introduce the principle in detail. It's been a long time. Now it's the end of the year, and it's time to send it out.
Eents overview
Let's take a simple example to see what events are in the Kubernetes cluster.
Create a new namespace called moelove, and then create a deployment called redis in it. Next, look at all the events in this namespace.
(MoeLove) ➜ kubectl create ns moelove namespace/moelove created (MoeLove) ➜ kubectl -n moelove create deployment redis --image=ghcr.io/moelove/redis:alpine deployment.apps/redis created (MoeLove) ➜ kubectl -n moelove get deploy NAME READY UP-TO-DATE AVAILABLE AGE redis 1/1 1 1 11s (MoeLove) ➜ kubectl -n moelove get events LAST SEEN TYPE REASON OBJECT MESSAGE 21s Normal Scheduled pod/redis-687967dbc5-27vmr Successfully assigned moelove/redis-687967dbc5-27vmr to kind-worker3 21s Normal Pulling pod/redis-687967dbc5-27vmr Pulling image "ghcr.io/moelove/redis:alpine" 15s Normal Pulled pod/redis-687967dbc5-27vmr Successfully pulled image "ghcr.io/moelove/redis:alpine" in 6.814310968s 14s Normal Created pod/redis-687967dbc5-27vmr Created container redis 14s Normal Started pod/redis-687967dbc5-27vmr Started container redis 22s Normal SuccessfulCreate replicaset/redis-687967dbc5 Created pod: redis-687967dbc5-27vmr 22s Normal ScalingReplicaSet deployment/redis Scaled up replica set redis-687967dbc5 to 1
However, we will find that kubectl get events are not arranged in the order of events by default, so we often need to add the -- sort by = '{. Metadata. Creationtimestamp}' parameter to make its output arranged by time.
That's why kubernetes v1 The reason why the kubectl alpha events command will be added in version 23. I was in the previous Article "K8S ecological weekly | Kubernetes v1.23.0 officially released, list of new features" It has been described in detail in, so it will not be expanded here.
After sorting by time, you can see the following results:
(MoeLove) ➜ kubectl -n moelove get events --sort-by='{.metadata.creationTimestamp}' LAST SEEN TYPE REASON OBJECT MESSAGE 2m12s Normal Scheduled pod/redis-687967dbc5-27vmr Successfully assigned moelove/redis-687967dbc5-27vmr to kind-worker3 2m13s Normal SuccessfulCreate replicaset/redis-687967dbc5 Created pod: redis-687967dbc5-27vmr 2m13s Normal ScalingReplicaSet deployment/redis Scaled up replica set redis-687967dbc5 to 1 2m12s Normal Pulling pod/redis-687967dbc5-27vmr Pulling image "ghcr.io/moelove/redis:alpine" 2m6s Normal Pulled pod/redis-687967dbc5-27vmr Successfully pulled image "ghcr.io/moelove/redis:alpine" in 6.814310968s 2m5s Normal Created pod/redis-687967dbc5-27vmr Created container redis 2m5s Normal Started pod/redis-687967dbc5-27vmr Started container redis
Through the above operations, we can find that events is actually a resource in the Kubernetes cluster. When the resource state in the Kubernetes cluster changes, new events can be generated.
Drill down to Events
Single Event object
Since events is a resource in the Kubernetes cluster, its metadata Name should contain its name for individual operations. So we can output its name with the following command:
(MoeLove) ➜ kubectl -n moelove get events --sort-by='{.metadata.creationTimestamp}' -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' redis-687967dbc5-27vmr.16c4fb7bde8c69d2 redis-687967dbc5.16c4fb7bde6b54c4 redis.16c4fb7bde1bf769 redis-687967dbc5-27vmr.16c4fb7bf8a0ab35 redis-687967dbc5-27vmr.16c4fb7d8ecaeff8 redis-687967dbc5-27vmr.16c4fb7d99709da9 redis-687967dbc5-27vmr.16c4fb7d9be30c06
Select any event record and output it to YAML format for viewing:
(MoeLove) ➜ kubectl -n moelove get events redis-687967dbc5-27vmr.16c4fb7bde8c69d2 -o yaml action: Binding apiVersion: v1 eventTime: "2021-12-28T19:31:13.702987Z" firstTimestamp: null involvedObject: apiVersion: v1 kind: Pod name: redis-687967dbc5-27vmr namespace: moelove resourceVersion: "330230" uid: 71b97182-5593-47b2-88cc-b3f59618c7aa kind: Event lastTimestamp: null message: Successfully assigned moelove/redis-687967dbc5-27vmr to kind-worker3 metadata: creationTimestamp: "2021-12-28T19:31:13Z" name: redis-687967dbc5-27vmr.16c4fb7bde8c69d2 namespace: moelove resourceVersion: "330235" uid: e5c03126-33b9-4559-9585-5e82adcd96b0 reason: Scheduled reportingComponent: default-scheduler reportingInstance: default-scheduler-kind-control-plane source: {} type: Normal
You can see that it contains a lot of information. We won't expand it here first. Let's look at another example.
Events in kubectl describe
We can perform the describe operation on the Deployment object and Pod object respectively, and the following results can be obtained (the intermediate output is omitted):
- Operation on Deployment
(MoeLove) ➜ kubectl -n moelove describe deploy/redis Name: redis Namespace: moelove ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 15m deployment-controller Scaled up replica set redis-687967dbc5 to 1
- Operation on Pod
(MoeLove) ➜ kubectl -n moelove describe pods redis-687967dbc5-27vmr Name: redis-687967dbc5-27vmr Namespace: moelove Priority: 0 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 18m default-scheduler Successfully assigned moelove/redis-687967dbc5-27vmr to kind-worker3 Normal Pulling 18m kubelet Pulling image "ghcr.io/moelove/redis:alpine" Normal Pulled 17m kubelet Successfully pulled image "ghcr.io/moelove/redis:alpine" in 6.814310968s Normal Created 17m kubelet Created container redis Normal Started 17m kubelet Started container redis
We can find that when we describe different resource objects, the events we can see are directly related to ourselves. When describing deployment, no events related to Pod can be seen.
This shows that the Event object contains the information of the resource object it describes, and they are directly related.
Combined with the single Event object we saw earlier, we found that the content in the involvedObject field is the information of the resource object associated with the Event.
Learn more about Events
Let's take a look at the following example to create a Deployment, but use a nonexistent image:
(MoeLove) ➜ kubectl -n moelove create deployment non-exist --image=ghcr.io/moelove/non-exist deployment.apps/non-exist created (MoeLove) ➜ kubectl -n moelove get pods NAME READY STATUS RESTARTS AGE non-exist-d9ddbdd84-tnrhd 0/1 ErrImagePull 0 11s redis-687967dbc5-27vmr 1/1 Running 0 26m
We can see that the current Pod is in an erimagepull state. View the events in the current namespace (I omitted the previous deploy/redis record)
(MoeLove) ➜ kubectl -n moelove get events --sort-by='{.metadata.creationTimestamp}' LAST SEEN TYPE REASON OBJECT MESSAGE 35s Normal SuccessfulCreate replicaset/non-exist-d9ddbdd84 Created pod: non-exist-d9ddbdd84-tnrhd 35s Normal ScalingReplicaSet deployment/non-exist Scaled up replica set non-exist-d9ddbdd84 to 1 35s Normal Scheduled pod/non-exist-d9ddbdd84-tnrhd Successfully assigned moelove/non-exist-d9ddbdd84-tnrhd to kind-worker3 17s Warning Failed pod/non-exist-d9ddbdd84-tnrhd Error: ErrImagePull 17s Warning Failed pod/non-exist-d9ddbdd84-tnrhd Failed to pull image "ghcr.io/moelove/non-exist": rpc error: code = Unknown desc = failed to pull and unpack image "ghcr.io/moelove/non-exist:latest": failed to resolve reference "ghcr.io/moelove/non-exist:latest": failed to authorize: failed to fetch anonymous token: unexpected status: 403 Forbidden 18s Normal Pulling pod/non-exist-d9ddbdd84-tnrhd Pulling image "ghcr.io/moelove/non-exist" 4s Warning Failed pod/non-exist-d9ddbdd84-tnrhd Error: ImagePullBackOff 4s Normal BackOff pod/non-exist-d9ddbdd84-tnrhd Back-off pulling image "ghcr.io/moelove/non-exist"
Perform the describe operation on this Pod:
(MoeLove) ➜ kubectl -n moelove describe pods non-exist-d9ddbdd84-tnrhd ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 4m default-scheduler Successfully assigned moelove/non-exist-d9ddbdd84-tnrhd to kind-worker3 Normal Pulling 2m22s (x4 over 3m59s) kubelet Pulling image "ghcr.io/moelove/non-exist" Warning Failed 2m21s (x4 over 3m59s) kubelet Failed to pull image "ghcr.io/moelove/non-exist": rpc error: code = Unknown desc = failed to pull and unpack image "ghcr.io/moelove/non-exist:latest": failed to resolve reference "ghcr.io/moelove/non-exist:latest": failed to authorize: failed to fetch anonymous token: unexpected status: 403 Forbidden Warning Failed 2m21s (x4 over 3m59s) kubelet Error: ErrImagePull Warning Failed 2m9s (x6 over 3m58s) kubelet Error: ImagePullBackOff Normal BackOff 115s (x7 over 3m58s) kubelet Back-off pulling image "ghcr.io/moelove/non-exist"
We can find that the output here is different from that of running Pod correctly before. The main difference is in the Age column. Here we see an output like 115s (x7 over 3m58s).
Its meaning indicates that this type of event has occurred 7 times in 3m58s, and the latest one occurred before 115s
But when we went to kubectl get events directly, we didn't see events repeated seven times. This means that Kubernetes will automatically merge duplicate events.
Select the last Events method (as mentioned earlier) and output its contents in YAML format:
(MoeLove) ➜ kubectl -n moelove get events non-exist-d9ddbdd84-tnrhd.16c4fce570cfba46 -o yaml apiVersion: v1 count: 43 eventTime: null firstTimestamp: "2021-12-28T19:57:06Z" involvedObject: apiVersion: v1 fieldPath: spec.containers{non-exist} kind: Pod name: non-exist-d9ddbdd84-tnrhd namespace: moelove resourceVersion: "333366" uid: 33045163-146e-4282-b559-fec19a189a10 kind: Event lastTimestamp: "2021-12-28T18:07:14Z" message: Back-off pulling image "ghcr.io/moelove/non-exist" metadata: creationTimestamp: "2021-12-28T19:57:06Z" name: non-exist-d9ddbdd84-tnrhd.16c4fce570cfba46 namespace: moelove resourceVersion: "334638" uid: 60708be0-23b9-481b-a290-dd208fed6d47 reason: BackOff reportingComponent: "" reportingInstance: "" source: component: kubelet host: kind-worker3 type: Normal
Here, we can see that its field includes a count field, indicating how many times similar events have occurred. And first timestamp and last timestamp respectively indicate the time when the event first appeared and last appeared. This explains the duration of events in the previous output.
Thoroughly understand Events
The following is a random selection from Events. We can see some field information contained in it:
apiVersion: v1 count: 1 eventTime: null firstTimestamp: "2021-12-28T19:31:13Z" involvedObject: apiVersion: apps/v1 kind: ReplicaSet name: redis-687967dbc5 namespace: moelove resourceVersion: "330227" uid: 11e98a9d-9062-4ccb-92cb-f51cc74d4c1d kind: Event lastTimestamp: "2021-12-28T19:31:13Z" message: 'Created pod: redis-687967dbc5-27vmr' metadata: creationTimestamp: "2021-12-28T19:31:13Z" name: redis-687967dbc5.16c4fb7bde6b54c4 namespace: moelove resourceVersion: "330231" uid: 8e37ec1e-b3a1-420c-96d4-3b3b2995c300 reason: SuccessfulCreate reportingComponent: "" reportingInstance: "" source: component: replicaset-controller type: Normal
The meanings of the main fields are as follows:
- count: indicates how many times similar events have occurred (described earlier)
- involvedObject: the resource object directly associated with this event (described earlier). The structure is as follows:
type ObjectReference struct { Kind string Namespace string Name string UID types.UID APIVersion string ResourceVersion string FieldPath string }
- source: directly related components, with the following structure:
type EventSource struct { Component string Host string }
- reason: a simple summary (or a fixed code) is more suitable for screening conditions, mainly for machine-readable. At present, there are more than 50 such codes;
- message: give a more readable and detailed description
- type: Currently, there are only two types: Normal and Warning, and their meanings are also written in the source code:
// staging/src/k8s.io/api/core/v1/types.go const ( // Information only and will not cause any problems EventTypeNormal string = "Normal" // These events are to warn that something might go wrong EventTypeWarning string = "Warning" )
Therefore, when we collect these Events as a tracking span, we can classify them according to their source, associate them by involvedObject, and sort them by time.
summary
In this article, I mainly introduce the actual role of Events object and the meaning of its fields through two examples, a correctly deployed Deploy and a Deploy without image deployment.
For Kubernetes, Events contains a lot of useful information, but these information will not have any impact on Kubernetes, and they are not the actual log of Kubernetes. By default, the logs in Kubernetes will be cleaned up after 1 hour to free up the resource occupation of etcd.
Therefore, in order to better let the Cluster Administrator know what happened, we usually collect the events of Kubernetes cluster in the production environment. The tools I personally recommend are: https://github.com/opsgenie/k...
Of course, you can also follow my previous article More elegant Kubernetes cluster event measurement scheme , Jaeger uses tracing to collect and display events in Kubernetes cluster.
Welcome to subscribe my official account number [MoeLove].