Go服务必须监听0.0.0.0:8080而非127.0.0.1:8080,因Kubernetes中localhost仅指向容器自身,Service及其他Pod无法访问;正确写法为http.ListenAndServe(":8080", nil)或读取环境变量PORT动态绑定。

Go服务监听地址必须是 0.0.0.0:8080,不是 127.0.0.1:8080
Kubernetes Pod 的网络模型决定了容器内 localhost 只指向自己,Service 或其他 Pod 根本无法访问。一旦你写成 http.ListenAndServe("127.0.0.1:8080", nil),kubectl get pods 看起来是 Running,但所有流量都进不来,curl 超时、探针失败、CrashLoopBackOff 都可能由此触发。
正确做法是显式监听全网卡:http.ListenAndServe(":8080", nil),或更健壮地读取环境变量:port := os.Getenv("PORT") + http.ListenAndServe(":" + port, nil)。
- 务必确认 Go 代码里没硬编码
127.0.0.1;很多本地调试通过的代码一上 K8s 就挂,根源就在这 - 如果用了
gin、echo等框架,检查启动语句是否带 host 参数(如e.Start("127.0.0.1:8080")) -
containerPort在 Deployment YAML 中必须和实际监听端口一致(比如代码监听:8080,YAML 却写containerPort: 80,探针会连不上)
MySQL 连接字符串不能写死,必须用 Secret + ConfigMap 注入
把 user:pass@tcp(10.96.1.2:3306)/mydb 直接写进代码或镜像,等于把密码塞进 Git 和镜像层——生产环境零容忍。
正确拆分方式:
立即学习“go语言免费学习笔记(深入)”;
- 敏感字段(
username、password)走Secret:base64 编码后注入为环境变量或文件 - 非敏感字段(
host、port、database_name)走ConfigMap,方便多环境复用 - Go 代码中统一用
os.Getenv()拼接连接串,例如:fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", user, pass, host, port, dbname)
常见错误:Secret 的 key 名(如 username)和 YAML 中 secretKeyRef.key 不一致,导致环境变量为空,DB 初始化直接 panic。
livenessProbe 和 readinessProbe 必须配独立路径,且 Go 代码要真实注册
Kubernetes 不看进程是否存在,只认 HTTP 状态码。没暴露 /healthz 和 /readyz,或者路径名拼错(比如 YAML 写 /health,代码只注册了 /healthz),探针持续 404,Pod 就会被反复重启。
Go 里最简注册方式:
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
})
http.HandleFunc("/readyz", func(w http.ResponseWriter, r *http.Request) {
if err := db.Ping(); err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
})
-
/healthz应极轻量,不做 DB 查询,只答“进程活着” -
/readyz可查 DB 连通性,但建议设timeoutSeconds: 5,避免阻塞探针队列 - Deployment YAML 中
httpGet.path必须和代码中HandleFunc的路径完全一致,大小写、斜杠都不能差
Dockerfile 必须禁用 CGO_ENABLED=0,否则 Alpine 镜像运行报 no such file or directory
Go 默认开启 CGO,会链接 glibc;而 Alpine 用 musl libc。镜像构建成功,运行时却崩溃,日志只显示:standard_init_linux.go:228: exec user process caused: no such file or directory——这是 musl 和 glibc 不兼容的典型症状。
多阶段构建关键点:
- 构建阶段:用
golang:1.22-alpine,但必须在go build前加CGO_ENABLED=0 - 运行阶段:用
scratch或gcr.io/distroless/static-debian12,体积小、无 shell、无法交互式入侵 - 如果用了 cgo 依赖(如
sqlite3、某些加密库),不能用scratch,得切回alpine并apk add对应动态库
最后别忘了 USER 65532:65532 ——非 root 用户运行是容器安全底线,漏掉这条,K8s 审计或平台策略可能直接拒绝部署。


















