Kubernetes Ingress 用 TLS Secret 给预览域名接上 HTTPS

前言: 昨天给预览服务配好了 Ingress ,测试同学终于能用域名打开页面。今天他把地址从 http://preview.example.test 改成 https://preview.example.test,却遇到了证书提示。我第一反应是:规则里已经写了域名,入口应该知道怎么处理吧?翻了 Kubernetes Ingress 官方文档才发现,域名分流和 TLS 握手是两件事。于是我想弄清楚:没有给 Ingress 配证书时,HTTPS 卡在哪里?配上 TLS Secret 后,又有哪些边界不能忽略?

这篇接着上一篇的 preview 服务,只讲入口这一层的 HTTPS。证书签发、自动续期和控制器安装先不展开。

一. 域名能打开,不代表 HTTPS 已经好了

  1. 先把场景还原一下:同一命名空间里已经有 preview:80 这个 Service ,入口控制器也在运行。浏览器访问 http://preview.example.test 时,入口按 Ingress 的 host 和路径规则,把请求交给这个服务。这里解决的是"请求往哪儿走"。

  2. 换成 https://,浏览器会先和入口建立 TLS 连接,确认对方出示的证书能证明自己是 preview.example.test。握手发生在转发应用请求之前。如果入口没有适用的证书,或证书与域名不符,浏览器可能先报安全错误,后端 Pod 根本没有机会处理这次请求。具体错误页面取决于浏览器和入口控制器配置。

重点看两条路的起点:HTTPS 比 HTTP 多了入口出示证书这一步,原来的分流规则不会替它完成握手。

二. 我最初想把证书放到应用里

  1. 最直接的想法,是给 preview 容器装证书,让应用自己监听 HTTPS。单个服务这样做并非不行,但这篇的外部请求先到入口控制器。如果入口本来就负责接收浏览器连接,把证书只放在后端,不会自动让入口具备正确的证书。

  2. 稍微好一点,我想在 Ingress 文件里直接写证书内容。这样也很别扭:私钥会跟普通路由规则放在一起,配置文件很容易被复制到仓库。既然此前数据库密码已经用 Secret 单独交付,入口证书也需要一个单独的存放和引用位置。

尝试 谁拿到证书 对当前入口的影响
只放在应用容器 后端应用 入口的 TLS 握手仍要另行处理
直接写进路由文件 配置文件读者 私钥容易随规则扩散
入口引用 TLS Secret 入口控制器 可在入口完成浏览器这一段握手

图里重点看红色的入口:浏览器首先找的是入口,不能指望后端替它在更早的阶段出示证书。

三. 给入口一把对应域名的钥匙

  1. Kubernetes 的做法,是把证书和私钥放进类型为 kubernetes.io/tls 的 Secret ,再让 Ingress 的 tls.secretName 引用它。这里的 Secret 就像前台保管的门禁材料:访客还没被引导到具体部门,前台先证明这栋楼确实是访客要找的地方。rules.host 是后续分流时核对的收件地址,两处域名应对应同一个预览域名。

  2. 官方 TLS 配置说明明确写到,Ingress 在入口终止 TLS ,默认假设入口到 Service 与 Pod 这一段使用明文。也就是说,浏览器地址栏出现锁,不代表集群内部每一跳都加密了。要不要保护内部链路,需要结合环境和入口控制器能力单独设计。

text 复制代码
浏览器先确认入口出示的证书属于访问的域名
入口完成 TLS 握手,再按 Ingress 规则选择 Service
Service 把请求交给当前可用的 Pod

重点看绿色的握手边界:证书负责浏览器到入口这一段,路由仍由原来的 Ingress 规则完成。

四. 最小配置里,三个名字要对上

  1. 假设你已经有真实域名的证书文件 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
  1. 然后在上一篇的规则里补上 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
  1. 我会把三个位置连着检查:证书覆盖的域名、tls.hosts、rules.host。只改其中一个,可能造成握手证书不匹配,或握手完成后路由找不到后端。本文清单对照官方字段编写,没有在真实公网域名和入口控制器上完成端到端访问测试;不要把它当成已经验证过的线上配置。

这张图重点看三处都指向同一个域名;secretName 则把规则连接到实际证书材料。

五. 配上 TLS 后,先别急着宣布收工

  1. 证书存在,仍可能遇到浏览器警告。常见检查顺序是:域名是否真的到达预期入口,入口控制器是否接管这份 Ingress ,Secret 是否在同一命名空间,证书是否覆盖该域名、是否在有效期内。浏览器看到的证书也可能是控制器的默认证书,这时更要确认主机名和控制器归属,而不是先改后端代码。

  2. 若入口已经可达,可以用 curl -v https://preview.example.test/ 观察连接和证书信息,并在浏览器里检查实际出示的证书。不要用 -k 当作"修好了"的验证:它会跳过证书校验,只能帮助区分"连接能否建立"和"证书是否可信"。测试域名、DNS、证书信任链和入口暴露方式,都要按自己的环境准备。

  3. 回到前台类比:前台拿到了正确的门牌证明,访客才愿意进门;进门之后还要查接待表。TLS Secret 不会替你签发或自动续期证书,也不会让后端链路自动加密。这几个问题在真正对外开放前都值得单独确认。

图里按请求顺序排查;如果浏览器还没通过证书校验,就先别把问题归到 Service 或 Pod。

六. 总结:把"能到入口"和"信任入口"分开

  1. 昨天我们解决的是外部请求到达入口后,怎样按域名和路径找到 preview。今天补上的是更早的一步:浏览器能否信任这个入口。Ingress 引用同命名空间的 TLS Secret ,让入口拿到证书与私钥,在转发前处理浏览器这一段 TLS。

  2. 下次看到"HTTP 能打开、HTTPS 有警告",我会按下面的路径看,而不是直接去重启应用:

text 复制代码
域名是否到达预期入口
入口是否拿到覆盖该域名的有效证书
握手后是否匹配 Ingress 规则
Service 后面是否有可用 Pod

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

相关推荐
用户1494484813201 小时前
为什么大厂很少直接用 2PC/TCC?聊聊分布式事务在真实业务里的落地套路
分布式·后端
Thneonl1 小时前
采样采错地方,trace 全断链:OTel 尾部采样的代价账
后端·架构
匆匆那年随风1 小时前
零依赖 C# Office 库到底怎么用——四个场景讲透 Wisdom.Office
后端
今天早睡1 小时前
用子图封装流程,设计清晰的父子状态接口
后端
Lyy1 小时前
DevOps平台 — 第十七篇:测试管理的设计与实现
后端·devops
用户EasyAdminBlazor1 小时前
用 EasyAdminBlazor + OpenCode 开发进销存:实际做了什么,花了多久
后端
ByteRock1 小时前
同样是 Decimal,为什么 MySQL 和 ClickHouse 会写成两套世界
后端
leo在掘金1 小时前
一天155万亿Token,DeepInfer省在哪
后端·架构
阿良别做梦1 小时前
LangGraph 学习之路:让工作流返工,也让它及时停下
后端·开源