美文网首页golang开发
记录一次排查k8s集群中go服务不断重启的问题

记录一次排查k8s集群中go服务不断重启的问题

作者: robertzhai | 来源:发表于2022-02-09 22:42 被阅读0次

背景

  1. 某次晚上上线后,某个k8s服务出现频繁重启的现象,看了阿里云k8s的监控,是由于对应服务的健康检查失败导致k8s不断重新创建pod,然后重启。
  2. 看了下splunk里面的错误日志,由于splunk里面的日志太多,几个同事花了一些时间也没定位到是啥原因,加上太晚就决定然运维对Pod进行了扩容,这样可以减少重启的次数,第二天到公司再排查。
  3. 第二天到公司重新review了下代码,没发现明显问题,后来google了下,可能是fatal error 导致进程退出,进而导致健康检查失败,于是我在main函数里对错误日志做了重定向,代码如下
// 重定向错误  
// 调用示例 在main函数中加入 bc_error.RedirectFatal("/opt/go/logs/app_fatal.log")
func RedirectFatal(logFileName string) {
    if logFileName == "" {
        logFileName = fmt.Sprintf("/opt/go/logs/%d_fatal.log", php.Time())
    }   
   
    logFile, err := os.OpenFile(logFileName, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
    if err != nil {
        PanicLogger.Errorf("服务启动出错:打开异常日志文件%s失败 err:%+v", logFileName, err)
    } else if logFile != nil {
        PanicLogger.Warnf("服务启动成功:打开异常日志文件%s 成功", logFileName)
        // 将进程标准出错重定向至文件,进程崩溃时运行时将向该文件记录协程调用栈信息
        syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd()))
    } else {
        PanicLogger.Warnf("服务启动出错:打开异常日志文件%s 发生不明错误", logFileName)
    }   
}
  1. 然后上线了几个pod,终于捕获到了完整的stack fatal error , 对照代码看了是并发写map 导致了fatal error , 这种是不能revovey的,后来在map的地方加了sync.RWMutex 解决了这个问题,上线后没有重启了

  2. 总结不能被recover的

  • 数据竞争(比如:对map进行并发读写),可以通过golang的编译标记race对代码进行检测是否存在数据竞争(比如:并发读写map)
  • 内存不足
  • 死锁

参考

相关文章

网友评论

    本文标题:记录一次排查k8s集群中go服务不断重启的问题

    本文链接:https://www.haomeiwen.com/subject/bdywqrtx.html