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

And*_*iak 5 linux signals go docker kubernetes

我有一个用 Go 编写的 API,已进行 Docker 化并在 GKE 上的 Kubernetes 集群中运行。

目前,我的 API 服务器不处理任何关闭场景,例如 Pod 死亡或被故意关闭。

我应该捕获哪组 UNIX 信号来正常关闭服务器以及什么情况会触发它们?例如崩溃、K8s 关闭等。

Ale*_*tau 8

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
}
Run Code Online (Sandbox Code Playgroud)

此外,您还应该将 Liveness 和 Readiness 探针添加到您的 pod 中:

livenessProbe:
  httpGet:
    path: /health
    port: 80
readinessProbe:
  httpGet:
    path: /health
    port: 80
Run Code Online (Sandbox Code Playgroud)