前言: 昨天给预览服务配好了 Ingress ,测试同学终于能用域名打开页面。今天他把地址从 http://preview.example.test 改成 https://preview.example.test,却遇到了证书提示。我第一反应是:规则里已经写了域名,入口应该知道怎么处理吧?翻了 Kubernetes Ingress 官方文档才发现,域名分流和 TLS 握手是两件事。于是我想弄清楚:没有给 Ingress 配证书时,HTTPS 卡在哪里?配上 TLS Secret 后,又有哪些边界不能忽略?
这篇接着上一篇的 preview 服务,只讲入口这一层的 HTTPS。证书签发、自动续期和控制器安装先不展开。
一. 域名能打开,不代表 HTTPS 已经好了
-
先把场景还原一下:同一命名空间里已经有
preview:80这个 Service ,入口控制器也在运行。浏览器访问http://preview.example.test时,入口按 Ingress 的host和路径规则,把请求交给这个服务。这里解决的是"请求往哪儿走"。 -
换成
https://,浏览器会先和入口建立 TLS 连接,确认对方出示的证书能证明自己是preview.example.test。握手发生在转发应用请求之前。如果入口没有适用的证书,或证书与域名不符,浏览器可能先报安全错误,后端 Pod 根本没有机会处理这次请求。具体错误页面取决于浏览器和入口控制器配置。

重点看两条路的起点:HTTPS 比 HTTP 多了入口出示证书这一步,原来的分流规则不会替它完成握手。
二. 我最初想把证书放到应用里
-
最直接的想法,是给
preview容器装证书,让应用自己监听 HTTPS。单个服务这样做并非不行,但这篇的外部请求先到入口控制器。如果入口本来就负责接收浏览器连接,把证书只放在后端,不会自动让入口具备正确的证书。 -
稍微好一点,我想在 Ingress 文件里直接写证书内容。这样也很别扭:私钥会跟普通路由规则放在一起,配置文件很容易被复制到仓库。既然此前数据库密码已经用 Secret 单独交付,入口证书也需要一个单独的存放和引用位置。
| 尝试 | 谁拿到证书 | 对当前入口的影响 |
|---|---|---|
| 只放在应用容器 | 后端应用 | 入口的 TLS 握手仍要另行处理 |
| 直接写进路由文件 | 配置文件读者 | 私钥容易随规则扩散 |
| 入口引用 TLS Secret | 入口控制器 | 可在入口完成浏览器这一段握手 |

图里重点看红色的入口:浏览器首先找的是入口,不能指望后端替它在更早的阶段出示证书。
三. 给入口一把对应域名的钥匙
-
Kubernetes 的做法,是把证书和私钥放进类型为
kubernetes.io/tls的 Secret ,再让 Ingress 的tls.secretName引用它。这里的 Secret 就像前台保管的门禁材料:访客还没被引导到具体部门,前台先证明这栋楼确实是访客要找的地方。rules.host是后续分流时核对的收件地址,两处域名应对应同一个预览域名。 -
官方 TLS 配置说明明确写到,Ingress 在入口终止 TLS ,默认假设入口到 Service 与 Pod 这一段使用明文。也就是说,浏览器地址栏出现锁,不代表集群内部每一跳都加密了。要不要保护内部链路,需要结合环境和入口控制器能力单独设计。
text
浏览器先确认入口出示的证书属于访问的域名
入口完成 TLS 握手,再按 Ingress 规则选择 Service
Service 把请求交给当前可用的 Pod

重点看绿色的握手边界:证书负责浏览器到入口这一段,路由仍由原来的 Ingress 规则完成。
四. 最小配置里,三个名字要对上
- 假设你已经有真实域名的证书文件
tls.crt和对应私钥tls.key。下面的命令按照 官方kubectl create secret tls语法创建 TLS Secret 。命令要在放置 Ingress 的命名空间执行;不要把私钥文件提交到仓库。证书签发过程不在本文范围内。
bash
kubectl -n preview-lab create secret tls preview-tls \
--cert=tls.crt \
--key=tls.key
- 然后在上一篇的规则里补上
tls。这里的example-class仍是占位值,必须替换为集群真实的 IngressClass ;同命名空间里也需要已有preview:80这个 Service 。preview.example.test是示例域名,不会因为提交清单就自动有公网解析。
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: preview
namespace: preview-lab
spec:
ingressClassName: example-class # !!! 注意:改成实际的 IngressClass
tls:
- hosts:
- preview.example.test # !!! 注意:证书必须覆盖这个域名
secretName: preview-tls # !!! 注意:Secret 在同一命名空间
rules:
- host: preview.example.test
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: preview
port:
number: 80
- 我会把三个位置连着检查:证书覆盖的域名、
tls.hosts、rules.host。只改其中一个,可能造成握手证书不匹配,或握手完成后路由找不到后端。本文清单对照官方字段编写,没有在真实公网域名和入口控制器上完成端到端访问测试;不要把它当成已经验证过的线上配置。

这张图重点看三处都指向同一个域名;secretName 则把规则连接到实际证书材料。
五. 配上 TLS 后,先别急着宣布收工
-
证书存在,仍可能遇到浏览器警告。常见检查顺序是:域名是否真的到达预期入口,入口控制器是否接管这份 Ingress ,Secret 是否在同一命名空间,证书是否覆盖该域名、是否在有效期内。浏览器看到的证书也可能是控制器的默认证书,这时更要确认主机名和控制器归属,而不是先改后端代码。
-
若入口已经可达,可以用
curl -v https://preview.example.test/观察连接和证书信息,并在浏览器里检查实际出示的证书。不要用-k当作"修好了"的验证:它会跳过证书校验,只能帮助区分"连接能否建立"和"证书是否可信"。测试域名、DNS、证书信任链和入口暴露方式,都要按自己的环境准备。 -
回到前台类比:前台拿到了正确的门牌证明,访客才愿意进门;进门之后还要查接待表。TLS Secret 不会替你签发或自动续期证书,也不会让后端链路自动加密。这几个问题在真正对外开放前都值得单独确认。

图里按请求顺序排查;如果浏览器还没通过证书校验,就先别把问题归到 Service 或 Pod。
六. 总结:把"能到入口"和"信任入口"分开
-
昨天我们解决的是外部请求到达入口后,怎样按域名和路径找到
preview。今天补上的是更早的一步:浏览器能否信任这个入口。Ingress 引用同命名空间的 TLS Secret ,让入口拿到证书与私钥,在转发前处理浏览器这一段 TLS。 -
下次看到"HTTP 能打开、HTTPS 有警告",我会按下面的路径看,而不是直接去重启应用:
text
域名是否到达预期入口
入口是否拿到覆盖该域名的有效证书
握手后是否匹配 Ingress 规则
Service 后面是否有可用 Pod

这张图把前台的工作拆开了:先证明身份,再查接待表,最后才把请求交给正在工作的服务实例。