Go程序必须捕获SIGTERM并调用server.Shutdown()配合超时context,拒绝新请求、等待活跃连接完成;超时须小于terminationGracePeriodSeconds,且需手动管理长连接、DB连接池等资源释放。

Go 程序必须监听 SIGTERM 并调用 server.Shutdown()
容器环境(Docker/K8s)终止 Pod 时默认发 SIGTERM,不是 SIGKILL。若 Go 不捕获它,进程立即退出,所有活跃 HTTP 连接被硬断开。
http.Server.Close() 是暴力关闭,会中断所有连接;server.Shutdown() 才是标准做法:拒绝新请求、等待已有 handler 返回。
- 必须配
context.WithTimeout(),超时时间要小于 K8s 的terminationGracePeriodSeconds(比如设 30s,K8s 配 45s) - 别在 handler 里启动 goroutine 后立刻返回——
Shutdown()不等后台 goroutine,会导致请求实际未完成就退出 - 记得关闭 DB 连接池、取消长轮询 context、释放文件句柄等后台资源
Deployment 必须显式配置 maxSurge 和 maxUnavailable
这两个参数不是可有可无的装饰字段,而是滚动更新节奏的刹车和油门。设错会导致卡住、秒级不可用,或资源争抢失败。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
-
maxSurge: 1允许临时多跑 1 个 Pod(如从 3→4),否则新 Pod 拉不起来就卡住 -
maxUnavailable: 1保证任何时候至少有 2 个 Pod 在服务(3−1),避免流量断崖 -
maxSurge: 0是无效配置,会导致 rollout 卡住——新 Pod 根本起不来 - 低副本数(如
replicas=2)下,maxSurge: 25%实际为 0,可能触发“先删后启”
滚动更新本质是改 Deployment 的镜像字段,不是重启进程
Go 本身不支持“热替换二进制”。所谓滚动更新,本质是靠 Kubernetes Deployment 控制器拉起新 Pod + Go 进程自己配合优雅退出来实现零中断。
立即学习“go语言免费学习笔记(深入)”;
- 不能用 Go 直接“更新”一个正在运行的 Pod 的镜像——Pod 是不可变的
- 正确路径:修改
Deployment.Spec.Template.Spec.Containers[0].Image字段,然后调用clientset.AppsV1().Deployments().Update() - 必须确保
strategy.type == "RollingUpdate"(别依赖默认,显式写出来更稳) - 别碰 ReplicaSet 或 Pod,全交给 Deployment 控制器;绕过它 Delete+Create 是错误做法
更新后必须轮询状态,Update() 成功不等于滚动完成
Update() 调用成功只表示 API Server 接收了变更,不代表滚动已结束。真正判断完成需轮询 Deployment 的 status 字段。
- 检查
status.updatedReplicas == status.replicas(所有副本都已更新) - 同时检查
status.availableReplicas == status.replicas(所有副本都已就绪) - readinessProbe 必须真实反映服务就绪状态,否则新 Pod 就算起来了也不会接入流量
- 不要用
time.Sleep()猜测等待时长,轮询间隔建议 2–5 秒,超时设 5–10 分钟
readinessProbe 延迟太长、terminationGracePeriodSeconds 小于 Shutdown() 超时、或 maxSurge 在小集群里被截断为 0,整个链路就会在某个环节硬断开。

















