exitCode 137 表示容器被 SIGKILL(信号9)终止,极大概率是 cgroup 内存超限触发 OOM Killer;需结合 kubectl describe 查 OOMKilled 字段、dmesg 日志及 memory.stat 中 rss 值综合判定。

看 exitCode 137 就知道是内存超限了
Go 应用在 Kubernetes 中反复 CrashLoopBackOff,第一眼不是翻日志,而是查退出码。如果 exitCode 是 137,基本可以锁定是 cgroup OOMKilled —— 容器内存用量超过了 resources.limits.memory,被内核直接 SIGKILL。
执行这条命令快速确认:
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.status.containerStatuses[0].lastState.terminated.exitCode}'
若输出 137,再补一句:
kubectl describe pod <pod-name> -n <namespace> | grep -A2 "OOMKilled"
常见陷阱:
立即学习“go语言免费学习笔记(深入)”;
-
resources.requests.memory设太低,导致调度到内存紧张的节点,冷启动时瞬间突破 limits - Go 程序未设
GOMEMLIMIT,GC 不及时,内存尖峰冲过 limit - 用了
FROM scratch镜像但没加WORKDIR /,CMD ["/app"]失效,容器启动即报no such file or directory,exitCode 为1,容易误判为 OOM
kubectl logs --previous 是唯一能抓到崩溃前输出的手段
Go 程序崩溃快、日志少,当前容器里往往空空如也。--previous 参数不是可选项,是必选项 —— 它读的是上一轮崩溃前的标准输出和 stderr,对定位 panic、config load error、DB dial timeout 这类问题极其关键。
实操要点:
- 多容器 Pod 必须加
-c <container-name>,否则默认取第一个容器(可能只是 initContainer) - 如果日志里出现
panic: runtime error或failed to connect to database,直接对应代码位置改 - 若日志为空,说明崩溃发生在容器 runtime 启动阶段:检查
command/args是否语法错误、挂载路径是否只读、secret/configmap 是否缺失
livenessProbe initialDelaySeconds 设太小会杀死还没启动完的 Go 服务
Go 应用冷启动慢是常态:gRPC server 初始化、DB 连接池填充、配置热加载都可能耗时 10–30 秒。如果 livenessProbe.initialDelaySeconds 设成 5,kubelet 在应用监听端口前就发起探测,失败后立刻 kill 容器 —— 表现就是 CrashLoopBackOff,但根本不是程序 bug。
正确做法:
-
readinessProbe.initialDelaySeconds设为3–5,仅确保端口已监听、HTTP healthz 返回 200 -
livenessProbe.initialDelaySeconds必须 ≥ 应用完全就绪所需时间(建议先本地time ./app测一次冷启耗时) - 务必配
failureThreshold和periodSeconds,避免网络抖动误判;例如periodSeconds: 10,failureThreshold: 3
没有 shell 的 distroless 镜像怎么 debug?用 ephemeral container
Go 服务常用 gcr.io/distroless/static-debian12 或 scratch,里面没有 /bin/sh,kubectl exec -it 直接报错。这时候不能靠“进容器看看”,得用 Kubernetes 原生调试机制:ephemeral container。
步骤很直接:
- 先确认集群支持(v1.23+ 默认开启):
kubectl get nodes -o wide看 kubelet 版本 - 临时注入一个带工具的容器:
kubectl debug -it <pod-name> -n <namespace> --image=busybox:stable - 进去了就能
cat /proc/1/cmdline看主进程命令行,ls -l /proc/1/root/看挂载路径,netstat -tuln看端口是否真监听
注意:ephemeral container 无法访问主容器的环境变量或 secrets(除非显式挂载),它只共享网络和 PID namespace,够查进程状态,但不能替代日志和配置校验。


















