Go服务必须暴露真实/readyz探针:需探测DB、Redis、gRPC等核心依赖并缓存结果,禁止硬编码返回200;初始化完成后再关闭readyCh供探针阻塞读取;蓝绿靠Service selector切换双Deployment,优雅关闭须监听SIGTERM并等待所有goroutine退出。

Go 服务必须暴露真实 /readyz,否则流量切过去就 panic
很多团队把 /readyz 写成硬返回 HTTP 200,结果新 Pod 还没连上数据库、Redis 连接池为空、gRPC client 没完成健康检查,Kubernetes 就已把它加进 Endpoints,第一个请求直接崩溃。
必须检查核心依赖,且不能在 handler 里实时探测——耗时操作会拖慢探针,导致 K8s 反复失败重试:
- 用 goroutine 启动后定期 ping DB、SET/GET Redis、调用下游
/health;结果缓存到本地布尔变量 -
/readyzhandler 只读缓存,不触发任何 IO - 初始化耗时波动大(比如 config 加载 + migration)时,启动 HTTP server 后加
time.Sleep(2 * time.Second),比依赖initialDelaySeconds更可控 - 避免竞态:DB 初始化和配置加载顺序错乱时,
/readyz返回 200 但实际 client 是 nil;建议用readyCh chan struct{},所有初始化完成后才close(readyCh),handler 阻塞等待
Kubernetes 原生蓝绿靠 Service selector 切换,不是改 Deployment
蓝绿不是靠滚动更新或替换 Pod,而是两个独立的 Deployment(version: v1 和 version: v2),共用一个 Service,仅通过修改其 selector 指向来切流。
常见错误是用 kubectl apply -f 覆盖整个 Service YAML,容易冲掉 CI 注入的 label(如 git-commit: abc123),导致监控断联或灰度失效:
立即学习“go语言免费学习笔记(深入)”;
评估 Kubernetes 集群安全态势,覆盖 RBAC、工作负载安全、网络策略、基础设施即代码(IaC)、运行时监控和密钥管理等 30 项控制项……
- 正确做法:用
kubectl patch service user-api -p '{"spec":{"selector":{"version":"v2"}}}' - 确保两个 Deployment 的 label key 完全一致:
version: v2≠ver: v2≠VERSION: v2 -
minReadySeconds: 10是保障,不是探针替代;它要求 Pod Ready 状态持续 10 秒才被加入 Endpoints - 别给新 Deployment 设
maxSurge: 1——这是滚动更新参数,对蓝绿无效,还可能干扰调度
优雅关闭必须等完所有 goroutine,srv.Shutdown() 不是可选项
切流后旧 Pod 被删,但如果只调 srv.Close() 或忽略信号,正在处理的 HTTP 请求、gRPC 流、Kafka 消费 goroutine 全部被中断,结果就是丢数据、502、半截响应。
Go 服务要自己扛住 SIGTERM,并协调所有生命周期:
- HTTP server 启动后保存
*http.Server实例,监听syscall.SIGTERM和os.Interrupt - 收到信号后,调
srv.Shutdown(ctx),ctx带 15–30 秒超时,不能用context.Background() - 所有后台 goroutine(指标上报、消息消费、定时任务)必须接收
context.Context,并在ctx.Done()时 clean exit - 禁用全局 flag、无缓冲 channel 或
os.Exit(0)强退——事务中断、连接未释放、日志截断都可能发生
数据库兼容性是蓝绿成败的隐藏门槛
蓝绿切换瞬间,新旧版本同时可能访问同一套数据库。如果 v2 加了非空字段、删了旧索引、或改了唯一约束,v1 会立刻报错,用户看到的是 500 而不是“正在升级”。
这不是 Go 代码能绕开的问题,必须在发布前确认:
- 所有 DDL 必须向后兼容:新增字段设默认值或允许 NULL;删除字段先废弃再下线;索引变更不影响旧查询执行计划
- 避免“先切流再跑 migration”——蓝绿要求数据库 schema 在切流前就已兼容双版本
- 如果用了 Flyway/Liquibase,确保 v1 和 v2 的 migration 脚本都能在当前 DB 状态下安全执行(或跳过)
- 有状态中间件(如本地缓存、文件存储)需额外设计同步或隔离机制,否则用户会话丢失、上传中断
真正卡住蓝绿落地的,往往不是 Kubernetes YAML 写得对不对,而是 /readyz 是否真能反映 DB 连通、Shutdown 是否真等完了 Kafka 消费、schema 变更是否真没破坏 v1 的读写路径——这些细节藏在日志里、埋在压测中、爆在凌晨三点的告警里。

















