微服务镜像必须使用明确标签(如v1.2.3或Git SHA),禁用latest以保障可重现性和滚动更新可靠性;Helm values.yaml中需固定image.tag,CI中注入tag;Deployment应配置合理replicas与滚动策略(maxSurge:1, maxUnavailable:0);模板中namespace须用{{ .Release.Namespace }}实现环境复用;Golang程序必须主动监听SIGTERM并调用server.Shutdown()实现真正优雅退出。

微服务镜像必须带明确标签,不能用 latest
K8s 默认不拉取 latest 镜像(除非 imagePullPolicy: Always),但生产环境绝不该依赖 latest —— 它破坏可重现性,也容易因镜像覆盖导致滚动更新失败或回滚失效。
- 构建时用 Git commit SHA 或语义化版本打标签,例如:
docker build -t mysvc:v1.2.3 . - Helm
values.yaml里固定写死image.tag: "v1.2.3",而非留空或填"latest" - CI 流水线中,把 tag 注入 Helm
template命令:helm template --set image.tag=${CI_COMMIT_TAG} ./chart
Deployment 的 replicas 和 strategy 要按服务类型设
无状态微服务(如 HTTP API)通常设 replicas: 3 起步,但关键不在数字,而在更新策略是否匹配业务容忍度。
- 滚动更新(默认)适合多数场景,但需配
maxSurge: 1和maxUnavailable: 0避免请求丢失 - 有状态服务(如带本地缓存或会话绑定)慎用滚动更新;改用
type: Recreate,否则新旧 Pod 可能同时读写冲突 - 若服务启动慢(比如要加载大配置、连 DB),务必加
readinessProbe+initialDelaySeconds,否则 K8s 会在 Golang 程序真正就绪前就把流量导过去
Helm Chart 里别硬编码 namespace,用 {{ .Release.Namespace }}
很多人在 templates/deployment.yaml 里写死 namespace: prod,结果 chart 无法复用到 staging 或 CI 环境。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 所有资源对象的
metadata.namespace字段统一用{{ .Release.Namespace }},让helm install -n myns决定归属 - ServiceAccount、RoleBinding 等 RBAC 资源也必须依赖该变量,否则跨 namespace 权限会失效
- 若 chart 需要创建 namespace,单独放
templates/namespace.yaml,并加{{- if .Values.createNamespace }}控制开关
Golang 程序得主动响应 SIGTERM,否则 preStop 无效
Helm 模板常加 lifecycle.preStop.exec.command 执行 sleep 10,但这只是“等”,不是“优雅退出”。真正起作用的是 Golang 进程自己监听信号。
立即学习“go语言免费学习笔记(深入)”;
- 在 main 函数里用
signal.Notify监听os.Interrupt和syscall.SIGTERM - 收到信号后,调用 HTTP server 的
Shutdown()方法,并等待活跃连接关闭(建议设ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)) - 别依赖
preStop延迟代替程序自身处理 —— 如果 Go 程序已僵死,sleep 再久也没用
Golang 微服务跑在 K8s 上,最常出问题的地方不在 YAML 写错,而在于容器进程没真正理解“优雅终止”和“健康探针”的契约。Helm Chart 是胶水,但胶水粘不住没写好 shutdown 逻辑的代码。

















