EKS中Go应用SIGTERM信号优雅关闭日志捕获问题
问题描述
我在EKS环境中删除Pod时,希望捕获Go服务器优雅关闭的日志,但发现Pod收到SIGTERM信号后服务器立即关闭,没有生成预期的优雅关闭相关日志。我已经在Pod配置中设置了terminationGracePeriodSeconds: 180,相关的Go服务器初始化代码如下:
func ServeRequest(configuredRoutes http.Handler) { air_logger.SERVER_STARTUP("########## SERVER STARTED ##########") server := &http.Server{ Addr: config.GetConfig().Server.Port, Handler: handlers.CORS( handlers.AllowedMethods([]string{"OPTIONS", "GET", "POST", "PUT", "PATCH"}), handlers.AllowedHeaders([]string{"DNT", "User-Agent", "X-Requested-With", "If-Modified-Since", "Cache-Control", "Content-Type", "Range", "Pragma", "X-FourKitesUserId", "X-FourKitesDeviceId", "Authorization", "Expires"}), handlers.MaxAge(600), )(configuredRoutes), } done := make(chan bool, 1) quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) go func() { <-quit test_logger.Info(context.TODO(), "test-service server is shutting down") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() server.SetKeepAlivesEnabled(false) if err := server.Shutdown(ctx); err != nil { test_logger.Fatal(ctx, "error in graceful shutdown of the test-service server:", err.Error()) } close(done) }() if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { test_logger.Fatal(context.TODO(), "test-service server shutdown with error: ", err.Error()) } test_logger.Info(context.TODO(), "test-service before server shutdown gracefully") <-done test_logger.Info(context.TODO(), "test-service server shutdown gracefully") }
排查与解决思路
- 确认信号传递是否正常:容器中主进程PID必须为1才能直接接收kubelet发送的SIGTERM。如果用shell脚本启动Go程序,要改用
exec ./your-go-binary,让Go进程成为PID1,避免shell拦截信号。 - 调整优雅关闭超时窗口:当前代码中优雅关闭的上下文超时仅设置为5秒,远小于Pod的180秒终止宽限期。建议将超时时间调整为
170*time.Second,给剩余请求处理留足时间,同时避免超过kubelet的等待时长。 - 验证日志输出配置:检查
test_logger的日志级别是否开启了Info级,并且日志是否输出到容器的标准输出/标准错误流。EKS的日志采集工具通常只会收集这两个流的内容,如果日志写入了文件,需要调整配置。 - 添加信号接收调试日志:在信号处理协程的最开头增加一条更醒目的日志,比如
test_logger.Info(context.TODO(), "Received SIGTERM/SIGINT, starting graceful shutdown"),确认信号是否真的被捕获到。 - 检查Pod终止事件:执行
kubectl describe pod <pod-name>查看Pod终止时的事件日志,确认kubelet是否正常发送了SIGTERM,以及是否在宽限期内发送了SIGKILL。
内容的提问来源于stack exchange,提问作者Nisha Vijayakumar
相关产品推荐
相关产品推荐

