You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Pulumi更新Kubernetes Deployment时Pod无法优雅停机问题排查

问题结论

该问题不是Pulumi的Bug,根因为容器启动进程的信号转发逻辑不符合Kubernetes优雅停机的要求。

原因说明

  • Kubernetes优雅停机的核心逻辑是:销毁Pod时,会先给容器内的PID 1进程发送SIGTERM信号,等待terminationGracePeriodSeconds(默认30秒)后进程仍未退出的话,再发送SIGKILL强制销毁进程。
  • 你使用go run作为容器启动命令时,会触发两层问题:
    • go run不会直接执行业务代码,会先编译源码生成临时二进制文件,再fork子进程运行该二进制,此时go run本身是容器的PID 1进程,你实际的业务代码是它的子进程。
    • go run原生不支持将收到的系统信号转发给它生成的子业务进程,Kubernetes发送的SIGTERM信号被PID 1的go run进程接收后直接退出,不会通知到业务进程,业务逻辑还没执行优雅停机流程,就被后续的SIGKILL强制销毁了。

验证信息

本地IDE运行测试时,信号直接发给了业务进程,所以可以看到包含"Signal":"interrupt"标识和Worker has been stopped的停机日志:

{"level":"info","msg":"trying to activate gcloud service account","time":"2021-06-17T12:19:25-05:00"}
{"level":"info","msg":"env var not found","time":"2021-06-17T12:19:25-05:00"}
{"Namespace":"default","TaskQueue":"main-task-queue","WorkerID":"37574@Paymahns-Air@","level":"error","msg":"Started Worker","time":"2021-06-17T12:19:25-05:00"}
{"Namespace":"default","Signal":"interrupt","TaskQueue":"main-task-queue","WorkerID":"37574@Paymahns-Air@","level":"error","msg":"Worker has been stopped.","time":"2021-06-17T12:19:27-05:00"}
{"Namespace":"default","TaskQueue":"main-task-queue","WorkerID":"37574@Paymahns-Air@","level":"error","msg":"Stopped Worker","time":"2021-06-17T12:19:27-05:00"}

容器内进程列表也验证了进程层级:PID 1为go run进程,实际业务进程为PID 3782的二进制程序:

root@worker-ffzpxpdm-78b9797dcd-xsfwr:/gadic# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.3  0.3 2046200 30828 ?       Ssl  18:04   0:12 go run src/cmd/worker/main.go --temporal-host temporal-server.temporal.svc.cluster.local --temporal-port 7233 --grpc-port 6789 --grpc-hos
root        3782  0.0  0.5 1640772 43232 ?       Sl   18:06   0:00 /tmp/go-build2661472711/b001/exe/main --temporal-host temporal-server.temporal.svc.cluster.local --temporal-port 7233 --grpc-port 6789 --
root        3808  0.1  0.0   4244  3468 pts/0    Ss   19:07   0:00 /bin/bash
root        3817  0.0  0.0   5900  2792 pts/0    R+   19:07   0:00 ps aux

手动执行kill -TERM 1时信号不会转发给下层二进制程序,优雅停机逻辑不触发;执行kill -TERM 3782时优雅停机逻辑可以正常触发,也符合上述逻辑。

解决方案

  • 生产环境Docker镜像不要使用go run启动服务,在镜像构建阶段完成源码编译,直接将编译后的二进制文件作为容器启动命令,保证业务进程就是PID 1,可以直接接收Kubernetes发送的停机信号。
  • 如有特殊场景必须使用go run启动,可以引入dumb-init等轻量初始化进程作为PID 1,由它管理子进程并转发收到的系统信号。

内容的提问来源于stack exchange,提问作者Paymahn Moghadasian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 09:24:05