kubernetes不部署go服务,只调度容器;go服务须监听0.0.0.0:8080、暴露/healthz和/readyz、用cgo_enabled=0构建静态二进制、yaml中selector.matchlabels与template.labels必须完全一致,否则pod卡在containercreating或crashloopbackoff。

直接上结论:Kubernetes 不部署 Go 服务,它只调度、监控、重启你提供的容器;Go 服务必须自己暴露 /healthz 和 /readyz、监听 0.0.0.0:8080、用 CGO_ENABLED=0 构建静态二进制、YAML 中 selector.matchLabels 和 template.labels 必须一字不差——漏掉任一环节,Pod 就会卡在 ContainerCreating 或反复 CrashLoopBackOff。
Go 代码里没写 /healthz 和 /readyz,K8s 就会杀掉你的 Pod
livenessProbe 和 readinessProbe 默认只发 HTTP GET 请求,路径不对或返回非 2xx/5xx(比如直接 panic 或没注册 handler),探针就永远失败。K8s 不猜你的健康逻辑,它只看状态码。
-
/healthz应返回200,不做 DB 查询、不连 Redis、不调下游——只回答“进程还在跑吗” -
/readyz可查db.Ping()、redis.Ping(),但超时必须控制在timeoutSeconds: 10内,否则探针判定失败 - 路径名必须和 Deployment YAML 中
httpGet.path完全一致:livenessProbe.httpGet.path: "/healthz"→ 代码里就得有http.HandleFunc("/healthz", ...) - 端口也要对齐:代码监听
:8080,YAML 的containerPort就不能写80,否则探针连不上
Dockerfile 用 FROM golang:alpine 直接跑,镜像就废了
golang:alpine 镜像带完整 Go 工具链、apk、shell,体积大、攻击面宽,且默认开启 CGO——在 Alpine 上运行会报 standard_init_linux.go:228: exec user process caused: no such file or directory,因为 musl libc 找不到 glibc 符号。
- 必须多阶段构建:第一阶段用
golang:1.22-alpine AS builder,编译前加ENV CGO_ENABLED=0 GOOS=linux - 第二阶段用
FROM scratch或FROM gcr.io/distroless/static-debian12,只 COPY 二进制,无 shell、无包管理器 - 入口命令必须是
CMD ["/main"],不是go run main.go;若用了 cgo(如sqlite3),第二阶段得换alpine:latest并apk add sqlite - 加上
USER 65532:65532,避免以 root 运行——否则容器逃逸后直接拿下节点
Deployment YAML 里 selector.matchLabels 和 template.labels 差一个空格,kubectl apply 就报错
K8s API Server 对 label selector 做硬校验,不是“建议匹配”,而是“必须完全一致”。一旦 Deployment 创建成功,spec.selector 就不可变更;改错一点,新 Pod 永远不会被 Service 收入流量池,也不会被旧 ReplicaSet 清理。
- 两边 label 必须严格相同,例如:
matchLabels: {app: "user-api"}↔template.metadata.labels: {app: "user-api"} - 不能一边写
app: user-api,另一边写APP: user-api或app: "UserApi" - template 里别多加
version: "v1"等字段,除非 selector 也显式包含它 - CI/CD 中建议用
envsubst注入 label 值,手写容易漏空格或大小写
Go 服务没监听 SIGTERM,滚动更新时请求就丢
K8s 在滚动更新或缩容时发 SIGTERM,不是 SIGKILL。如果你的代码只监听 os.Interrupt 或直接 os.Exit(0),HTTP 连接会中断、DB 事务未提交、gRPC 流未关闭。
- 必须同时监听
syscall.SIGTERM和os.Interrupt(后者用于本地调试) - 收到信号后调用
http.Server.Shutdown(),设超时(如30s),超时后强制os.Exit(1) - DB 连接池、消息消费者等资源,要在
Shutdown()返回后再关闭,顺序不能反 - 禁用
log.Fatal()和panic退出方式——它们绕过 defer 和 Shutdown 流程
最常被忽略的是监听地址写成 127.0.0.1:8080:Pod 内的 localhost 只指向自己,Service 流量根本进不来,现象是 kubectl get pods 显示 Running,但 curl 任何 IP 都超时。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











