一个能跑起来的 Go 微服务 Deployment YAML 必须正确配置 containerPort(与 Go 代码监听端口一致)、livenessProbe 和 readinessProbe(如 HTTP GET /healthz),使用静态编译镜像,Service 的 selector 要匹配 Pod label(如 app: my-go-service),ConfigMap/Secret 需按需挂载为环境变量或文件,日志必须输出到 stdout 且禁用 ANSI 颜色。

怎么写一个能跑起来的 Go 微服务 Deployment YAML
Go 服务本身没特殊要求,K8s 只认容器镜像和端口。关键不是“Go 怎么写”,而是 Deployment 里哪些字段不能漏、不能错。
常见错误:本地 go run main.go 能通,但 Pod 一直 CrashLoopBackOff——大概率是没暴露端口、没设健康检查、或容器启动后立刻退出(比如没加 http.ListenAndServe 阻塞)。
-
spec.containers[].ports[].containerPort必须和 Go 代码里监听的端口一致(如http.ListenAndServe(":8080", nil)→ 这里填8080) - 加
livenessProbe和readinessProbe,哪怕只是 HTTP GET/healthz;不加的话 K8s 不知道服务是否真就绪 - 镜像名别用
localhost:5000/myapp这种本地 registry 地址,除非你真配了imagePullPolicy: Never,否则拉不到 - Go 编译时建议用
CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' -o myapp .,避免 Alpine 镜像缺 libc
多个 Go 实例共用同一个 Service 怎么配
Service 的 selector 匹配的是 Pod 的 label,不是 Deployment 名、也不是镜像名。多个 Deployment 想被同一个 Service 转发,label 必须对得上。
典型翻车现场:两个 Deployment 分别叫 user-svc 和 order-svc,但 Service 的 selector 写成 app: user-svc,结果 order 实例永远收不到流量。
- 统一约定一个 label 键,比如都用
app: my-go-service,Service 的selector就写app: my-go-service - 不同 Deployment 可以用不同
deployment.kubernetes.io/revision或自定义 label(如version: v1.2)做区分,但 Service 不关心这些 - Service 的
port和targetPort别搞反:port是 Service 暴露的端口(外部调用用),targetPort是 Pod 容器里实际监听的端口(Go 代码写的那个)
Go 微服务怎么读取 K8s ConfigMap 和 Secret
Go 程序本身不感知 ConfigMap,靠 K8s 把配置挂进容器文件系统或环境变量。Go 代码只管读文件或 os.Getenv,但挂载方式错了就读不到。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
最常踩的坑:ConfigMap 挂成 volume,却在代码里用 os.Getenv("DB_HOST") 去读——环境变量根本没注入。
- 想用环境变量:在
Deployment.spec.containers[].envFrom下加configMapRef或secretRef;或者用env[].valueFrom.configMapKeyRef单个注入 - 想用文件:用
volumes[].configMap挂载到路径(如/etc/config),Go 代码用ioutil.ReadFile("/etc/config/db_host")读(注意权限和路径是否存在) - Secret 默认 base64 编码,挂成文件时 K8s 自动解码;挂成环境变量时也自动解码,Go 代码不用再
base64.Decode
为什么 Go 服务在 K8s 里日志不输出或输出乱码
K8s 日志采集依赖容器 stdout/stderr。Go 默认打日志到文件或 syslog?那 kubectl logs 就是空的。
另一个高频问题:日志里全是 [36mINFO[0m 这种 ANSI 转义字符,因为某些日志库(如 logrus)默认开颜色,而容器环境没 TTY,导致输出不可读。
- 确保所有日志最终走到
fmt.Println、log.Print或zap.L().Info()这类写 stdout 的路径,别写文件 - 禁用日志颜色:
log.SetFlags(0)+log.SetOutput(os.Stdout);用logrus的话加logrus.SetFormatter(&logrus.TextFormatter{DisableColors: true}) - 如果用了结构化日志(如
zap),确保 encoder 配置为consoleEncoder或jsonEncoder,别用newDevelopmentEncoder(它会加颜色)
真正麻烦的从来不是写 YAML,而是让 Go 进程在容器里安静地活下来、把日志吐到 stdout、把健康状态准确告诉 K8s——这三件事卡住一个,整个部署就卡在 Pending 或 CrashLoopBackOff 里反复横跳。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










