Deployment 和 Service 是 Go 应用在 Kubernetes 上最小可行组合;ServiceAccount 非可选而是调用 API 前提,须显式创建并绑定 RBAC,容器端口需与 containerPort 及探针严格一致,镜像构建须禁用 CGO 并选用轻量基础镜像。

Deployment 和 Service 是 Go 应用在 Kubernetes 上最小可行组合;ServiceAccount 不是可选项,而是调用 API 的前提——没它,client-go 连 InClusterConfig() 都会 panic。
Go 服务必须从环境变量读端口,且与 containerPort 严格一致
硬编码 http.ListenAndServe(":8080", nil) 在本地能跑,进集群后 readinessProbe 必挂:Kubernetes 不看代码里写了啥,只按 containerPort 和探针配置去连。一旦不匹配,就报 connection refused。
- 代码里改用
os.Getenv("PORT"),fallback 到"8080" -
deployment.yaml中的containerPort必须和实际监听端口相同(比如 8080) - 若加了 Nginx sidecar,还要确认它转发的目标端口和容器内监听端口对齐
ServiceAccount 不要依赖默认的 default
命名空间自带的 default ServiceAccount 没任何 RBAC 权限,client-go 调 CoreV1().Pods("default").List() 会直接返回 Forbidden 错误——这和初始化失败不同,容易误判为代码问题。
- 显式创建专属
ServiceAccount,比如go-app-sa,限定在应用所在命名空间 - Pod 模板中必须声明
serviceAccountName: go-app-sa,否则仍走default - Kubernetes 1.24+ 默认不自动挂载 token,如需访问 API,得确保没设
automountServiceAccountToken: false
用 InClusterConfig() 加载配置,别碰 ~/.kube/config
本地调试时用 clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile) 看似方便,但上线后会 panic:找不到 /root/.kube/config 或权限拒绝。Pod 内唯一可靠路径是 /var/run/secrets/kubernetes.io/serviceaccount/ 下的 token 和 ca.crt。
- 生产代码只用
rest.InClusterConfig(),它自动读取挂载的 ServiceAccount 凭据 - 手动挂载 kubeconfig(如通过 volume)风险高:路径错、权限不对(需 400 或 444)、CA 证书缺失都会导致 HTTPS 请求失败
- RBAC 权限缺失不会让
InClusterConfig()失败,但后续 list/watch 操作一定 403
镜像构建必须禁用 CGO,否则 Alpine 镜像启动即崩溃
CGO 启用时,Go 二进制会动态链接 libc,而 Alpine 用 musl —— 镜像 build 成功,容器一启就报 no such file or directory。
- Dockerfile 构建阶段加
CGO_ENABLED=0 GOOS=linux - 运行镜像优先选
scratch或alpine:latest,但后者需提前apk add ca-certificates,否则调 Kubernetes API 会因证书缺失失败 - 别用
FROM golang:alpine直接运行,它含完整构建链,体积大、有 CVE 风险
ServiceAccount 的 token 和证书挂载是隐式发生的,但权限控制是显式的——RBAC 绑定漏一条 resources 或少一个 verbs,client-go 就会静默失败,日志里只有 403,没有更多线索。


















