go应用在kubernetes中启用tls应由ingress控制器终止,而非go代码处理;需创建含tls.crt(leaf→intermediate→root顺序)和tls.key(非加密pem)的secret,ingress中host与tls.hosts严格一致,应用仅监听http。

Go 应用在 Kubernetes 中启用 TLS,核心不是在 Go 代码里加证书逻辑,而是靠 Ingress + Secret + Controller 协同完成。直接在 http.ListenAndServe 里硬编码证书不仅无效,还会干扰 Ingress 的 TLS 终止机制。
创建 TLS Secret 时必须用 PEM 格式且顺序不能错
Secret 必须包含两个 key:tls.crt 和 tls.key,且内容必须是标准 PEM 块(以 -----BEGIN CERTIFICATE----- 开头,-----END CERTIFICATE----- 结尾)。
- 如果证书链不完整(比如缺中间 CA),浏览器或客户端会报
x509: certificate signed by unknown authority -
tls.crt文件里必须把 leaf 证书放最前面,中间证书跟在后面,根证书放最后;顺序反了 Nginx Ingress controller 会静默忽略中间证书 - 私钥不能加密(即不能有
DEK-Info行),否则 Ingress controller 启动失败,日志里出现failed to load X509 key pair - 用
kubectl create secret tls创建比手写 YAML 更安全,它会自动校验格式:kubectl create secret tls go-app-tls \ --cert=server.crt \ --key=server.key \ -n default
Ingress 资源里 host 和 tls.hosts 必须严格一致
Ingress 的 TLS 配置只匹配 spec.tls.hosts 字段,它和 spec.rules.host 是两个独立字段,但值必须完全相同,否则证书不会被加载。
- 例如你域名是
api.example.com,那么spec.tls.hosts和spec.rules.host都得写成api.example.com,写成*.example.com或漏掉都不行 - 多个域名共用一个 Secret 时,
spec.tls.hosts是字符串数组,每个 host 都要出现在该数组里,Ingress controller 才会把证书绑定到对应路由 - 如果用了 Let’s Encrypt 的 wildcard 证书,确保 DNS 解析已生效,否则 ACME 挑战失败,Ingress 日志里会出现
no object matching key类似提示
Go 应用本身只需监听 HTTP,别碰 TLS
Go 服务保持纯 HTTP 暴露(如 http.ListenAndServe(":8080", nil)),让 Ingress controller 做 TLS 终止。这是云原生部署的标准做法,也是最易维护的方式。
- 不要在 Go 里调用
http.ListenAndServeTLS,否则会和 Ingress 冲突,导致连接被重置或 400 错误 - 如果应用需要知道原始请求是 HTTPS(比如生成绝对 URL),通过
X-Forwarded-Proto: https头判断,而不是检查端口或 TLS 状态 - 健康检查探针(liveness/readiness)也走 HTTP,Ingress controller 会把 /healthz 这类路径正常转发,无需额外配置 TLS
- 若必须做 mTLS(如服务间双向认证),那是 Service Mesh(如 Istio)或自定义 sidecar 的职责,不属于 Ingress TLS 范畴
真正容易被忽略的是证书有效期和更新流程:Secret 不会自动轮转,Ingress controller 也不会主动 reload。证书快过期时,必须手动替换 Secret 并触发 rollout(比如 patch annotation 或重启 pod),否则到期后所有 HTTPS 请求直接失败——这个时间点往往没人盯着日志看。











