kubectl describe 最底下那几行 Events 是从哪来的?为什么崩溃的 Pod 每次重启不会让事件越攒越多?这篇用一个反复崩溃的 Pod 观察 Event 对象的 count 递增、两套 API 里的字段、etcd 里的过期机制,以及 Pod 删除之后事件还在的现象。
20 秒时 kubectl get events -n k16 有 5 个 Event 对象:
reason=Scheduled type=Normal count=1 first=2026-10-10T09:08:37Z last=2026-10-10T09:08:37Z
reason=Pulled type=Normal count=3 first=2026-10-10T09:08:38Z last=2026-10-10T09:08:50Z
reason=Created type=Normal count=3 first=2026-10-10T09:08:38Z last=2026-10-10T09:08:50Z
reason=Started type=Normal count=3 first=2026-10-10T09:08:38Z last=2026-10-10T09:08:51Z
reason=BackOff type=Warning count=2 first=2026-10-10T09:08:40Z last=2026-10-10T09:08:51Z
100 秒时有 5 个 Event 对象:
reason=Scheduled type=Normal count=1 first=2026-10-10T09:08:37Z last=2026-10-10T09:08:37Z
reason=Pulled type=Normal count=5 first=2026-10-10T09:08:38Z last=2026-10-10T09:10:04Z
reason=Created type=Normal count=5 first=2026-10-10T09:08:38Z last=2026-10-10T09:10:04Z
reason=Started type=Normal count=5 first=2026-10-10T09:08:38Z last=2026-10-10T09:10:05Z
reason=BackOff type=Warning count=4 first=2026-10-10T09:08:40Z last=2026-10-10T09:10:05Z
同一个 Event 对象(名字不变)count 变大的有 4 个:Pulled 3→5, Created 3→5, Started 3→5, BackOff 2→4容器 exit 1 后被 kubelet 按退避时间不停重启。20 秒时有 5 个 Event 对象,100 秒时仍然是 5 个——Created、Pulled、Started 从 count=3 涨到 5,BackOff 从 2 涨到 4,名字不变,lastTimestamp 不断更新,firstTimestamp 保持第一次的时间。kubelet 的事件记录器把“同一个来源、同一个对象、同一个原因和消息”的事件合并成一个对象,而不是每次新建一个。
事件对象 crash.18dd1feacbf4fdde(reason=BackOff)
core/v1: count=4 firstTimestamp=2026-10-10T09:08:40Z lastTimestamp=2026-10-10T09:10:05Z source={'component': 'kubelet', 'host': 'kx-main-worker2'} reportingComponent=kubelet involvedObject=Pod/crash
events.k8s.io: eventTime=None series=None deprecatedCount=4 deprecatedFirstTimestamp=2026-10-10T09:08:40Z reportingController=kubelet regarding=Pod/crash
两套 API 读的是同一份存储:True(uid 相同)同一个 BackOff 事件从 core/v1 读,count=4、firstTimestamp、lastTimestamp 和 source.component=kubelet 都在顶层;从 events.k8s.io/v1 读,新 API 的 eventTime、series 是空的,这些信息放在 deprecatedCount、deprecatedFirstTimestamp 里,reportingController=kubelet。两者 uid 相同,是同一份存储的两个视图;写 Event 的组件用旧的记录方式,新 API 的 series 就不会有值。
etcd key /registry/events/k16/crash.18dd1feacbf4fdde:lease=非 0(532aa124d675144d) etcdctl lease timetolive:lease 532aa124d675144d granted with TTL(3660s), remaining(3646s) 对比:一个 Pod 的 key(/registry/pods/kube-system/coredns-559f6c778d-g7z75)的 lease=0(没有过期时间)
etcd 里 /registry/events/… 的每个 key 都绑着一个 lease:etcdctl lease timetolive 显示 granted with TTL(3660s),到点 etcd 自己删除,不需要任何控制器清理;而 Pod 的 key lease=0,永不过期。所以事件只能回溯大约一小时。
Pod crash 已经删除(Error from server (NotFound): pods "crash" not found);kubectl get events 仍然有 5 个对象,involvedObject 都指向 ['crash'] kubectl events --for pod/crash:LAST SEEN TYPE REASON OBJECT MESSAGE | 104s Normal Scheduled Pod/crash Successfully assigned k16/crash to kx-main-worker2 | 17s (x5 over 103s) Normal Pulled Pod/crash Container image "busybox:1.36" already present on machine and can | 17s (x5 over 103s) Normal Created Pod/crash Container created kubectl describe pod crash:Error from server (NotFound): pods "crash" not found
删除 Pod 之后 kubectl get pod 和 kubectl describe pod 都是 NotFound,但 5 个 Event 对象仍在,kubectl events --for pod/crash 能看到完整的时间线(Pulled 一行是 x5 over 103s)。排查“已经被删掉的 Pod 为什么重启”时,事件往往是唯一的线索;而它不是持久的,一小时后就没有了。