pod启动即被杀因livenessprobe初始延迟过短,应设initialdelayseconds为10或30秒;go需显式监听sigterm并用shutdown()优雅关闭;readinessprobe须与业务端口一致;terminationgraceperiodseconds需与shutdown超时对齐。

Pod 启动后立即被 kill - 检查 livenessProbe 初始延迟是否过短
很多 Go 应用在 K8s 里刚启动几秒就被重启,不是程序崩了,而是 livenessProbe 太急——它默认从容器启动就开始计时,而 Go 的 HTTP server 可能还没 bind 成功,更别说加载配置、连 DB、预热缓存了。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
-
initialDelaySeconds至少设为10(简单服务)或30(带初始化逻辑的),别信“我代码很快”——K8s 节点 IO、网络、调度延迟都不可控 - 如果用
httpGet探针,确保 handler 不做重操作:比如不要在/healthz里查 MySQL 主从延迟,只检查本地 listener 是否就绪 - 避免用
exec执行curl或netstat:容器里可能没装,且 shell 启动有开销,httpGet更轻量也更稳定
Go 程序收不到 SIGTERM 或关不干净 —— 必须显式监听并阻塞主 goroutine
K8s 发送 SIGTERM 后,若 Go 进程 main 函数已退出(比如启了个 goroutine 就 return),容器会立刻终止,正在处理的 HTTP 请求、数据库事务、消息确认全丢。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 用
signal.Notify监听os.Interrupt和syscall.SIGTERM,收到后触发 graceful shutdown 流程 - HTTP server 关闭必须用
srv.Shutdown(),不能只调srv.Close()—— 后者会立刻断连,前者会等活跃请求完成(可配超时) - main 函数末尾要
select{}或time.Sleep(time.Hour)阻塞住,否则进程提前退出,信号根本来不及响应 - 第三方库(如
gin、echo)的 graceful shutdown 要看文档,有些需额外中间件或包装器,别假设它自动支持
readinessProbe 返回 200 但流量仍打进来 —— 检查探针路径与业务 handler 是否共用同一端口和 mux
常见错误是把 /readyz 和业务路由注册到不同 HTTP server(比如一个走 :8080,一个走 :9090),但 readinessProbe 配的却是 :8080/readyz,而实际流量全打在 :9090 上。结果探针永远成功,但业务根本没起来。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 确保 readiness 探针路径(如
/readyz)和业务 HTTP server 是同一个实例,共享http.ServeMux或 router - 探针 handler 应检查关键依赖:DB 连接池可用、Redis ping 通、必要配置已加载。但别检查外部依赖全链路(比如调第三方 API),那会让 readiness 变得脆弱
- 如果用多端口(如 metrics 单独开
:9090),readinessProbe仍应指向主业务端口,否则 K8s 认为“服务就绪”,其实流量无处可去
容器退出码非 0 却没进 CrashLoopBackOff —— 查 terminationGracePeriodSeconds 和 preStop 生命周期
有时 Go 程序 panic 退出,exit code 是 2,但 Pod 状态卡在 Terminating 好几分钟才重建,或者干脆没重建——这通常是因为 terminationGracePeriodSeconds 设得太大(默认 30 秒),而 preStop 没配或执行失败,导致 K8s 等不到容器自然退出,最后强制发 SIGKILL。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
-
terminationGracePeriodSeconds建议设为30(够多数 Go 应用 graceful shutdown),别设成300—— 等五分钟?用户早刷出空白页了 - preStop 最好配个
exec,比如sleep 2,给 Go 程序留出接收 SIGTERM 的窗口;如果用httpGet,注意它不保证一定触发,不如 exec 可靠 - 在 preStop 里别做重操作(比如 dump 内存),它本身没有超时控制,失败会导致整个 termination 卡住
最常被忽略的一点:Go 的 http.Server.Shutdown() 超时时间,和 K8s 的 terminationGracePeriodSeconds 必须对齐。前者比后者长,shutdown 永远完不成;后者比前者短,K8s 直接杀进程,前者的超时就白设了。










