为了账号安全,请及时绑定邮箱和手机立即绑定

如何优雅地关闭在 Kubernetes 上运行的 Go 服务

如何优雅地关闭在 Kubernetes 上运行的 Go 服务

Go
翻翻过去那场雪 2023-06-01 16:58:48
我有一个用 Go 编写的 API,它已经被 Docker 化并在 GKE 上的 Kubernetes 集群中运行。目前,我的 API 服务器不处理任何关闭场景,例如 Pod 死亡或被故意关闭。我应该期望捕获哪一组 UNIX 信号以正常关闭服务器以及什么情况会触发它们?例如,崩溃、K8s 关闭等。
查看完整描述

2 回答

?
忽然笑

TA贡献1806条经验 获得超5个赞

Kubernetes 发出一个SIGTERM信号。所以优雅的关机可能看起来像这样:


package main


import (

    "context"

    "log"

    "net/http"

    "os"

    "os/signal"

    "syscall"

)


func main() {

    var srv http.Server


    idleConnsClosed := make(chan struct{})

    go func() {

        sigint := make(chan os.Signal, 1)


        // interrupt signal sent from terminal

        signal.Notify(sigint, os.Interrupt)

        // sigterm signal sent from kubernetes

        signal.Notify(sigint, syscall.SIGTERM)


        <-sigint


        // We received an interrupt signal, shut down.

        if err := srv.Shutdown(context.Background()); err != nil {

            // Error from closing listeners, or context timeout:

            log.Printf("HTTP server Shutdown: %v", err)

        }

        close(idleConnsClosed)

    }()


    if err := srv.ListenAndServe(); err != http.ErrServerClosed {

        // Error starting or closing listener:

        log.Printf("HTTP server ListenAndServe: %v", err)

    }


    <-idleConnsClosed

}

您还应该将 Liveness 和 Readiness 探测器添加到您的 Pod 中:


livenessProbe:

  httpGet:

    path: /health

    port: 80

readinessProbe:

  httpGet:

    path: /health

    port: 80


查看完整回答
反对 回复 2023-06-01
?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

当 Kubernetes 发送SIGTERM信号流量仍然可以路由到 pod 时,因为从端点集和SIGTERM信号中删除 pod 是异步的——如果 pod 在SIGTERM端点之后可能没有时间更新。 SIGTERM只是礼貌地要求开始收尾,但不要立即停止接受新的请求。

您可以在<-sigint部署之后或添加到部署中后将睡眠添加到您的代码中

lifecycle:
      preStop: 
             exec:     
                  command: ["sh", "-c", "sleep 10"]
查看完整回答
反对 回复 2023-06-01
  • 2 回答
  • 0 关注
  • 128 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信