Pulumi 不执行 kubernetes 的正常关闭 pods

Pulumi does not perform graceful shutdown of kubernetes pods

我正在使用 pulumi 来管理 kubernetes 部署。其中一个部署 运行 是一个图像,它拦截 SIGINT 和 SIGTERM 信号以像这样执行正常关闭(这个例子是 运行ning 在我的 IDE 中):

{"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"}

注意 "Signal":"interrupt"Worker has been stopped 的消息。

我发现当我更改源代码(更改 docker 图像)和 运行 pulumi up 时,pod 不会根据 [=] 中描述的内容正常终止24=]。这是 GCP 日志的屏幕截图:

上图中突出显示的日志行是应用发出的第一行日志。请注意,关闭消息未记录在突出显示的行上方,这表明 pod 没有机会执行正常关闭。

为什么 pod 无法通过 kubernetes 提供的正常关闭机制?这可能是 pulumi 如何执行部署更新的错误吗?


编辑:在做了更多调查后我发现这个问题正在发生,因为用 go run /path/to/main.go 启动一个 docker 容器实际上最终创建了两个这样的进程(在 exec 进入容器):

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 则信号不会转发到底层二进制文件 /tmp/go-build2661472711/b001/exe/main,这意味着不会执行应用程序的正常关闭。但是,如果我 运行 kill -TERM 3782 那么正常关闭逻辑 执行的。

似乎 go run 产生了一个子进程并且 this blog post 表明信号只转发给 PID 1。最重要的是,不幸的是 go run 没有转发信号到它产生的子进程。

我找到的解决方案是在我的 docker 文件中添加 RUN go build -o worker /path/to/main.go,然后使用 ./worker --arg1 --arg2 而不是 go run /path/to/main.go --arg1 --arg2 启动 docker 容器。

这样做可确保 go 不会产生任何子进程,并确保信号在 docker 容器内得到正确处理。