适用于 Kubernetes 1.24+、kubectl 1.24+。先用 kubectl version 记录客户端和服务端版本,并确认 kubectl 与服务端的版本偏差在官方支持范围内。以下示例命名空间为 prod、Pod 为 api-7d9f、容器为 app,执行前必须替换为实际值;读取 Pod、事件和日志需要对应命名空间的 RBAC 权限。先保留失败现场,不要一开始就删除 Pod、扩大资源限额或关闭探针。
1. 先确认是哪个容器、哪一次退出
CrashLoopBackOff 表示 kubelet 正在延迟下一次重启,不是根因。一个 Pod 可能包含多个业务容器、边车和 init 容器,应先固定对象与时间线:
date -u
kubectl version
kubectl -n prod get pod api-7d9f -o wide
kubectl -n prod describe pod api-7d9f
kubectl -n prod get pod api-7d9f -o jsonpath='{range .status.initContainerStatuses[*]}init/{.name}{"\t"}{.state.waiting.reason}{"\t"}{.lastState.terminated.reason}{"\t"}{.lastState.terminated.exitCode}{"\n"}{end}{range .status.containerStatuses[*]}container/{.name}{"\t"}{.restartCount}{"\t"}{.state.waiting.reason}{"\t"}{.lastState.terminated.reason}{"\t"}{.lastState.terminated.exitCode}{"\n"}{end}'
重点记录 restartCount、当前 state、lastState.terminated.reason、exitCode、开始与结束时间。Completed 对长驻服务可能意味着入口命令正常退出但不符合工作负载模型;Error 需要结合应用日志解释;OOMKilled 才直接指向容器内存限制相关路径。退出码 137 常对应 SIGKILL,但不能脱离 reason、节点日志和时间线直接断定是内存耗尽。
2. 读取上一次实例的日志
容器已经重启时,当前日志可能只有新一轮启动内容,优先读取上一次终止实例:
kubectl -n prod logs api-7d9f -c app --previous --timestamps
kubectl -n prod logs api-7d9f -c app --timestamps
kubectl -n prod get events \
--field-selector involvedObject.kind=Pod,involvedObject.name=api-7d9f \
--sort-by=.metadata.creationTimestamp
--previous 只保留前一个已终止实例的日志;节点重启、容器运行时回收或日志轮转后可能不可用。事件也有保留期限,因此应在故障窗口尽早采集。不要在论坛或工单中直接粘贴完整环境变量、Secret、令牌或连接串。
若应用在写日志前就退出,继续检查镜像入口、参数、挂载和安全上下文,而不是把“日志为空”当作没有失败。
3. 核对实际生效的工作负载配置
先找到 Pod 的控制器,再查看当前对象,不要只看本地清单:
kubectl -n prod get pod api-7d9f \
-o jsonpath='{range .metadata.ownerReferences[*]}{.kind}{"/"}{.name}{"\n"}{end}'
kubectl -n prod get pod api-7d9f -o yaml
kubectl -n prod get deploy api -o yaml
kubectl -n prod rollout history deploy/api
逐项核对 image 与摘要、command、args、workingDir、环境变量来源、ConfigMap/Secret 引用、卷挂载、securityContext 和资源限制。Kubernetes 的 command/args 不会自动经过交互式 shell 解释;需要管道、重定向或变量展开时,应明确使用可审计的脚本或 shell,并正确处理信号转发。
CreateContainerConfigError、ImagePullBackOff 和卷挂载失败发生在应用进程启动前,不属于同一条应用退出路径,应以 describe 中的事件为主,检查对象名、键名、镜像凭据、PVC 与节点挂载错误。
4. 区分内存终止与探针触发的重启
kubectl -n prod get pod api-7d9f \
-o jsonpath='{range .spec.containers[?(@.name=="app")]}{.resources}{"\n"}{.startupProbe}{"\n"}{.livenessProbe}{"\n"}{.readinessProbe}{"\n"}{end}'
kubectl -n prod describe pod api-7d9f
出现 OOMKilled 时,对齐容器 limits.memory、工作集监控、应用堆限制和节点内存压力。先确认是容器 cgroup 超限还是节点侧驱逐;仅增加 limit 可能掩盖泄漏,也可能让节点承受更大风险。
readinessProbe 失败只会让 Pod 暂停接收流量,不会直接重启容器;livenessProbe 连续失败会触发重启。慢启动应用应考虑与真实启动上界匹配的 startupProbe,避免存活探针在初始化完成前反复终止进程。检查 path、port、scheme、超时和失败阈值,并从 Pod 所在网络与进程监听方式解释结果,不要只在运维终端访问一次就判定探针正确。
5. 验证修复而不是只看 Running
修正控制器模板后观察一次受控发布:
kubectl -n prod rollout status deploy/api --timeout=5m
kubectl -n prod get pods -l app=api -w
kubectl -n prod get deploy api
kubectl -n prod get events --sort-by=.metadata.creationTimestamp
Running 只表示 Pod 已分配且至少有容器在运行,不等于应用可用。闭环应同时满足:新 Pod 达到预期 Ready 数,观察窗口内 restartCount 不再增长,没有新的异常终止或探针失败事件,发布状态完成,并且从真实服务入口执行的受控健康检查和关键请求恢复。若回滚是既定处置流程,应先记录失败版本、镜像摘要和相关日志,再按工作负载的发布策略执行,避免丢失根因证据。