replicas字段是Kubernetes必须严格维持的精确副本数,设为3即确保始终有且仅有3个Running Pod(忽略滚动更新时maxUnavailable允许的临时偏差)。

Deployment replicas字段直接控制实例数
replicas不是“建议值”,而是 Kubernetes 控制器必须维持的精确副本数。设为 3,控制器就会确保集群中始终有且仅有 3 个 Pod 处于 Running 状态(不考虑 Unavailable 策略临时允许的偏差)。它不关心你代码里开了多少 goroutine,只认这个数字。
常见错误包括:
- 把
replicas: 1当成“够用”,结果节点宕机服务直接中断 - 看到 Pod 频繁重启(
CrashLoopBackOff),却还指望replicas自动补足——控制器不会掩盖故障,只会不断重试启动失败的 Pod - 滚动更新时没设
maxUnavailable,导致流量瞬间全断
生产环境起步建议设为 2 或 3,并搭配 minReadySeconds: 10 避免新 Pod 还没真正就绪就被认为可用。
Go 代码必须监听 0.0.0.0,不能写 localhost
Pod 内部的 localhost 或 127.0.0.1 只指向自身容器,Service 的流量根本进不来。你会看到 kubectl get endpoints 返回 <none>,即使 kubectl get pods 全是 Running。
立即学习“go语言免费学习笔记(深入)”;
正确写法只有两种:
-
http.ListenAndServe(":8080", nil)(推荐,Gonet/http默认行为) -
http.ListenAndServe("0.0.0.0:8080", nil)(显式,更易理解)
如果用了 gin,检查是否误写了 r.Run("127.0.0.1:8080");如果用了自定义 http.Server,务必确认 Addr 字段是 ":8080" 而非 "127.0.0.1:8080"。本地调试可以 localhost,但镜像构建前必须改掉。
Service selector 和 Pod labels 必须字面量完全匹配
Kubernetes 不做模糊匹配、不忽略空格、不自动转换大小写。哪怕只差一个连字符或大小写,Endpoint 就为空,Service 流量零转发。
典型不匹配场景:
- Deployment 模板里写
labels: {app: go-app},Service 的selector却写成app: my-go-app - Deployment 用了
env: prod,Service 却漏掉了这个 key,只写了app: go-app - YAML 缩进错误导致 labels 实际没嵌套在
template.metadata下,Pod 根本没打上标签
验证方法:先 kubectl get pods -l app=go-app 看能否列出 Pod;再 kubectl get svc go-app-service -o yaml 对照 spec.selector 字段,逐字比对。
用 client-go 更新 replicas 必须传指针,且需处理资源版本冲突
client-go 的 Update() 方法要求 Spec.Replicas 是 *int32 类型,直接赋值 3 会编译报错。同时,Kubernetes API 基于乐观锁,若并发修改同一 Deployment,第二次 Update() 会返回 409 Conflict 错误。
安全做法是:
- 用
&replicasValue取地址,例如:deployment.Spec.Replicas = &newReplicas - 捕获
errors.IsConflict(err),触发重试逻辑(先Get()拿最新版,再改再Update()) - 避免在循环里反复
Get()后直接Update(),应加简单退避(如time.Sleep(100 * time.Millisecond))防止雪崩
别省略 ResourceVersion 字段校验——它不是可选项,是并发安全的唯一保障。
部署多实例本身不难,难的是让每个实例真正被发现、能承接流量、出问题时能准确定位。端口、标签、监听地址这三处写错,比逻辑 bug 更隐蔽,也更常导致 “明明跑起来了却访问不到”。


















