一次pod无法ready的问题定位
原先可以正常部署的项目,在新的部署中突然提示pod无法ready,本文记录定位思路及解决方式。
查看pod事件,发现pod在启动时readiness探活一直失败,进而导致pod一直在重启。
- 简单排查无法定位原因,将pod的部署manifest文件中,探活端口关闭,以便登录pod定位。注释代码如下:
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
- 登录pod手动启动服务
手动启动服务,启动后使用netstat
命令查看网络状态,如下:
发现存在一个SYN_SENT
状态的连接,说明到此IP的网络连接存在问题(关于SYN_SENT状态可自行Google)。
发现服务在停留大约2min后,可正常启动,正常启动后再次查看netstat
输出,如下:
服务在正常启动后,SYN_SENT
状态的连接消失,基本可判定是该网络连接直接阻塞了服务启动。
- 阅读代码定位
首先全局搜索,发现并没有直接调用此IP的代码。接着在main
函数的关键路径添加打印日志,发现main
函数第一句打印信息的执行大约在2min后,与SYN_SENT
时间基本一致。Go语言中,在main
函数前执行的只有init
函数。服务代码并没有直接实现的init
函数,所以基本可判定是依赖的第三方包中init
函数引发的问题。
由于没有很好的根据IP地址反向查找域名的方法,所以只能继续通过全局搜索func init()
关键字来排查。对于每个搜索结果检查是否存在连接网络的行为。好在搜索结果不过,最终发现确实某个第三方库的init
函数中会向某域名发起连接,ping
域名得到的IP与SYN_SENT
状态IP一致:
- 经验
整个的定位过程中也走过一些弯路,比如开始试图通过pprof
去发现一些有用的线索,但并未成功。通过trace
得到的网络IO图也没发现此网络调用。
当开发可能被外部依赖的第三方库时,init
函数中尽量避免网络IO等操作,以防使用者所处网络环境不通导致业务问题。