v1containerstateterminated是kubernetes中描述容器已终止状态的数据模型,对应api中的v1.containerstateterminated,用于承载退出码、原因、消息等诊断字段;其完整实现位于kubernetes/client/models/和aio/client/models/目录下,需通过pod.status.containerstatuses[i].state.terminated访问。

Pod.Status.ContainerStatuses 里查 State.Terminated
Go 客户端获取 Pod 后,终止状态不在 Pod.Status.Phase(它只反映整体生命周期,如 Running、Succeeded),而藏在每个容器的详细状态里。核心路径是:pod.Status.ContainerStatuses[i].State.Terminated —— 只有这个字段非 nil,才说明该容器已终止。
注意:一个 Pod 里多个容器可能状态不一致,比如主容器退出了,init 容器早已成功完成,sidecar 还在运行。必须遍历 ContainerStatuses 切片逐个判断。
-
Terminated字段为 nil?说明容器没终止过(还在Running或刚启动) - 即使容器退出码是 0,
Terminated.ExitCode也会被设为0,不能靠是否为 0 来判断“是否终止” - 如果容器正在重启中(CrashLoopBackOff),
State.Waiting非 nil,State.Terminated为 nil;上一次终止记录保留在pod.Status.ContainerStatuses[i].LastTerminationState.Terminated
用 client-go 获取时别漏掉 Watch 或 List 的完整字段
默认 Get 请求可能因服务端优化省略部分嵌套结构,尤其是 Terminated.Reason 或 Terminated.Message。确保你调用的是完整资源对象:
pod, err := clientset.CoreV1().Pods(namespace).Get(ctx, name, metav1.GetOptions{
// 不需要额外参数,但要注意:v1.22+ 默认返回全部字段
})
如果发现 Terminated 字段总是 nil,检查是否误用了 Watch 的 partial object(比如从 event.Object 直接断言为 *corev1.Pod 而没做 deep copy),或用了 FieldSelector 过滤导致字段被裁剪。
- 本地调试时,先用
kubectl get pod -o yaml确认 YAML 里确实存在containerStatuses[*].state.terminated块 - 若使用
Informers,确保 ListFunc 返回的是完整 Pod 对象(默认是),不要在 TransformFunc 中意外清空Status - 集群版本低于 v1.19 时,
Terminated.Signal字段可能为空(K8s 不暴露信号值),别依赖它做判断
Terminated.Reason 和 Terminated.ExitCode 的典型取值含义
这两个字段组合能帮你快速定位退出原因,但它们不是全量覆盖所有场景:
-
Reason="OOMKilled":内存超限被 cgroup kill,ExitCode通常为 137(SIGKILL) -
Reason="Error":容器进程主动退出且非 0 码,ExitCode即实际返回值 -
Reason="Completed":正常结束(如 Job 容器执行完命令),ExitCode=0 -
Reason=""(空字符串) +ExitCode=0:常见于容器启动后立刻静默退出,可能是 CMD 写错或入口脚本没阻塞 -
Terminated.Message有时含 runtime 日志摘要(如 containerd 的 "failed to create container"),但不可靠,优先看 events
注意:Reason 是 K8s 自己归纳的字符串,不是 Docker 或 containerd 原始事件,不能和 docker inspect 的 Status 直接对齐。
想查历史终止记录?得看 LastTerminationState
当前 State.Terminated 只反映最近一次终止(如果容器当前处于 terminated 状态)。但如果容器正在重启循环,当前状态是 Waiting,那上次退出详情就得从 LastTerminationState.Terminated 拿:
if status.LastTerminationState.Terminated != nil {
t := status.LastTerminationState.Terminated
log.Printf("Last exit: %d, reason: %s", t.ExitCode, t.Reason)
}
这个字段在每次容器重启前由 kubelet 更新,比直接查 events 更及时,也比轮询 kubectl describe pod 更轻量。
- 如果容器从未终止过,
LastTerminationState是零值(nil),别 panic 解引用 - Job/CronJob 的 Pod 在成功完成后,
State.Terminated存在,LastTerminationState也为 nil —— 因为没有“下一次”,所以只用看前者 - 某些异常场景(如节点失联后重建 Pod),
LastTerminationState可能丢失,此时需 fallback 到 Event API 查Failed类型事件
真正麻烦的是多容器协同退出的时序问题:比如主容器因 panic 退出,init 容器早已完成,sidecar 正在优雅关闭——三个 Terminated 时间戳、退出码、reason 全不同,得按业务语义自己聚合判断。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











